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 attr attr
= {};
3067 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3069 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3070 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3071 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3075 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3079 if (bgp_input_modifier(
3080 peer
, rn_p
, &attr
, afi
, safi
,
3081 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3089 bgp_attr_undup(&attr
, ain
->attr
);
3096 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3100 iana_safi_t pkt_safi
;
3101 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3102 PEER_FLAG_MAX_PREFIX_FORCE
))
3103 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3104 + peer
->pcount
[afi
][safi
]
3105 : peer
->pcount
[afi
][safi
];
3107 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3110 if (pcount
> peer
->pmax
[afi
][safi
]) {
3111 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3112 PEER_STATUS_PREFIX_LIMIT
)
3117 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3118 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3119 peer
->pmax
[afi
][safi
]);
3120 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3122 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3123 PEER_FLAG_MAX_PREFIX_WARNING
))
3126 /* Convert AFI, SAFI to values for packet. */
3127 pkt_afi
= afi_int2iana(afi
);
3128 pkt_safi
= safi_int2iana(safi
);
3132 ndata
[0] = (pkt_afi
>> 8);
3134 ndata
[2] = pkt_safi
;
3135 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3136 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3137 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3138 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3140 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3141 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3142 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3146 /* Dynamic peers will just close their connection. */
3147 if (peer_dynamic_neighbor(peer
))
3150 /* restart timer start */
3151 if (peer
->pmax_restart
[afi
][safi
]) {
3152 peer
->v_pmax_restart
=
3153 peer
->pmax_restart
[afi
][safi
] * 60;
3155 if (bgp_debug_neighbor_events(peer
))
3157 "%s Maximum-prefix restart timer started for %d secs",
3158 peer
->host
, peer
->v_pmax_restart
);
3160 BGP_TIMER_ON(peer
->t_pmax_restart
,
3161 bgp_maximum_prefix_restart_timer
,
3162 peer
->v_pmax_restart
);
3167 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3168 PEER_STATUS_PREFIX_LIMIT
);
3170 if (pcount
> (pcount
* peer
->pmax_threshold
[afi
][safi
] / 100)) {
3171 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3172 PEER_STATUS_PREFIX_THRESHOLD
)
3177 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3178 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3179 peer
->pmax
[afi
][safi
]);
3180 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3181 PEER_STATUS_PREFIX_THRESHOLD
);
3183 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3184 PEER_STATUS_PREFIX_THRESHOLD
);
3188 /* Unconditionally remove the route from the RIB, without taking
3189 * damping into consideration (eg, because the session went down)
3191 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3192 struct peer
*peer
, afi_t afi
, safi_t safi
)
3195 struct bgp
*bgp
= NULL
;
3196 bool delete_route
= false;
3198 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3201 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3202 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3204 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3207 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3208 delete_route
= true;
3209 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3210 delete_route
= true;
3212 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3213 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3214 bgp
= pi
->peer
->bgp
;
3216 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3217 list_delete_node(bgp
->gr_info
[afi
][safi
]
3220 dest
->rt_node
= NULL
;
3226 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3227 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3230 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3231 struct peer
*peer
, afi_t afi
, safi_t safi
,
3232 struct prefix_rd
*prd
)
3234 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3236 /* apply dampening, if result is suppressed, we'll be retaining
3237 * the bgp_path_info in the RIB for historical reference.
3239 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3240 && peer
->sort
== BGP_PEER_EBGP
)
3241 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3242 == BGP_DAMP_SUPPRESSED
) {
3243 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3248 #ifdef ENABLE_BGP_VNC
3249 if (safi
== SAFI_MPLS_VPN
) {
3250 struct bgp_dest
*pdest
= NULL
;
3251 struct bgp_table
*table
= NULL
;
3253 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3254 (struct prefix
*)prd
);
3255 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3256 table
= bgp_dest_get_bgp_table_info(pdest
);
3258 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3259 peer
->bgp
, prd
, table
, p
, pi
);
3261 bgp_dest_unlock_node(pdest
);
3263 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3264 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3266 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3267 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3272 /* If this is an EVPN route, process for un-import. */
3273 if (safi
== SAFI_EVPN
)
3274 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3276 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3279 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3280 struct peer
*peer
, struct attr
*attr
,
3281 struct bgp_dest
*dest
)
3283 struct bgp_path_info
*new;
3285 /* Make new BGP info. */
3286 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3288 new->instance
= instance
;
3289 new->sub_type
= sub_type
;
3292 new->uptime
= bgp_clock();
3297 static void overlay_index_update(struct attr
*attr
,
3298 union gw_addr
*gw_ip
)
3302 if (gw_ip
== NULL
) {
3303 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3305 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3306 sizeof(union gw_addr
));
3310 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3311 union gw_addr
*gw_ip
)
3313 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3319 if (afi
!= AFI_L2VPN
)
3322 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3324 if (gw_ip
== NULL
) {
3325 memset(&temp
, 0, sizeof(temp
));
3326 path_gw_ip_remote
= &temp
.ip
;
3328 path_gw_ip_remote
= gw_ip
;
3330 return !!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3333 /* Check if received nexthop is valid or not. */
3334 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3335 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3336 struct bgp_dest
*dest
)
3339 bool is_bgp_static_route
=
3340 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3343 /* Only validated for unicast and multicast currently. */
3344 /* Also valid for EVPN where the nexthop is an IP address. */
3345 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3348 /* If NEXT_HOP is present, validate it. */
3349 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3350 if ((attr
->nexthop
.s_addr
== INADDR_ANY
&& !is_bgp_static_route
)
3351 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3352 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3356 /* If MP_NEXTHOP is present, validate it. */
3357 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3358 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3359 * it is not an IPv6 link-local address.
3361 * If we receive an UPDATE with nexthop length set to 32 bytes
3362 * we shouldn't discard an UPDATE if it's set to (::).
3363 * The link-local (2st) is validated along the code path later.
3365 if (attr
->mp_nexthop_len
) {
3366 switch (attr
->mp_nexthop_len
) {
3367 case BGP_ATTR_NHLEN_IPV4
:
3368 case BGP_ATTR_NHLEN_VPNV4
:
3369 ret
= ((attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3370 && !is_bgp_static_route
)
3372 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3373 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3377 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3378 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3379 ret
= ((IN6_IS_ADDR_UNSPECIFIED(
3380 &attr
->mp_nexthop_global
)
3381 && !is_bgp_static_route
)
3382 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3383 || IN6_IS_ADDR_MULTICAST(
3384 &attr
->mp_nexthop_global
)
3385 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3388 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3389 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3390 || IN6_IS_ADDR_MULTICAST(
3391 &attr
->mp_nexthop_global
)
3392 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3405 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3406 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3407 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3408 uint32_t num_labels
, int soft_reconfig
,
3409 struct bgp_route_evpn
*evpn
)
3412 int aspath_loop_count
= 0;
3413 struct bgp_dest
*dest
;
3415 struct attr new_attr
;
3416 struct attr
*attr_new
;
3417 struct bgp_path_info
*pi
;
3418 struct bgp_path_info
*new;
3419 struct bgp_path_info_extra
*extra
;
3421 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3423 int do_loop_check
= 1;
3424 int has_valid_label
= 0;
3426 uint8_t pi_type
= 0;
3427 uint8_t pi_sub_type
= 0;
3429 #ifdef ENABLE_BGP_VNC
3430 int vnc_implicit_withdraw
= 0;
3434 memset(&new_attr
, 0, sizeof(struct attr
));
3435 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3436 new_attr
.label
= MPLS_INVALID_LABEL
;
3439 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3440 /* TODO: Check to see if we can get rid of "is_valid_label" */
3441 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3442 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3444 has_valid_label
= bgp_is_valid_label(label
);
3446 /* When peer's soft reconfiguration enabled. Record input packet in
3449 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3450 && peer
!= bgp
->peer_self
)
3451 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3453 /* Check previously received route. */
3454 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3455 if (pi
->peer
== peer
&& pi
->type
== type
3456 && pi
->sub_type
== sub_type
3457 && pi
->addpath_rx_id
== addpath_id
)
3460 /* AS path local-as loop check. */
3461 if (peer
->change_local_as
) {
3462 if (peer
->allowas_in
[afi
][safi
])
3463 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3464 else if (!CHECK_FLAG(peer
->flags
,
3465 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3466 aspath_loop_count
= 1;
3468 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3469 > aspath_loop_count
) {
3470 peer
->stat_pfx_aspath_loop
++;
3471 reason
= "as-path contains our own AS A;";
3476 /* If the peer is configured for "allowas-in origin" and the last ASN in
3478 * as-path is our ASN then we do not need to call aspath_loop_check
3480 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3481 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3484 /* AS path loop check. */
3485 if (do_loop_check
) {
3486 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3487 > peer
->allowas_in
[afi
][safi
]
3488 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3489 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3490 > peer
->allowas_in
[afi
][safi
])) {
3491 peer
->stat_pfx_aspath_loop
++;
3492 reason
= "as-path contains our own AS;";
3497 /* Route reflector originator ID check. */
3498 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3499 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3500 peer
->stat_pfx_originator_loop
++;
3501 reason
= "originator is us;";
3505 /* Route reflector cluster ID check. */
3506 if (bgp_cluster_filter(peer
, attr
)) {
3507 peer
->stat_pfx_cluster_loop
++;
3508 reason
= "reflected from the same cluster;";
3512 /* Apply incoming filter. */
3513 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3514 peer
->stat_pfx_filter
++;
3519 /* RFC 8212 to prevent route leaks.
3520 * This specification intends to improve this situation by requiring the
3521 * explicit configuration of both BGP Import and Export Policies for any
3522 * External BGP (EBGP) session such as customers, peers, or
3523 * confederation boundaries for all enabled address families. Through
3524 * codification of the aforementioned requirement, operators will
3525 * benefit from consistent behavior across different BGP
3528 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3529 if (!bgp_inbound_policy_exists(peer
,
3530 &peer
->filter
[afi
][safi
])) {
3531 reason
= "inbound policy missing";
3535 /* draft-ietf-idr-deprecate-as-set-confed-set
3536 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3537 * Eventually, This document (if approved) updates RFC 4271
3538 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3539 * and obsoletes RFC 6472.
3541 if (peer
->bgp
->reject_as_sets
)
3542 if (aspath_check_as_sets(attr
->aspath
)) {
3544 "as-path contains AS_SET or AS_CONFED_SET type;";
3550 /* Apply incoming route-map.
3551 * NB: new_attr may now contain newly allocated values from route-map
3553 * commands, so we need bgp_attr_flush in the error paths, until we
3555 * the attr (which takes over the memory references) */
3556 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3559 peer
->stat_pfx_filter
++;
3560 reason
= "route-map;";
3561 bgp_attr_flush(&new_attr
);
3565 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3566 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3567 /* remove from RIB previous entry */
3568 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3571 if (peer
->sort
== BGP_PEER_EBGP
) {
3573 /* If we receive the graceful-shutdown community from an eBGP
3574 * peer we must lower local-preference */
3575 if (new_attr
.community
3576 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3577 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3578 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3580 /* If graceful-shutdown is configured then add the GSHUT
3581 * community to all paths received from eBGP peers */
3582 } else if (CHECK_FLAG(peer
->bgp
->flags
,
3583 BGP_FLAG_GRACEFUL_SHUTDOWN
))
3584 bgp_attr_add_gshut_community(&new_attr
);
3589 pi_sub_type
= pi
->sub_type
;
3592 /* next hop check. */
3593 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3594 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3596 peer
->stat_pfx_nh_invalid
++;
3597 reason
= "martian or self next-hop;";
3598 bgp_attr_flush(&new_attr
);
3602 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3603 peer
->stat_pfx_nh_invalid
++;
3604 reason
= "self mac;";
3608 /* Update Overlay Index */
3609 if (afi
== AFI_L2VPN
) {
3610 overlay_index_update(&new_attr
,
3611 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3614 attr_new
= bgp_attr_intern(&new_attr
);
3616 /* If maximum prefix count is configured and current prefix
3619 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3622 /* If the update is implicit withdraw. */
3624 pi
->uptime
= bgp_clock();
3625 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3627 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3629 /* Same attribute comes in. */
3630 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3631 && attrhash_cmp(pi
->attr
, attr_new
)
3632 && (!has_valid_label
3633 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3634 num_labels
* sizeof(mpls_label_t
))
3636 && (overlay_index_equal(
3638 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3639 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3640 BGP_CONFIG_DAMPENING
)
3641 && peer
->sort
== BGP_PEER_EBGP
3642 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3643 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3644 bgp_debug_rdpfxpath2str(
3645 afi
, safi
, prd
, p
, label
,
3646 num_labels
, addpath_id
? 1 : 0,
3647 addpath_id
, pfx_buf
,
3649 zlog_debug("%s rcvd %s", peer
->host
,
3653 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3654 != BGP_DAMP_SUPPRESSED
) {
3655 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3657 bgp_process(bgp
, dest
, afi
, safi
);
3659 } else /* Duplicate - odd */
3661 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3662 if (!peer
->rcvd_attr_printed
) {
3664 "%s rcvd UPDATE w/ attr: %s",
3666 peer
->rcvd_attr_str
);
3667 peer
->rcvd_attr_printed
= 1;
3670 bgp_debug_rdpfxpath2str(
3671 afi
, safi
, prd
, p
, label
,
3672 num_labels
, addpath_id
? 1 : 0,
3673 addpath_id
, pfx_buf
,
3676 "%s rcvd %s...duplicate ignored",
3677 peer
->host
, pfx_buf
);
3680 /* graceful restart STALE flag unset. */
3681 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3682 bgp_path_info_unset_flag(
3683 dest
, pi
, BGP_PATH_STALE
);
3684 bgp_dest_set_defer_flag(dest
, false);
3685 bgp_process(bgp
, dest
, afi
, safi
);
3689 bgp_dest_unlock_node(dest
);
3690 bgp_attr_unintern(&attr_new
);
3695 /* Withdraw/Announce before we fully processed the withdraw */
3696 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3697 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3698 bgp_debug_rdpfxpath2str(
3699 afi
, safi
, prd
, p
, label
, num_labels
,
3700 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3703 "%s rcvd %s, flapped quicker than processing",
3704 peer
->host
, pfx_buf
);
3707 bgp_path_info_restore(dest
, pi
);
3710 /* Received Logging. */
3711 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3712 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3713 num_labels
, addpath_id
? 1 : 0,
3714 addpath_id
, pfx_buf
,
3716 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3719 /* graceful restart STALE flag unset. */
3720 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3721 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3722 bgp_dest_set_defer_flag(dest
, false);
3725 /* The attribute is changed. */
3726 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3728 /* implicit withdraw, decrement aggregate and pcount here.
3729 * only if update is accepted, they'll increment below.
3731 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3733 /* Update bgp route dampening information. */
3734 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3735 && peer
->sort
== BGP_PEER_EBGP
) {
3736 /* This is implicit withdraw so we should update
3739 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3740 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3742 #ifdef ENABLE_BGP_VNC
3743 if (safi
== SAFI_MPLS_VPN
) {
3744 struct bgp_dest
*pdest
= NULL
;
3745 struct bgp_table
*table
= NULL
;
3747 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3748 (struct prefix
*)prd
);
3749 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3750 table
= bgp_dest_get_bgp_table_info(pdest
);
3752 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3753 bgp
, prd
, table
, p
, pi
);
3755 bgp_dest_unlock_node(pdest
);
3757 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3758 && (safi
== SAFI_UNICAST
)) {
3759 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3761 * Implicit withdraw case.
3763 ++vnc_implicit_withdraw
;
3764 vnc_import_bgp_del_route(bgp
, p
, pi
);
3765 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3770 /* Special handling for EVPN update of an existing route. If the
3771 * extended community attribute has changed, we need to
3773 * the route using its existing extended community. It will be
3774 * subsequently processed for import with the new extended
3777 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3780 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3782 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3785 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3786 attr_new
->ecommunity
);
3788 if (bgp_debug_update(peer
, p
, NULL
, 1))
3790 "Change in EXT-COMM, existing %s new %s",
3792 pi
->attr
->ecommunity
),
3794 attr_new
->ecommunity
));
3795 if (safi
== SAFI_EVPN
)
3796 bgp_evpn_unimport_route(
3797 bgp
, afi
, safi
, p
, pi
);
3798 else /* SAFI_MPLS_VPN */
3799 vpn_leak_to_vrf_withdraw(bgp
,
3805 /* Update to new attribute. */
3806 bgp_attr_unintern(&pi
->attr
);
3807 pi
->attr
= attr_new
;
3809 /* Update MPLS label */
3810 if (has_valid_label
) {
3811 extra
= bgp_path_info_extra_get(pi
);
3812 if (extra
->label
!= label
) {
3813 memcpy(&extra
->label
, label
,
3814 num_labels
* sizeof(mpls_label_t
));
3815 extra
->num_labels
= num_labels
;
3817 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3818 bgp_set_valid_label(&extra
->label
[0]);
3821 /* Update SRv6 SID */
3822 if (attr
->srv6_l3vpn
) {
3823 extra
= bgp_path_info_extra_get(pi
);
3824 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3825 sid_copy(&extra
->sid
[0],
3826 &attr
->srv6_l3vpn
->sid
);
3827 extra
->num_sids
= 1;
3829 } else if (attr
->srv6_vpn
) {
3830 extra
= bgp_path_info_extra_get(pi
);
3831 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3832 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3833 extra
->num_sids
= 1;
3837 #ifdef ENABLE_BGP_VNC
3838 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3839 && (safi
== SAFI_UNICAST
)) {
3840 if (vnc_implicit_withdraw
) {
3842 * Add back the route with its new attributes
3844 * The route is still selected, until the route
3846 * queued by bgp_process actually runs. We have
3848 * update to the VNC side immediately to avoid
3850 * configuration changes (e.g., route-map
3852 * trigger re-importation of the entire RIB.
3854 vnc_import_bgp_add_route(bgp
, p
, pi
);
3855 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3860 /* Update bgp route dampening information. */
3861 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3862 && peer
->sort
== BGP_PEER_EBGP
) {
3863 /* Now we do normal update dampening. */
3864 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
3865 if (ret
== BGP_DAMP_SUPPRESSED
) {
3866 bgp_dest_unlock_node(dest
);
3871 /* Nexthop reachability check - for unicast and
3872 * labeled-unicast.. */
3873 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3874 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3875 || (safi
== SAFI_EVPN
&&
3876 bgp_evpn_is_prefix_nht_supported(p
))) {
3877 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3878 && peer
->ttl
== BGP_DEFAULT_TTL
3879 && !CHECK_FLAG(peer
->flags
,
3880 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3881 && !CHECK_FLAG(bgp
->flags
,
3882 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3887 struct bgp
*bgp_nexthop
= bgp
;
3889 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3890 bgp_nexthop
= pi
->extra
->bgp_orig
;
3892 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3894 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3895 pi
, NULL
, connected
)
3896 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3897 bgp_path_info_set_flag(dest
, pi
,
3900 if (BGP_DEBUG(nht
, NHT
)) {
3901 zlog_debug("%s(%pI4): NH unresolved",
3903 (in_addr_t
*)&attr_new
->nexthop
);
3905 bgp_path_info_unset_flag(dest
, pi
,
3909 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
3911 #ifdef ENABLE_BGP_VNC
3912 if (safi
== SAFI_MPLS_VPN
) {
3913 struct bgp_dest
*pdest
= NULL
;
3914 struct bgp_table
*table
= NULL
;
3916 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3917 (struct prefix
*)prd
);
3918 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3919 table
= bgp_dest_get_bgp_table_info(pdest
);
3921 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3922 bgp
, prd
, table
, p
, pi
);
3924 bgp_dest_unlock_node(pdest
);
3928 /* If this is an EVPN route and some attribute has changed,
3930 * route for import. If the extended community has changed, we
3932 * have done the un-import earlier and the import would result
3934 * route getting injected into appropriate L2 VNIs. If it is
3936 * some other attribute change, the import will result in
3938 * the attributes for the route in the VNI(s).
3940 if (safi
== SAFI_EVPN
&& !same_attr
&&
3941 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3942 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3944 /* Process change. */
3945 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3947 bgp_process(bgp
, dest
, afi
, safi
);
3948 bgp_dest_unlock_node(dest
);
3950 if (SAFI_UNICAST
== safi
3951 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3952 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3954 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3956 if ((SAFI_MPLS_VPN
== safi
)
3957 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3959 vpn_leak_to_vrf_update(bgp
, pi
);
3962 #ifdef ENABLE_BGP_VNC
3963 if (SAFI_MPLS_VPN
== safi
) {
3964 mpls_label_t label_decoded
= decode_label(label
);
3966 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3967 type
, sub_type
, &label_decoded
);
3969 if (SAFI_ENCAP
== safi
) {
3970 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3971 type
, sub_type
, NULL
);
3976 } // End of implicit withdraw
3978 /* Received Logging. */
3979 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3980 if (!peer
->rcvd_attr_printed
) {
3981 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3982 peer
->rcvd_attr_str
);
3983 peer
->rcvd_attr_printed
= 1;
3986 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3987 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3989 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3992 /* Make new BGP info. */
3993 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
3995 /* Update MPLS label */
3996 if (has_valid_label
) {
3997 extra
= bgp_path_info_extra_get(new);
3998 if (extra
->label
!= label
) {
3999 memcpy(&extra
->label
, label
,
4000 num_labels
* sizeof(mpls_label_t
));
4001 extra
->num_labels
= num_labels
;
4003 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4004 bgp_set_valid_label(&extra
->label
[0]);
4007 /* Update SRv6 SID */
4008 if (safi
== SAFI_MPLS_VPN
) {
4009 extra
= bgp_path_info_extra_get(new);
4010 if (attr
->srv6_l3vpn
) {
4011 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4012 extra
->num_sids
= 1;
4013 } else if (attr
->srv6_vpn
) {
4014 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4015 extra
->num_sids
= 1;
4019 /* Update Overlay Index */
4020 if (afi
== AFI_L2VPN
) {
4021 overlay_index_update(new->attr
,
4022 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4024 /* Nexthop reachability check. */
4025 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4026 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4027 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4028 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4029 && peer
->ttl
== BGP_DEFAULT_TTL
4030 && !CHECK_FLAG(peer
->flags
,
4031 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4032 && !CHECK_FLAG(bgp
->flags
,
4033 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4038 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4040 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
4042 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4043 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4045 if (BGP_DEBUG(nht
, NHT
)) {
4046 char buf1
[INET6_ADDRSTRLEN
];
4048 (const void *)&attr_new
->nexthop
,
4049 buf1
, INET6_ADDRSTRLEN
);
4050 zlog_debug("%s(%s): NH unresolved", __func__
,
4053 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4056 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4059 new->addpath_rx_id
= addpath_id
;
4061 /* Increment prefix */
4062 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4064 /* Register new BGP information. */
4065 bgp_path_info_add(dest
, new);
4067 /* route_node_get lock */
4068 bgp_dest_unlock_node(dest
);
4070 #ifdef ENABLE_BGP_VNC
4071 if (safi
== SAFI_MPLS_VPN
) {
4072 struct bgp_dest
*pdest
= NULL
;
4073 struct bgp_table
*table
= NULL
;
4075 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4076 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4077 table
= bgp_dest_get_bgp_table_info(pdest
);
4079 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4080 bgp
, prd
, table
, p
, new);
4082 bgp_dest_unlock_node(pdest
);
4086 /* If this is an EVPN route, process for import. */
4087 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4088 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4090 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4092 /* Process change. */
4093 bgp_process(bgp
, dest
, afi
, safi
);
4095 if (SAFI_UNICAST
== safi
4096 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4097 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4098 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4100 if ((SAFI_MPLS_VPN
== safi
)
4101 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4103 vpn_leak_to_vrf_update(bgp
, new);
4105 #ifdef ENABLE_BGP_VNC
4106 if (SAFI_MPLS_VPN
== safi
) {
4107 mpls_label_t label_decoded
= decode_label(label
);
4109 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4110 sub_type
, &label_decoded
);
4112 if (SAFI_ENCAP
== safi
) {
4113 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4120 /* This BGP update is filtered. Log the reason then update BGP
4123 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4125 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4126 if (!peer
->rcvd_attr_printed
) {
4127 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4128 peer
->rcvd_attr_str
);
4129 peer
->rcvd_attr_printed
= 1;
4132 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4133 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4135 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4136 peer
->host
, pfx_buf
, reason
);
4140 /* If this is an EVPN route, un-import it as it is now filtered.
4142 if (safi
== SAFI_EVPN
)
4143 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4145 if (SAFI_UNICAST
== safi
4146 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4147 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4149 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4151 if ((SAFI_MPLS_VPN
== safi
)
4152 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4154 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4157 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4160 bgp_dest_unlock_node(dest
);
4162 #ifdef ENABLE_BGP_VNC
4164 * Filtered update is treated as an implicit withdrawal (see
4166 * a few lines above)
4168 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4169 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4177 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4178 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4179 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4180 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4183 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4184 struct bgp_dest
*dest
;
4185 struct bgp_path_info
*pi
;
4187 #ifdef ENABLE_BGP_VNC
4188 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4189 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4197 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4199 /* If peer is soft reconfiguration enabled. Record input packet for
4200 * further calculation.
4202 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4203 * routes that are filtered. This tanks out Quagga RS pretty badly due
4205 * the iteration over all RS clients.
4206 * Since we need to remove the entry from adj_in anyway, do that first
4208 * if there was no entry, we don't need to do anything more.
4210 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4211 && peer
!= bgp
->peer_self
)
4212 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4213 peer
->stat_pfx_dup_withdraw
++;
4215 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4216 bgp_debug_rdpfxpath2str(
4217 afi
, safi
, prd
, p
, label
, num_labels
,
4218 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4221 "%s withdrawing route %s not in adj-in",
4222 peer
->host
, pfx_buf
);
4224 bgp_dest_unlock_node(dest
);
4228 /* Lookup withdrawn route. */
4229 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4230 if (pi
->peer
== peer
&& pi
->type
== type
4231 && pi
->sub_type
== sub_type
4232 && pi
->addpath_rx_id
== addpath_id
)
4236 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4237 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4238 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4240 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4244 /* Withdraw specified route from routing table. */
4245 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4246 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4247 if (SAFI_UNICAST
== safi
4248 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4249 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4250 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4252 if ((SAFI_MPLS_VPN
== safi
)
4253 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4255 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4257 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4258 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4259 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4261 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4264 /* Unlock bgp_node_get() lock. */
4265 bgp_dest_unlock_node(dest
);
4270 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4273 struct update_subgroup
*subgrp
;
4274 subgrp
= peer_subgroup(peer
, afi
, safi
);
4275 subgroup_default_originate(subgrp
, withdraw
);
4280 * bgp_stop_announce_route_timer
4282 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4284 if (!paf
->t_announce_route
)
4287 THREAD_TIMER_OFF(paf
->t_announce_route
);
4291 * bgp_announce_route_timer_expired
4293 * Callback that is invoked when the route announcement timer for a
4296 static int bgp_announce_route_timer_expired(struct thread
*t
)
4298 struct peer_af
*paf
;
4301 paf
= THREAD_ARG(t
);
4304 if (peer
->status
!= Established
)
4307 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4310 peer_af_announce_route(paf
, 1);
4315 * bgp_announce_route
4317 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4319 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4321 struct peer_af
*paf
;
4322 struct update_subgroup
*subgrp
;
4324 paf
= peer_af_find(peer
, afi
, safi
);
4327 subgrp
= PAF_SUBGRP(paf
);
4330 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4331 * or a refresh has already been triggered.
4333 if (!subgrp
|| paf
->t_announce_route
)
4337 * Start a timer to stagger/delay the announce. This serves
4338 * two purposes - announcement can potentially be combined for
4339 * multiple peers and the announcement doesn't happen in the
4342 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4343 (subgrp
->peer_count
== 1)
4344 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4345 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4346 &paf
->t_announce_route
);
4350 * Announce routes from all AF tables to a peer.
4352 * This should ONLY be called when there is a need to refresh the
4353 * routes to the peer based on a policy change for this peer alone
4354 * or a route refresh request received from the peer.
4355 * The operation will result in splitting the peer from its existing
4356 * subgroups and putting it in new subgroups.
4358 void bgp_announce_route_all(struct peer
*peer
)
4363 FOREACH_AFI_SAFI (afi
, safi
)
4364 bgp_announce_route(peer
, afi
, safi
);
4367 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4368 struct bgp_table
*table
,
4369 struct prefix_rd
*prd
)
4372 struct bgp_dest
*dest
;
4373 struct bgp_adj_in
*ain
;
4376 table
= peer
->bgp
->rib
[afi
][safi
];
4378 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4379 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4380 if (ain
->peer
!= peer
)
4383 struct bgp_path_info
*pi
;
4384 uint32_t num_labels
= 0;
4385 mpls_label_t
*label_pnt
= NULL
;
4386 struct bgp_route_evpn evpn
;
4388 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4390 if (pi
->peer
== peer
)
4393 if (pi
&& pi
->extra
)
4394 num_labels
= pi
->extra
->num_labels
;
4396 label_pnt
= &pi
->extra
->label
[0];
4398 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4401 memset(&evpn
, 0, sizeof(evpn
));
4403 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4404 ain
->addpath_rx_id
, ain
->attr
, afi
,
4405 safi
, ZEBRA_ROUTE_BGP
,
4406 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4407 num_labels
, 1, &evpn
);
4410 bgp_dest_unlock_node(dest
);
4416 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4418 struct bgp_dest
*dest
;
4419 struct bgp_table
*table
;
4421 if (peer
->status
!= Established
)
4424 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4425 && (safi
!= SAFI_EVPN
))
4426 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4428 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4429 dest
= bgp_route_next(dest
)) {
4430 table
= bgp_dest_get_bgp_table_info(dest
);
4435 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4436 struct prefix_rd prd
;
4438 prd
.family
= AF_UNSPEC
;
4440 memcpy(&prd
.val
, p
->u
.val
, 8);
4442 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4447 struct bgp_clear_node_queue
{
4448 struct bgp_dest
*dest
;
4451 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4453 struct bgp_clear_node_queue
*cnq
= data
;
4454 struct bgp_dest
*dest
= cnq
->dest
;
4455 struct peer
*peer
= wq
->spec
.data
;
4456 struct bgp_path_info
*pi
;
4458 afi_t afi
= bgp_dest_table(dest
)->afi
;
4459 safi_t safi
= bgp_dest_table(dest
)->safi
;
4461 assert(dest
&& peer
);
4464 /* It is possible that we have multiple paths for a prefix from a peer
4465 * if that peer is using AddPath.
4467 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4468 if (pi
->peer
!= peer
)
4471 /* graceful restart STALE flag set. */
4472 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4473 && peer
->nsf
[afi
][safi
]
4474 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4475 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4476 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4478 /* If this is an EVPN route, process for
4480 if (safi
== SAFI_EVPN
)
4481 bgp_evpn_unimport_route(
4483 bgp_dest_get_prefix(dest
), pi
);
4484 /* Handle withdraw for VRF route-leaking and L3VPN */
4485 if (SAFI_UNICAST
== safi
4486 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4487 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4488 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4491 if (SAFI_MPLS_VPN
== safi
&&
4492 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4493 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4496 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4502 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4504 struct bgp_clear_node_queue
*cnq
= data
;
4505 struct bgp_dest
*dest
= cnq
->dest
;
4506 struct bgp_table
*table
= bgp_dest_table(dest
);
4508 bgp_dest_unlock_node(dest
);
4509 bgp_table_unlock(table
);
4510 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4513 static void bgp_clear_node_complete(struct work_queue
*wq
)
4515 struct peer
*peer
= wq
->spec
.data
;
4517 /* Tickle FSM to start moving again */
4518 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4520 peer_unlock(peer
); /* bgp_clear_route */
4523 static void bgp_clear_node_queue_init(struct peer
*peer
)
4525 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4527 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4528 #undef CLEAR_QUEUE_NAME_LEN
4530 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4531 peer
->clear_node_queue
->spec
.hold
= 10;
4532 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4533 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4534 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4535 peer
->clear_node_queue
->spec
.max_retries
= 0;
4537 /* we only 'lock' this peer reference when the queue is actually active
4539 peer
->clear_node_queue
->spec
.data
= peer
;
4542 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4543 struct bgp_table
*table
)
4545 struct bgp_dest
*dest
;
4546 int force
= bm
->process_main_queue
? 0 : 1;
4549 table
= peer
->bgp
->rib
[afi
][safi
];
4551 /* If still no table => afi/safi isn't configured at all or smth. */
4555 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4556 struct bgp_path_info
*pi
, *next
;
4557 struct bgp_adj_in
*ain
;
4558 struct bgp_adj_in
*ain_next
;
4560 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4561 * queued for every clearing peer, regardless of whether it is
4562 * relevant to the peer at hand.
4564 * Overview: There are 3 different indices which need to be
4565 * scrubbed, potentially, when a peer is removed:
4567 * 1 peer's routes visible via the RIB (ie accepted routes)
4568 * 2 peer's routes visible by the (optional) peer's adj-in index
4569 * 3 other routes visible by the peer's adj-out index
4571 * 3 there is no hurry in scrubbing, once the struct peer is
4572 * removed from bgp->peer, we could just GC such deleted peer's
4573 * adj-outs at our leisure.
4575 * 1 and 2 must be 'scrubbed' in some way, at least made
4576 * invisible via RIB index before peer session is allowed to be
4577 * brought back up. So one needs to know when such a 'search' is
4582 * - there'd be a single global queue or a single RIB walker
4583 * - rather than tracking which route_nodes still need to be
4584 * examined on a peer basis, we'd track which peers still
4587 * Given that our per-peer prefix-counts now should be reliable,
4588 * this may actually be achievable. It doesn't seem to be a huge
4589 * problem at this time,
4591 * It is possible that we have multiple paths for a prefix from
4593 * if that peer is using AddPath.
4597 ain_next
= ain
->next
;
4599 if (ain
->peer
== peer
) {
4600 bgp_adj_in_remove(dest
, ain
);
4601 bgp_dest_unlock_node(dest
);
4607 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4609 if (pi
->peer
!= peer
)
4613 bgp_path_info_reap(dest
, pi
);
4615 struct bgp_clear_node_queue
*cnq
;
4617 /* both unlocked in bgp_clear_node_queue_del */
4618 bgp_table_lock(bgp_dest_table(dest
));
4619 bgp_dest_lock_node(dest
);
4621 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4622 sizeof(struct bgp_clear_node_queue
));
4624 work_queue_add(peer
->clear_node_queue
, cnq
);
4632 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4634 struct bgp_dest
*dest
;
4635 struct bgp_table
*table
;
4637 if (peer
->clear_node_queue
== NULL
)
4638 bgp_clear_node_queue_init(peer
);
4640 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4641 * Idle until it receives a Clearing_Completed event. This protects
4642 * against peers which flap faster than we can we clear, which could
4645 * a) race with routes from the new session being installed before
4646 * clear_route_node visits the node (to delete the route of that
4648 * b) resource exhaustion, clear_route_node likely leads to an entry
4649 * on the process_main queue. Fast-flapping could cause that queue
4653 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4654 * the unlock will happen upon work-queue completion; other wise, the
4655 * unlock happens at the end of this function.
4657 if (!peer
->clear_node_queue
->thread
)
4660 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4661 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4663 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4664 dest
= bgp_route_next(dest
)) {
4665 table
= bgp_dest_get_bgp_table_info(dest
);
4669 bgp_clear_route_table(peer
, afi
, safi
, table
);
4672 /* unlock if no nodes got added to the clear-node-queue. */
4673 if (!peer
->clear_node_queue
->thread
)
4677 void bgp_clear_route_all(struct peer
*peer
)
4682 FOREACH_AFI_SAFI (afi
, safi
)
4683 bgp_clear_route(peer
, afi
, safi
);
4685 #ifdef ENABLE_BGP_VNC
4686 rfapiProcessPeerDown(peer
);
4690 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4692 struct bgp_table
*table
;
4693 struct bgp_dest
*dest
;
4694 struct bgp_adj_in
*ain
;
4695 struct bgp_adj_in
*ain_next
;
4697 table
= peer
->bgp
->rib
[afi
][safi
];
4699 /* It is possible that we have multiple paths for a prefix from a peer
4700 * if that peer is using AddPath.
4702 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4706 ain_next
= ain
->next
;
4708 if (ain
->peer
== peer
) {
4709 bgp_adj_in_remove(dest
, ain
);
4710 bgp_dest_unlock_node(dest
);
4718 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4720 struct bgp_dest
*dest
;
4721 struct bgp_path_info
*pi
;
4722 struct bgp_table
*table
;
4724 if (safi
== SAFI_MPLS_VPN
) {
4725 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4726 dest
= bgp_route_next(dest
)) {
4727 struct bgp_dest
*rm
;
4729 /* look for neighbor in tables */
4730 table
= bgp_dest_get_bgp_table_info(dest
);
4734 for (rm
= bgp_table_top(table
); rm
;
4735 rm
= bgp_route_next(rm
))
4736 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4738 if (pi
->peer
!= peer
)
4740 if (!CHECK_FLAG(pi
->flags
,
4744 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4749 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4750 dest
= bgp_route_next(dest
))
4751 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4753 if (pi
->peer
!= peer
)
4755 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4757 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4763 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4765 if (peer
->sort
== BGP_PEER_IBGP
)
4768 if (peer
->sort
== BGP_PEER_EBGP
4769 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4770 || FILTER_LIST_OUT_NAME(filter
)
4771 || DISTRIBUTE_OUT_NAME(filter
)))
4776 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4778 if (peer
->sort
== BGP_PEER_IBGP
)
4781 if (peer
->sort
== BGP_PEER_EBGP
4782 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4783 || FILTER_LIST_IN_NAME(filter
)
4784 || DISTRIBUTE_IN_NAME(filter
)))
4789 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4792 struct bgp_dest
*dest
;
4793 struct bgp_path_info
*pi
;
4794 struct bgp_path_info
*next
;
4796 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4797 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4798 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4802 /* Unimport EVPN routes from VRFs */
4803 if (safi
== SAFI_EVPN
)
4804 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4807 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4808 && pi
->type
== ZEBRA_ROUTE_BGP
4809 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4810 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4811 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4813 if (bgp_fibupd_safi(safi
))
4814 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4817 bgp_path_info_reap(dest
, pi
);
4821 /* Delete all kernel routes. */
4822 void bgp_cleanup_routes(struct bgp
*bgp
)
4825 struct bgp_dest
*dest
;
4826 struct bgp_table
*table
;
4828 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4829 if (afi
== AFI_L2VPN
)
4831 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4834 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4836 if (afi
!= AFI_L2VPN
) {
4838 safi
= SAFI_MPLS_VPN
;
4839 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4840 dest
= bgp_route_next(dest
)) {
4841 table
= bgp_dest_get_bgp_table_info(dest
);
4842 if (table
!= NULL
) {
4843 bgp_cleanup_table(bgp
, table
, safi
);
4844 bgp_table_finish(&table
);
4845 bgp_dest_set_bgp_table_info(dest
, NULL
);
4846 bgp_dest_unlock_node(dest
);
4850 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4851 dest
= bgp_route_next(dest
)) {
4852 table
= bgp_dest_get_bgp_table_info(dest
);
4853 if (table
!= NULL
) {
4854 bgp_cleanup_table(bgp
, table
, safi
);
4855 bgp_table_finish(&table
);
4856 bgp_dest_set_bgp_table_info(dest
, NULL
);
4857 bgp_dest_unlock_node(dest
);
4862 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
4863 dest
= bgp_route_next(dest
)) {
4864 table
= bgp_dest_get_bgp_table_info(dest
);
4865 if (table
!= NULL
) {
4866 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4867 bgp_table_finish(&table
);
4868 bgp_dest_set_bgp_table_info(dest
, NULL
);
4869 bgp_dest_unlock_node(dest
);
4874 void bgp_reset(void)
4877 bgp_zclient_reset();
4878 access_list_reset();
4879 prefix_list_reset();
4882 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4884 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4885 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4886 PEER_CAP_ADDPATH_AF_TX_RCV
));
4889 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4891 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4892 struct bgp_nlri
*packet
)
4901 int addpath_encoded
;
4902 uint32_t addpath_id
;
4905 lim
= pnt
+ packet
->length
;
4907 safi
= packet
->safi
;
4909 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4911 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4912 syntactic validity. If the field is syntactically incorrect,
4913 then the Error Subcode is set to Invalid Network Field. */
4914 for (; pnt
< lim
; pnt
+= psize
) {
4915 /* Clear prefix structure. */
4916 memset(&p
, 0, sizeof(struct prefix
));
4918 if (addpath_encoded
) {
4920 /* When packet overflow occurs return immediately. */
4921 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4922 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4924 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4925 addpath_id
= ntohl(addpath_id
);
4926 pnt
+= BGP_ADDPATH_ID_LEN
;
4929 /* Fetch prefix length. */
4930 p
.prefixlen
= *pnt
++;
4931 /* afi/safi validity already verified by caller,
4932 * bgp_update_receive */
4933 p
.family
= afi2family(afi
);
4935 /* Prefix length check. */
4936 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4939 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4940 peer
->host
, p
.prefixlen
, packet
->afi
);
4941 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4944 /* Packet size overflow check. */
4945 psize
= PSIZE(p
.prefixlen
);
4947 /* When packet overflow occur return immediately. */
4948 if (pnt
+ psize
> lim
) {
4951 "%s [Error] Update packet error (prefix length %d overflows packet)",
4952 peer
->host
, p
.prefixlen
);
4953 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4956 /* Defensive coding, double-check the psize fits in a struct
4958 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4961 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4962 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4963 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4966 /* Fetch prefix from NLRI packet. */
4967 memcpy(p
.u
.val
, pnt
, psize
);
4969 /* Check address. */
4970 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4971 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4972 /* From RFC4271 Section 6.3:
4974 * If a prefix in the NLRI field is semantically
4976 * (e.g., an unexpected multicast IP address),
4978 * be logged locally, and the prefix SHOULD be
4983 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4984 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4989 /* Check address. */
4990 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4991 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4996 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4998 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5003 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5008 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5010 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5017 /* Normal process. */
5019 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5020 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5021 NULL
, NULL
, 0, 0, NULL
);
5023 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5024 safi
, ZEBRA_ROUTE_BGP
,
5025 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5028 /* Do not send BGP notification twice when maximum-prefix count
5030 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5031 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5033 /* Address family configuration mismatch. */
5035 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5038 /* Packet length consistency check. */
5042 "%s [Error] Update packet error (prefix length mismatch with total length)",
5044 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5047 return BGP_NLRI_PARSE_OK
;
5050 static struct bgp_static
*bgp_static_new(void)
5052 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5055 static void bgp_static_free(struct bgp_static
*bgp_static
)
5057 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5058 route_map_counter_decrement(bgp_static
->rmap
.map
);
5060 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5061 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5064 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5065 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5067 struct bgp_dest
*dest
;
5068 struct bgp_path_info
*pi
;
5069 struct bgp_path_info
*new;
5070 struct bgp_path_info rmap_path
;
5072 struct attr
*attr_new
;
5073 route_map_result_t ret
;
5074 #ifdef ENABLE_BGP_VNC
5075 int vnc_implicit_withdraw
= 0;
5080 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5082 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5084 attr
.nexthop
= bgp_static
->igpnexthop
;
5085 attr
.med
= bgp_static
->igpmetric
;
5086 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5088 if (bgp_static
->atomic
)
5089 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5091 /* Store label index, if required. */
5092 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5093 attr
.label_index
= bgp_static
->label_index
;
5094 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5097 /* Apply route-map. */
5098 if (bgp_static
->rmap
.name
) {
5099 struct attr attr_tmp
= attr
;
5101 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5102 rmap_path
.peer
= bgp
->peer_self
;
5103 rmap_path
.attr
= &attr_tmp
;
5105 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5107 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5110 bgp
->peer_self
->rmap_type
= 0;
5112 if (ret
== RMAP_DENYMATCH
) {
5113 /* Free uninterned attribute. */
5114 bgp_attr_flush(&attr_tmp
);
5116 /* Unintern original. */
5117 aspath_unintern(&attr
.aspath
);
5118 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5122 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
5123 bgp_attr_add_gshut_community(&attr_tmp
);
5125 attr_new
= bgp_attr_intern(&attr_tmp
);
5128 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
5129 bgp_attr_add_gshut_community(&attr
);
5131 attr_new
= bgp_attr_intern(&attr
);
5134 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5135 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5136 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5140 if (attrhash_cmp(pi
->attr
, attr_new
)
5141 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5142 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5143 bgp_dest_unlock_node(dest
);
5144 bgp_attr_unintern(&attr_new
);
5145 aspath_unintern(&attr
.aspath
);
5148 /* The attribute is changed. */
5149 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5151 /* Rewrite BGP route information. */
5152 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5153 bgp_path_info_restore(dest
, pi
);
5155 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5156 #ifdef ENABLE_BGP_VNC
5157 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5158 && (safi
== SAFI_UNICAST
)) {
5159 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5161 * Implicit withdraw case.
5162 * We have to do this before pi is
5165 ++vnc_implicit_withdraw
;
5166 vnc_import_bgp_del_route(bgp
, p
, pi
);
5167 vnc_import_bgp_exterior_del_route(
5172 bgp_attr_unintern(&pi
->attr
);
5173 pi
->attr
= attr_new
;
5174 pi
->uptime
= bgp_clock();
5175 #ifdef ENABLE_BGP_VNC
5176 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5177 && (safi
== SAFI_UNICAST
)) {
5178 if (vnc_implicit_withdraw
) {
5179 vnc_import_bgp_add_route(bgp
, p
, pi
);
5180 vnc_import_bgp_exterior_add_route(
5186 /* Nexthop reachability check. */
5187 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5188 && (safi
== SAFI_UNICAST
5189 || safi
== SAFI_LABELED_UNICAST
)) {
5191 struct bgp
*bgp_nexthop
= bgp
;
5193 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5194 bgp_nexthop
= pi
->extra
->bgp_orig
;
5196 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5198 bgp_path_info_set_flag(dest
, pi
,
5201 if (BGP_DEBUG(nht
, NHT
)) {
5202 char buf1
[INET6_ADDRSTRLEN
];
5203 inet_ntop(p
->family
,
5207 "%s(%s): Route not in table, not advertising",
5210 bgp_path_info_unset_flag(
5211 dest
, pi
, BGP_PATH_VALID
);
5214 /* Delete the NHT structure if any, if we're
5216 * enabling/disabling import check. We
5217 * deregister the route
5218 * from NHT to avoid overloading NHT and the
5219 * process interaction
5221 bgp_unlink_nexthop(pi
);
5222 bgp_path_info_set_flag(dest
, pi
,
5225 /* Process change. */
5226 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5227 bgp_process(bgp
, dest
, afi
, safi
);
5229 if (SAFI_UNICAST
== safi
5230 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5232 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5233 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5237 bgp_dest_unlock_node(dest
);
5238 aspath_unintern(&attr
.aspath
);
5243 /* Make new BGP info. */
5244 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5246 /* Nexthop reachability check. */
5247 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5248 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5249 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5250 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5252 if (BGP_DEBUG(nht
, NHT
)) {
5253 char buf1
[INET6_ADDRSTRLEN
];
5254 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5257 "%s(%s): Route not in table, not advertising",
5260 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5263 /* Delete the NHT structure if any, if we're toggling between
5264 * enabling/disabling import check. We deregister the route
5265 * from NHT to avoid overloading NHT and the process interaction
5267 bgp_unlink_nexthop(new);
5269 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5272 /* Aggregate address increment. */
5273 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5275 /* Register new BGP information. */
5276 bgp_path_info_add(dest
, new);
5278 /* route_node_get lock */
5279 bgp_dest_unlock_node(dest
);
5281 /* Process change. */
5282 bgp_process(bgp
, dest
, afi
, safi
);
5284 if (SAFI_UNICAST
== safi
5285 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5286 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5287 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5290 /* Unintern original. */
5291 aspath_unintern(&attr
.aspath
);
5294 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5297 struct bgp_dest
*dest
;
5298 struct bgp_path_info
*pi
;
5300 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5302 /* Check selected route and self inserted route. */
5303 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5304 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5305 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5308 /* Withdraw static BGP route from routing table. */
5310 if (SAFI_UNICAST
== safi
5311 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5312 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5313 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5315 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5316 bgp_unlink_nexthop(pi
);
5317 bgp_path_info_delete(dest
, pi
);
5318 bgp_process(bgp
, dest
, afi
, safi
);
5321 /* Unlock bgp_node_lookup. */
5322 bgp_dest_unlock_node(dest
);
5326 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5328 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5329 afi_t afi
, safi_t safi
,
5330 struct prefix_rd
*prd
)
5332 struct bgp_dest
*dest
;
5333 struct bgp_path_info
*pi
;
5335 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5337 /* Check selected route and self inserted route. */
5338 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5339 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5340 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5343 /* Withdraw static BGP route from routing table. */
5345 #ifdef ENABLE_BGP_VNC
5346 rfapiProcessWithdraw(
5347 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5348 1); /* Kill, since it is an administrative change */
5350 if (SAFI_MPLS_VPN
== safi
5351 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5352 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5354 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5355 bgp_path_info_delete(dest
, pi
);
5356 bgp_process(bgp
, dest
, afi
, safi
);
5359 /* Unlock bgp_node_lookup. */
5360 bgp_dest_unlock_node(dest
);
5363 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5364 struct bgp_static
*bgp_static
, afi_t afi
,
5367 struct bgp_dest
*dest
;
5368 struct bgp_path_info
*new;
5369 struct attr
*attr_new
;
5370 struct attr attr
= {0};
5371 struct bgp_path_info
*pi
;
5372 #ifdef ENABLE_BGP_VNC
5373 mpls_label_t label
= 0;
5375 uint32_t num_labels
= 0;
5380 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5382 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5385 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5387 attr
.nexthop
= bgp_static
->igpnexthop
;
5388 attr
.med
= bgp_static
->igpmetric
;
5389 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5391 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5392 || (safi
== SAFI_ENCAP
)) {
5393 if (afi
== AFI_IP
) {
5394 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5395 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5398 if (afi
== AFI_L2VPN
) {
5399 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5401 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5402 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5403 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5404 sizeof(struct in6_addr
));
5405 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5406 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5407 struct bgp_encap_type_vxlan bet
;
5408 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5409 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5410 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5412 if (bgp_static
->router_mac
) {
5413 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5416 /* Apply route-map. */
5417 if (bgp_static
->rmap
.name
) {
5418 struct attr attr_tmp
= attr
;
5419 struct bgp_path_info rmap_path
;
5420 route_map_result_t ret
;
5422 rmap_path
.peer
= bgp
->peer_self
;
5423 rmap_path
.attr
= &attr_tmp
;
5425 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5427 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5430 bgp
->peer_self
->rmap_type
= 0;
5432 if (ret
== RMAP_DENYMATCH
) {
5433 /* Free uninterned attribute. */
5434 bgp_attr_flush(&attr_tmp
);
5436 /* Unintern original. */
5437 aspath_unintern(&attr
.aspath
);
5438 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5443 attr_new
= bgp_attr_intern(&attr_tmp
);
5445 attr_new
= bgp_attr_intern(&attr
);
5448 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5449 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5450 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5454 memset(&add
, 0, sizeof(union gw_addr
));
5455 if (attrhash_cmp(pi
->attr
, attr_new
)
5456 && overlay_index_equal(afi
, pi
, &add
)
5457 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5458 bgp_dest_unlock_node(dest
);
5459 bgp_attr_unintern(&attr_new
);
5460 aspath_unintern(&attr
.aspath
);
5463 /* The attribute is changed. */
5464 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5466 /* Rewrite BGP route information. */
5467 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5468 bgp_path_info_restore(dest
, pi
);
5470 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5471 bgp_attr_unintern(&pi
->attr
);
5472 pi
->attr
= attr_new
;
5473 pi
->uptime
= bgp_clock();
5474 #ifdef ENABLE_BGP_VNC
5476 label
= decode_label(&pi
->extra
->label
[0]);
5479 /* Process change. */
5480 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5481 bgp_process(bgp
, dest
, afi
, safi
);
5483 if (SAFI_MPLS_VPN
== safi
5484 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5485 vpn_leak_to_vrf_update(bgp
, pi
);
5487 #ifdef ENABLE_BGP_VNC
5488 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5489 pi
->attr
, afi
, safi
, pi
->type
,
5490 pi
->sub_type
, &label
);
5492 bgp_dest_unlock_node(dest
);
5493 aspath_unintern(&attr
.aspath
);
5499 /* Make new BGP info. */
5500 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5502 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5503 new->extra
= bgp_path_info_extra_new();
5505 new->extra
->label
[0] = bgp_static
->label
;
5506 new->extra
->num_labels
= num_labels
;
5508 #ifdef ENABLE_BGP_VNC
5509 label
= decode_label(&bgp_static
->label
);
5512 /* Aggregate address increment. */
5513 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5515 /* Register new BGP information. */
5516 bgp_path_info_add(dest
, new);
5517 /* route_node_get lock */
5518 bgp_dest_unlock_node(dest
);
5520 /* Process change. */
5521 bgp_process(bgp
, dest
, afi
, safi
);
5523 if (SAFI_MPLS_VPN
== safi
5524 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5525 vpn_leak_to_vrf_update(bgp
, new);
5527 #ifdef ENABLE_BGP_VNC
5528 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5529 safi
, new->type
, new->sub_type
, &label
);
5532 /* Unintern original. */
5533 aspath_unintern(&attr
.aspath
);
5536 /* Configure static BGP network. When user don't run zebra, static
5537 route should be installed as valid. */
5538 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5539 const char *ip_str
, afi_t afi
, safi_t safi
,
5540 const char *rmap
, int backdoor
, uint32_t label_index
)
5542 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5545 struct bgp_static
*bgp_static
;
5546 struct bgp_dest
*dest
;
5547 uint8_t need_update
= 0;
5549 /* Convert IP prefix string to struct prefix. */
5550 ret
= str2prefix(ip_str
, &p
);
5552 vty_out(vty
, "%% Malformed prefix\n");
5553 return CMD_WARNING_CONFIG_FAILED
;
5555 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5556 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5557 return CMD_WARNING_CONFIG_FAILED
;
5564 /* Set BGP static route configuration. */
5565 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5568 vty_out(vty
, "%% Can't find static route specified\n");
5569 return CMD_WARNING_CONFIG_FAILED
;
5572 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5574 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5575 && (label_index
!= bgp_static
->label_index
)) {
5577 "%% label-index doesn't match static route\n");
5578 return CMD_WARNING_CONFIG_FAILED
;
5581 if ((rmap
&& bgp_static
->rmap
.name
)
5582 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5584 "%% route-map name doesn't match static route\n");
5585 return CMD_WARNING_CONFIG_FAILED
;
5588 /* Update BGP RIB. */
5589 if (!bgp_static
->backdoor
)
5590 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5592 /* Clear configuration. */
5593 bgp_static_free(bgp_static
);
5594 bgp_dest_set_bgp_static_info(dest
, NULL
);
5595 bgp_dest_unlock_node(dest
);
5596 bgp_dest_unlock_node(dest
);
5599 /* Set BGP static route configuration. */
5600 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5601 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5603 /* Configuration change. */
5604 /* Label index cannot be changed. */
5605 if (bgp_static
->label_index
!= label_index
) {
5606 vty_out(vty
, "%% cannot change label-index\n");
5607 return CMD_WARNING_CONFIG_FAILED
;
5610 /* Check previous routes are installed into BGP. */
5611 if (bgp_static
->valid
5612 && bgp_static
->backdoor
!= backdoor
)
5615 bgp_static
->backdoor
= backdoor
;
5618 XFREE(MTYPE_ROUTE_MAP_NAME
,
5619 bgp_static
->rmap
.name
);
5620 route_map_counter_decrement(
5621 bgp_static
->rmap
.map
);
5622 bgp_static
->rmap
.name
=
5623 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5624 bgp_static
->rmap
.map
=
5625 route_map_lookup_by_name(rmap
);
5626 route_map_counter_increment(
5627 bgp_static
->rmap
.map
);
5629 XFREE(MTYPE_ROUTE_MAP_NAME
,
5630 bgp_static
->rmap
.name
);
5631 route_map_counter_decrement(
5632 bgp_static
->rmap
.map
);
5633 bgp_static
->rmap
.map
= NULL
;
5634 bgp_static
->valid
= 0;
5636 bgp_dest_unlock_node(dest
);
5638 /* New configuration. */
5639 bgp_static
= bgp_static_new();
5640 bgp_static
->backdoor
= backdoor
;
5641 bgp_static
->valid
= 0;
5642 bgp_static
->igpmetric
= 0;
5643 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5644 bgp_static
->label_index
= label_index
;
5647 XFREE(MTYPE_ROUTE_MAP_NAME
,
5648 bgp_static
->rmap
.name
);
5649 route_map_counter_decrement(
5650 bgp_static
->rmap
.map
);
5651 bgp_static
->rmap
.name
=
5652 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5653 bgp_static
->rmap
.map
=
5654 route_map_lookup_by_name(rmap
);
5655 route_map_counter_increment(
5656 bgp_static
->rmap
.map
);
5658 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5661 bgp_static
->valid
= 1;
5663 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5665 if (!bgp_static
->backdoor
)
5666 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5672 void bgp_static_add(struct bgp
*bgp
)
5676 struct bgp_dest
*dest
;
5677 struct bgp_dest
*rm
;
5678 struct bgp_table
*table
;
5679 struct bgp_static
*bgp_static
;
5681 FOREACH_AFI_SAFI (afi
, safi
)
5682 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5683 dest
= bgp_route_next(dest
)) {
5684 if (!bgp_dest_has_bgp_path_info_data(dest
))
5687 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5688 || (safi
== SAFI_EVPN
)) {
5689 table
= bgp_dest_get_bgp_table_info(dest
);
5691 for (rm
= bgp_table_top(table
); rm
;
5692 rm
= bgp_route_next(rm
)) {
5694 bgp_dest_get_bgp_static_info(
5696 bgp_static_update_safi(
5697 bgp
, bgp_dest_get_prefix(rm
),
5698 bgp_static
, afi
, safi
);
5702 bgp
, bgp_dest_get_prefix(dest
),
5703 bgp_dest_get_bgp_static_info(dest
), afi
,
5709 /* Called from bgp_delete(). Delete all static routes from the BGP
5711 void bgp_static_delete(struct bgp
*bgp
)
5715 struct bgp_dest
*dest
;
5716 struct bgp_dest
*rm
;
5717 struct bgp_table
*table
;
5718 struct bgp_static
*bgp_static
;
5720 FOREACH_AFI_SAFI (afi
, safi
)
5721 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5722 dest
= bgp_route_next(dest
)) {
5723 if (!bgp_dest_has_bgp_path_info_data(dest
))
5726 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5727 || (safi
== SAFI_EVPN
)) {
5728 table
= bgp_dest_get_bgp_table_info(dest
);
5730 for (rm
= bgp_table_top(table
); rm
;
5731 rm
= bgp_route_next(rm
)) {
5733 bgp_dest_get_bgp_static_info(
5738 bgp_static_withdraw_safi(
5739 bgp
, bgp_dest_get_prefix(rm
),
5741 (struct prefix_rd
*)
5742 bgp_dest_get_prefix(
5744 bgp_static_free(bgp_static
);
5745 bgp_dest_set_bgp_static_info(dest
,
5747 bgp_dest_unlock_node(dest
);
5750 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5751 bgp_static_withdraw(bgp
,
5752 bgp_dest_get_prefix(dest
),
5754 bgp_static_free(bgp_static
);
5755 bgp_dest_set_bgp_static_info(dest
, NULL
);
5756 bgp_dest_unlock_node(dest
);
5761 void bgp_static_redo_import_check(struct bgp
*bgp
)
5765 struct bgp_dest
*dest
;
5766 struct bgp_dest
*rm
;
5767 struct bgp_table
*table
;
5768 struct bgp_static
*bgp_static
;
5770 /* Use this flag to force reprocessing of the route */
5771 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5772 FOREACH_AFI_SAFI (afi
, safi
) {
5773 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5774 dest
= bgp_route_next(dest
)) {
5775 if (!bgp_dest_has_bgp_path_info_data(dest
))
5778 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5779 || (safi
== SAFI_EVPN
)) {
5780 table
= bgp_dest_get_bgp_table_info(dest
);
5782 for (rm
= bgp_table_top(table
); rm
;
5783 rm
= bgp_route_next(rm
)) {
5785 bgp_dest_get_bgp_static_info(
5787 bgp_static_update_safi(
5788 bgp
, bgp_dest_get_prefix(rm
),
5789 bgp_static
, afi
, safi
);
5792 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5793 bgp_static_update(bgp
,
5794 bgp_dest_get_prefix(dest
),
5795 bgp_static
, afi
, safi
);
5799 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5802 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5805 struct bgp_table
*table
;
5806 struct bgp_dest
*dest
;
5807 struct bgp_path_info
*pi
;
5809 /* Do not install the aggregate route if BGP is in the
5810 * process of termination.
5812 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
5813 || (bgp
->peer_self
== NULL
))
5816 table
= bgp
->rib
[afi
][safi
];
5817 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5818 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5819 if (pi
->peer
== bgp
->peer_self
5820 && ((pi
->type
== ZEBRA_ROUTE_BGP
5821 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5822 || (pi
->type
!= ZEBRA_ROUTE_BGP
5824 == BGP_ROUTE_REDISTRIBUTE
))) {
5825 bgp_aggregate_decrement(
5826 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
5828 bgp_unlink_nexthop(pi
);
5829 bgp_path_info_delete(dest
, pi
);
5830 bgp_process(bgp
, dest
, afi
, safi
);
5837 * Purge all networks and redistributed routes from routing table.
5838 * Invoked upon the instance going down.
5840 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5845 FOREACH_AFI_SAFI (afi
, safi
)
5846 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5851 * Currently this is used to set static routes for VPN and ENCAP.
5852 * I think it can probably be factored with bgp_static_set.
5854 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5855 const char *ip_str
, const char *rd_str
,
5856 const char *label_str
, const char *rmap_str
,
5857 int evpn_type
, const char *esi
, const char *gwip
,
5858 const char *ethtag
, const char *routermac
)
5860 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5863 struct prefix_rd prd
;
5864 struct bgp_dest
*pdest
;
5865 struct bgp_dest
*dest
;
5866 struct bgp_table
*table
;
5867 struct bgp_static
*bgp_static
;
5868 mpls_label_t label
= MPLS_INVALID_LABEL
;
5869 struct prefix gw_ip
;
5871 /* validate ip prefix */
5872 ret
= str2prefix(ip_str
, &p
);
5874 vty_out(vty
, "%% Malformed prefix\n");
5875 return CMD_WARNING_CONFIG_FAILED
;
5878 if ((afi
== AFI_L2VPN
)
5879 && (bgp_build_evpn_prefix(evpn_type
,
5880 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5881 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5882 return CMD_WARNING_CONFIG_FAILED
;
5885 ret
= str2prefix_rd(rd_str
, &prd
);
5887 vty_out(vty
, "%% Malformed rd\n");
5888 return CMD_WARNING_CONFIG_FAILED
;
5892 unsigned long label_val
;
5893 label_val
= strtoul(label_str
, NULL
, 10);
5894 encode_label(label_val
, &label
);
5897 if (safi
== SAFI_EVPN
) {
5898 if (esi
&& str2esi(esi
, NULL
) == 0) {
5899 vty_out(vty
, "%% Malformed ESI\n");
5900 return CMD_WARNING_CONFIG_FAILED
;
5902 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5903 vty_out(vty
, "%% Malformed Router MAC\n");
5904 return CMD_WARNING_CONFIG_FAILED
;
5907 memset(&gw_ip
, 0, sizeof(struct prefix
));
5908 ret
= str2prefix(gwip
, &gw_ip
);
5910 vty_out(vty
, "%% Malformed GatewayIp\n");
5911 return CMD_WARNING_CONFIG_FAILED
;
5913 if ((gw_ip
.family
== AF_INET
5914 && is_evpn_prefix_ipaddr_v6(
5915 (struct prefix_evpn
*)&p
))
5916 || (gw_ip
.family
== AF_INET6
5917 && is_evpn_prefix_ipaddr_v4(
5918 (struct prefix_evpn
*)&p
))) {
5920 "%% GatewayIp family differs with IP prefix\n");
5921 return CMD_WARNING_CONFIG_FAILED
;
5925 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5926 if (!bgp_dest_has_bgp_path_info_data(pdest
))
5927 bgp_dest_set_bgp_table_info(pdest
,
5928 bgp_table_init(bgp
, afi
, safi
));
5929 table
= bgp_dest_get_bgp_table_info(pdest
);
5931 dest
= bgp_node_get(table
, &p
);
5933 if (bgp_dest_has_bgp_path_info_data(dest
)) {
5934 vty_out(vty
, "%% Same network configuration exists\n");
5935 bgp_dest_unlock_node(dest
);
5937 /* New configuration. */
5938 bgp_static
= bgp_static_new();
5939 bgp_static
->backdoor
= 0;
5940 bgp_static
->valid
= 0;
5941 bgp_static
->igpmetric
= 0;
5942 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5943 bgp_static
->label
= label
;
5944 bgp_static
->prd
= prd
;
5947 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5948 route_map_counter_decrement(bgp_static
->rmap
.map
);
5949 bgp_static
->rmap
.name
=
5950 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5951 bgp_static
->rmap
.map
=
5952 route_map_lookup_by_name(rmap_str
);
5953 route_map_counter_increment(bgp_static
->rmap
.map
);
5956 if (safi
== SAFI_EVPN
) {
5958 bgp_static
->eth_s_id
=
5961 str2esi(esi
, bgp_static
->eth_s_id
);
5964 bgp_static
->router_mac
=
5965 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5966 (void)prefix_str2mac(routermac
,
5967 bgp_static
->router_mac
);
5970 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5972 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5974 bgp_static
->valid
= 1;
5975 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5981 /* Configure static BGP network. */
5982 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5983 const char *ip_str
, const char *rd_str
,
5984 const char *label_str
, int evpn_type
, const char *esi
,
5985 const char *gwip
, const char *ethtag
)
5987 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5990 struct prefix_rd prd
;
5991 struct bgp_dest
*pdest
;
5992 struct bgp_dest
*dest
;
5993 struct bgp_table
*table
;
5994 struct bgp_static
*bgp_static
;
5995 mpls_label_t label
= MPLS_INVALID_LABEL
;
5997 /* Convert IP prefix string to struct prefix. */
5998 ret
= str2prefix(ip_str
, &p
);
6000 vty_out(vty
, "%% Malformed prefix\n");
6001 return CMD_WARNING_CONFIG_FAILED
;
6004 if ((afi
== AFI_L2VPN
)
6005 && (bgp_build_evpn_prefix(evpn_type
,
6006 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6007 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6008 return CMD_WARNING_CONFIG_FAILED
;
6010 ret
= str2prefix_rd(rd_str
, &prd
);
6012 vty_out(vty
, "%% Malformed rd\n");
6013 return CMD_WARNING_CONFIG_FAILED
;
6017 unsigned long label_val
;
6018 label_val
= strtoul(label_str
, NULL
, 10);
6019 encode_label(label_val
, &label
);
6022 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6023 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6024 bgp_dest_set_bgp_table_info(pdest
,
6025 bgp_table_init(bgp
, afi
, safi
));
6027 bgp_dest_unlock_node(pdest
);
6028 table
= bgp_dest_get_bgp_table_info(pdest
);
6030 dest
= bgp_node_lookup(table
, &p
);
6033 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6035 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6036 bgp_static_free(bgp_static
);
6037 bgp_dest_set_bgp_static_info(dest
, NULL
);
6038 bgp_dest_unlock_node(dest
);
6039 bgp_dest_unlock_node(dest
);
6041 vty_out(vty
, "%% Can't find the route\n");
6046 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6047 const char *rmap_name
)
6049 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6050 struct bgp_rmap
*rmap
;
6052 rmap
= &bgp
->table_map
[afi
][safi
];
6054 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6055 route_map_counter_decrement(rmap
->map
);
6056 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6057 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6058 route_map_counter_increment(rmap
->map
);
6060 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6061 route_map_counter_decrement(rmap
->map
);
6065 if (bgp_fibupd_safi(safi
))
6066 bgp_zebra_announce_table(bgp
, afi
, safi
);
6071 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6072 const char *rmap_name
)
6074 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6075 struct bgp_rmap
*rmap
;
6077 rmap
= &bgp
->table_map
[afi
][safi
];
6078 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6079 route_map_counter_decrement(rmap
->map
);
6082 if (bgp_fibupd_safi(safi
))
6083 bgp_zebra_announce_table(bgp
, afi
, safi
);
6088 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6091 if (bgp
->table_map
[afi
][safi
].name
) {
6092 vty_out(vty
, " table-map %s\n",
6093 bgp
->table_map
[afi
][safi
].name
);
6097 DEFUN (bgp_table_map
,
6100 "BGP table to RIB route download filter\n"
6101 "Name of the route map\n")
6104 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6105 argv
[idx_word
]->arg
);
6107 DEFUN (no_bgp_table_map
,
6108 no_bgp_table_map_cmd
,
6109 "no table-map WORD",
6111 "BGP table to RIB route download filter\n"
6112 "Name of the route map\n")
6115 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6116 argv
[idx_word
]->arg
);
6122 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6123 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6124 backdoor$backdoor}]",
6126 "Specify a network to announce via BGP\n"
6131 "Route-map to modify the attributes\n"
6132 "Name of the route map\n"
6133 "Label index to associate with the prefix\n"
6134 "Label index value\n"
6135 "Specify a BGP backdoor route\n")
6137 char addr_prefix_str
[BUFSIZ
];
6142 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6145 vty_out(vty
, "%% Inconsistent address and mask\n");
6146 return CMD_WARNING_CONFIG_FAILED
;
6150 return bgp_static_set(
6151 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6152 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6153 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6156 DEFPY(ipv6_bgp_network
,
6157 ipv6_bgp_network_cmd
,
6158 "[no] network X:X::X:X/M$prefix \
6159 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6161 "Specify a network to announce via BGP\n"
6163 "Route-map to modify the attributes\n"
6164 "Name of the route map\n"
6165 "Label index to associate with the prefix\n"
6166 "Label index value\n")
6168 return bgp_static_set(
6169 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6170 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6173 static struct bgp_aggregate
*bgp_aggregate_new(void)
6175 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6178 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6180 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6181 route_map_counter_decrement(aggregate
->rmap
.map
);
6182 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6185 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6186 struct aspath
*aspath
,
6187 struct community
*comm
,
6188 struct ecommunity
*ecomm
,
6189 struct lcommunity
*lcomm
)
6191 static struct aspath
*ae
= NULL
;
6194 ae
= aspath_empty();
6199 if (origin
!= pi
->attr
->origin
)
6202 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6205 if (!community_cmp(pi
->attr
->community
, comm
))
6208 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6211 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6214 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6220 static void bgp_aggregate_install(
6221 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6222 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6223 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6224 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6226 struct bgp_dest
*dest
;
6227 struct bgp_table
*table
;
6228 struct bgp_path_info
*pi
, *orig
, *new;
6231 table
= bgp
->rib
[afi
][safi
];
6233 dest
= bgp_node_get(table
, p
);
6235 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6236 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6237 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6240 if (aggregate
->count
> 0) {
6242 * If the aggregate information has not changed
6243 * no need to re-install it again.
6245 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6246 ecommunity
, lcommunity
)) {
6247 bgp_dest_unlock_node(dest
);
6250 aspath_free(aspath
);
6252 community_free(&community
);
6254 ecommunity_free(&ecommunity
);
6256 lcommunity_free(&lcommunity
);
6262 * Mark the old as unusable
6265 bgp_path_info_delete(dest
, pi
);
6267 attr
= bgp_attr_aggregate_intern(
6268 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6269 aggregate
, atomic_aggregate
, p
);
6272 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6276 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6277 bgp
->peer_self
, attr
, dest
);
6279 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6281 bgp_path_info_add(dest
, new);
6282 bgp_process(bgp
, dest
, afi
, safi
);
6284 for (pi
= orig
; pi
; pi
= pi
->next
)
6285 if (pi
->peer
== bgp
->peer_self
6286 && pi
->type
== ZEBRA_ROUTE_BGP
6287 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6290 /* Withdraw static BGP route from routing table. */
6292 bgp_path_info_delete(dest
, pi
);
6293 bgp_process(bgp
, dest
, afi
, safi
);
6297 bgp_dest_unlock_node(dest
);
6300 /* Update an aggregate as routes are added/removed from the BGP table */
6301 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6302 safi_t safi
, struct bgp_aggregate
*aggregate
)
6304 struct bgp_table
*table
;
6305 struct bgp_dest
*top
;
6306 struct bgp_dest
*dest
;
6308 struct aspath
*aspath
= NULL
;
6309 struct community
*community
= NULL
;
6310 struct ecommunity
*ecommunity
= NULL
;
6311 struct lcommunity
*lcommunity
= NULL
;
6312 struct bgp_path_info
*pi
;
6313 unsigned long match
= 0;
6314 uint8_t atomic_aggregate
= 0;
6316 /* If the bgp instance is being deleted or self peer is deleted
6317 * then do not create aggregate route
6319 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6320 || (bgp
->peer_self
== NULL
))
6323 /* ORIGIN attribute: If at least one route among routes that are
6324 aggregated has ORIGIN with the value INCOMPLETE, then the
6325 aggregated route must have the ORIGIN attribute with the value
6326 INCOMPLETE. Otherwise, if at least one route among routes that
6327 are aggregated has ORIGIN with the value EGP, then the aggregated
6328 route must have the origin attribute with the value EGP. In all
6329 other case the value of the ORIGIN attribute of the aggregated
6330 route is INTERNAL. */
6331 origin
= BGP_ORIGIN_IGP
;
6333 table
= bgp
->rib
[afi
][safi
];
6335 top
= bgp_node_get(table
, p
);
6336 for (dest
= bgp_node_get(table
, p
); dest
;
6337 dest
= bgp_route_next_until(dest
, top
)) {
6338 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6340 if (dest_p
->prefixlen
<= p
->prefixlen
)
6345 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6346 if (BGP_PATH_HOLDDOWN(pi
))
6350 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6351 atomic_aggregate
= 1;
6353 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6357 * summary-only aggregate route suppress
6358 * aggregated route announcements.
6360 if (aggregate
->summary_only
) {
6361 (bgp_path_info_extra_get(pi
))->suppress
++;
6362 bgp_path_info_set_flag(dest
, pi
,
6363 BGP_PATH_ATTR_CHANGED
);
6370 * If at least one route among routes that are
6371 * aggregated has ORIGIN with the value INCOMPLETE,
6372 * then the aggregated route MUST have the ORIGIN
6373 * attribute with the value INCOMPLETE. Otherwise, if
6374 * at least one route among routes that are aggregated
6375 * has ORIGIN with the value EGP, then the aggregated
6376 * route MUST have the ORIGIN attribute with the value
6379 switch (pi
->attr
->origin
) {
6380 case BGP_ORIGIN_INCOMPLETE
:
6381 aggregate
->incomplete_origin_count
++;
6383 case BGP_ORIGIN_EGP
:
6384 aggregate
->egp_origin_count
++;
6392 if (!aggregate
->as_set
)
6396 * as-set aggregate route generate origin, as path,
6397 * and community aggregation.
6399 /* Compute aggregate route's as-path.
6401 bgp_compute_aggregate_aspath_hash(aggregate
,
6404 /* Compute aggregate route's community.
6406 if (pi
->attr
->community
)
6407 bgp_compute_aggregate_community_hash(
6409 pi
->attr
->community
);
6411 /* Compute aggregate route's extended community.
6413 if (pi
->attr
->ecommunity
)
6414 bgp_compute_aggregate_ecommunity_hash(
6416 pi
->attr
->ecommunity
);
6418 /* Compute aggregate route's large community.
6420 if (pi
->attr
->lcommunity
)
6421 bgp_compute_aggregate_lcommunity_hash(
6423 pi
->attr
->lcommunity
);
6426 bgp_process(bgp
, dest
, afi
, safi
);
6428 if (aggregate
->as_set
) {
6429 bgp_compute_aggregate_aspath_val(aggregate
);
6430 bgp_compute_aggregate_community_val(aggregate
);
6431 bgp_compute_aggregate_ecommunity_val(aggregate
);
6432 bgp_compute_aggregate_lcommunity_val(aggregate
);
6436 bgp_dest_unlock_node(top
);
6439 if (aggregate
->incomplete_origin_count
> 0)
6440 origin
= BGP_ORIGIN_INCOMPLETE
;
6441 else if (aggregate
->egp_origin_count
> 0)
6442 origin
= BGP_ORIGIN_EGP
;
6444 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6445 origin
= aggregate
->origin
;
6447 if (aggregate
->as_set
) {
6448 if (aggregate
->aspath
)
6449 /* Retrieve aggregate route's as-path.
6451 aspath
= aspath_dup(aggregate
->aspath
);
6453 if (aggregate
->community
)
6454 /* Retrieve aggregate route's community.
6456 community
= community_dup(aggregate
->community
);
6458 if (aggregate
->ecommunity
)
6459 /* Retrieve aggregate route's ecommunity.
6461 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6463 if (aggregate
->lcommunity
)
6464 /* Retrieve aggregate route's lcommunity.
6466 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6469 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6470 ecommunity
, lcommunity
, atomic_aggregate
,
6474 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6475 safi_t safi
, struct bgp_aggregate
*aggregate
)
6477 struct bgp_table
*table
;
6478 struct bgp_dest
*top
;
6479 struct bgp_dest
*dest
;
6480 struct bgp_path_info
*pi
;
6481 unsigned long match
;
6483 table
= bgp
->rib
[afi
][safi
];
6485 /* If routes exists below this node, generate aggregate routes. */
6486 top
= bgp_node_get(table
, p
);
6487 for (dest
= bgp_node_get(table
, p
); dest
;
6488 dest
= bgp_route_next_until(dest
, top
)) {
6489 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6491 if (dest_p
->prefixlen
<= p
->prefixlen
)
6495 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6496 if (BGP_PATH_HOLDDOWN(pi
))
6499 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6502 if (aggregate
->summary_only
&& pi
->extra
) {
6503 pi
->extra
->suppress
--;
6505 if (pi
->extra
->suppress
== 0) {
6506 bgp_path_info_set_flag(
6508 BGP_PATH_ATTR_CHANGED
);
6514 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6515 aggregate
->incomplete_origin_count
--;
6516 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6517 aggregate
->egp_origin_count
--;
6519 if (aggregate
->as_set
) {
6520 /* Remove as-path from aggregate.
6522 bgp_remove_aspath_from_aggregate_hash(
6526 if (pi
->attr
->community
)
6527 /* Remove community from aggregate.
6529 bgp_remove_comm_from_aggregate_hash(
6531 pi
->attr
->community
);
6533 if (pi
->attr
->ecommunity
)
6534 /* Remove ecommunity from aggregate.
6536 bgp_remove_ecomm_from_aggregate_hash(
6538 pi
->attr
->ecommunity
);
6540 if (pi
->attr
->lcommunity
)
6541 /* Remove lcommunity from aggregate.
6543 bgp_remove_lcomm_from_aggregate_hash(
6545 pi
->attr
->lcommunity
);
6549 /* If this node was suppressed, process the change. */
6551 bgp_process(bgp
, dest
, afi
, safi
);
6553 if (aggregate
->as_set
) {
6554 aspath_free(aggregate
->aspath
);
6555 aggregate
->aspath
= NULL
;
6556 if (aggregate
->community
)
6557 community_free(&aggregate
->community
);
6558 if (aggregate
->ecommunity
)
6559 ecommunity_free(&aggregate
->ecommunity
);
6560 if (aggregate
->lcommunity
)
6561 lcommunity_free(&aggregate
->lcommunity
);
6564 bgp_dest_unlock_node(top
);
6567 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
6568 const struct prefix
*aggr_p
,
6569 struct bgp_path_info
*pinew
, afi_t afi
,
6571 struct bgp_aggregate
*aggregate
)
6574 struct aspath
*aspath
= NULL
;
6575 uint8_t atomic_aggregate
= 0;
6576 struct community
*community
= NULL
;
6577 struct ecommunity
*ecommunity
= NULL
;
6578 struct lcommunity
*lcommunity
= NULL
;
6580 /* ORIGIN attribute: If at least one route among routes that are
6581 * aggregated has ORIGIN with the value INCOMPLETE, then the
6582 * aggregated route must have the ORIGIN attribute with the value
6583 * INCOMPLETE. Otherwise, if at least one route among routes that
6584 * are aggregated has ORIGIN with the value EGP, then the aggregated
6585 * route must have the origin attribute with the value EGP. In all
6586 * other case the value of the ORIGIN attribute of the aggregated
6587 * route is INTERNAL.
6589 origin
= BGP_ORIGIN_IGP
;
6593 if (aggregate
->summary_only
)
6594 (bgp_path_info_extra_get(pinew
))->suppress
++;
6596 switch (pinew
->attr
->origin
) {
6597 case BGP_ORIGIN_INCOMPLETE
:
6598 aggregate
->incomplete_origin_count
++;
6600 case BGP_ORIGIN_EGP
:
6601 aggregate
->egp_origin_count
++;
6609 if (aggregate
->incomplete_origin_count
> 0)
6610 origin
= BGP_ORIGIN_INCOMPLETE
;
6611 else if (aggregate
->egp_origin_count
> 0)
6612 origin
= BGP_ORIGIN_EGP
;
6614 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6615 origin
= aggregate
->origin
;
6617 if (aggregate
->as_set
) {
6618 /* Compute aggregate route's as-path.
6620 bgp_compute_aggregate_aspath(aggregate
,
6621 pinew
->attr
->aspath
);
6623 /* Compute aggregate route's community.
6625 if (pinew
->attr
->community
)
6626 bgp_compute_aggregate_community(
6628 pinew
->attr
->community
);
6630 /* Compute aggregate route's extended community.
6632 if (pinew
->attr
->ecommunity
)
6633 bgp_compute_aggregate_ecommunity(
6635 pinew
->attr
->ecommunity
);
6637 /* Compute aggregate route's large community.
6639 if (pinew
->attr
->lcommunity
)
6640 bgp_compute_aggregate_lcommunity(
6642 pinew
->attr
->lcommunity
);
6644 /* Retrieve aggregate route's as-path.
6646 if (aggregate
->aspath
)
6647 aspath
= aspath_dup(aggregate
->aspath
);
6649 /* Retrieve aggregate route's community.
6651 if (aggregate
->community
)
6652 community
= community_dup(aggregate
->community
);
6654 /* Retrieve aggregate route's ecommunity.
6656 if (aggregate
->ecommunity
)
6657 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6659 /* Retrieve aggregate route's lcommunity.
6661 if (aggregate
->lcommunity
)
6662 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6665 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6666 aspath
, community
, ecommunity
,
6667 lcommunity
, atomic_aggregate
, aggregate
);
6670 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6672 struct bgp_path_info
*pi
,
6673 struct bgp_aggregate
*aggregate
,
6674 const struct prefix
*aggr_p
)
6677 struct aspath
*aspath
= NULL
;
6678 uint8_t atomic_aggregate
= 0;
6679 struct community
*community
= NULL
;
6680 struct ecommunity
*ecommunity
= NULL
;
6681 struct lcommunity
*lcommunity
= NULL
;
6682 unsigned long match
= 0;
6684 if (BGP_PATH_HOLDDOWN(pi
))
6687 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6690 if (aggregate
->summary_only
6692 && pi
->extra
->suppress
> 0) {
6693 pi
->extra
->suppress
--;
6695 if (pi
->extra
->suppress
== 0) {
6696 bgp_path_info_set_flag(pi
->net
, pi
,
6697 BGP_PATH_ATTR_CHANGED
);
6702 if (aggregate
->count
> 0)
6705 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6706 aggregate
->incomplete_origin_count
--;
6707 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6708 aggregate
->egp_origin_count
--;
6710 if (aggregate
->as_set
) {
6711 /* Remove as-path from aggregate.
6713 bgp_remove_aspath_from_aggregate(aggregate
,
6716 if (pi
->attr
->community
)
6717 /* Remove community from aggregate.
6719 bgp_remove_community_from_aggregate(
6721 pi
->attr
->community
);
6723 if (pi
->attr
->ecommunity
)
6724 /* Remove ecommunity from aggregate.
6726 bgp_remove_ecommunity_from_aggregate(
6728 pi
->attr
->ecommunity
);
6730 if (pi
->attr
->lcommunity
)
6731 /* Remove lcommunity from aggregate.
6733 bgp_remove_lcommunity_from_aggregate(
6735 pi
->attr
->lcommunity
);
6738 /* If this node was suppressed, process the change. */
6740 bgp_process(bgp
, pi
->net
, afi
, safi
);
6742 origin
= BGP_ORIGIN_IGP
;
6743 if (aggregate
->incomplete_origin_count
> 0)
6744 origin
= BGP_ORIGIN_INCOMPLETE
;
6745 else if (aggregate
->egp_origin_count
> 0)
6746 origin
= BGP_ORIGIN_EGP
;
6748 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6749 origin
= aggregate
->origin
;
6751 if (aggregate
->as_set
) {
6752 /* Retrieve aggregate route's as-path.
6754 if (aggregate
->aspath
)
6755 aspath
= aspath_dup(aggregate
->aspath
);
6757 /* Retrieve aggregate route's community.
6759 if (aggregate
->community
)
6760 community
= community_dup(aggregate
->community
);
6762 /* Retrieve aggregate route's ecommunity.
6764 if (aggregate
->ecommunity
)
6765 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6767 /* Retrieve aggregate route's lcommunity.
6769 if (aggregate
->lcommunity
)
6770 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6773 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6774 aspath
, community
, ecommunity
,
6775 lcommunity
, atomic_aggregate
, aggregate
);
6778 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
6779 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6781 struct bgp_dest
*child
;
6782 struct bgp_dest
*dest
;
6783 struct bgp_aggregate
*aggregate
;
6784 struct bgp_table
*table
;
6786 table
= bgp
->aggregate
[afi
][safi
];
6788 /* No aggregates configured. */
6789 if (bgp_table_top_nolock(table
) == NULL
)
6792 if (p
->prefixlen
== 0)
6795 if (BGP_PATH_HOLDDOWN(pi
))
6798 child
= bgp_node_get(table
, p
);
6800 /* Aggregate address configuration check. */
6801 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
6802 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6804 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6805 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
6806 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
6810 bgp_dest_unlock_node(child
);
6813 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
6814 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6816 struct bgp_dest
*child
;
6817 struct bgp_dest
*dest
;
6818 struct bgp_aggregate
*aggregate
;
6819 struct bgp_table
*table
;
6821 table
= bgp
->aggregate
[afi
][safi
];
6823 /* No aggregates configured. */
6824 if (bgp_table_top_nolock(table
) == NULL
)
6827 if (p
->prefixlen
== 0)
6830 child
= bgp_node_get(table
, p
);
6832 /* Aggregate address configuration check. */
6833 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
6834 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6836 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6837 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
6838 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
6842 bgp_dest_unlock_node(child
);
6845 /* Aggregate route attribute. */
6846 #define AGGREGATE_SUMMARY_ONLY 1
6847 #define AGGREGATE_AS_SET 1
6848 #define AGGREGATE_AS_UNSET 0
6850 static const char *bgp_origin2str(uint8_t origin
)
6853 case BGP_ORIGIN_IGP
:
6855 case BGP_ORIGIN_EGP
:
6857 case BGP_ORIGIN_INCOMPLETE
:
6858 return "incomplete";
6863 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6864 afi_t afi
, safi_t safi
)
6866 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6869 struct bgp_dest
*dest
;
6870 struct bgp_aggregate
*aggregate
;
6872 /* Convert string to prefix structure. */
6873 ret
= str2prefix(prefix_str
, &p
);
6875 vty_out(vty
, "Malformed prefix\n");
6876 return CMD_WARNING_CONFIG_FAILED
;
6880 /* Old configuration check. */
6881 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6884 "%% There is no aggregate-address configuration.\n");
6885 return CMD_WARNING_CONFIG_FAILED
;
6888 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6889 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6890 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6891 NULL
, NULL
, 0, aggregate
);
6893 /* Unlock aggregate address configuration. */
6894 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
6896 if (aggregate
->community
)
6897 community_free(&aggregate
->community
);
6899 if (aggregate
->community_hash
) {
6900 /* Delete all communities in the hash.
6902 hash_clean(aggregate
->community_hash
,
6903 bgp_aggr_community_remove
);
6904 /* Free up the community_hash.
6906 hash_free(aggregate
->community_hash
);
6909 if (aggregate
->ecommunity
)
6910 ecommunity_free(&aggregate
->ecommunity
);
6912 if (aggregate
->ecommunity_hash
) {
6913 /* Delete all ecommunities in the hash.
6915 hash_clean(aggregate
->ecommunity_hash
,
6916 bgp_aggr_ecommunity_remove
);
6917 /* Free up the ecommunity_hash.
6919 hash_free(aggregate
->ecommunity_hash
);
6922 if (aggregate
->lcommunity
)
6923 lcommunity_free(&aggregate
->lcommunity
);
6925 if (aggregate
->lcommunity_hash
) {
6926 /* Delete all lcommunities in the hash.
6928 hash_clean(aggregate
->lcommunity_hash
,
6929 bgp_aggr_lcommunity_remove
);
6930 /* Free up the lcommunity_hash.
6932 hash_free(aggregate
->lcommunity_hash
);
6935 if (aggregate
->aspath
)
6936 aspath_free(aggregate
->aspath
);
6938 if (aggregate
->aspath_hash
) {
6939 /* Delete all as-paths in the hash.
6941 hash_clean(aggregate
->aspath_hash
,
6942 bgp_aggr_aspath_remove
);
6943 /* Free up the aspath_hash.
6945 hash_free(aggregate
->aspath_hash
);
6948 bgp_aggregate_free(aggregate
);
6949 bgp_dest_unlock_node(dest
);
6950 bgp_dest_unlock_node(dest
);
6955 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6956 safi_t safi
, const char *rmap
,
6957 uint8_t summary_only
, uint8_t as_set
,
6960 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6963 struct bgp_dest
*dest
;
6964 struct bgp_aggregate
*aggregate
;
6965 uint8_t as_set_new
= as_set
;
6967 /* Convert string to prefix structure. */
6968 ret
= str2prefix(prefix_str
, &p
);
6970 vty_out(vty
, "Malformed prefix\n");
6971 return CMD_WARNING_CONFIG_FAILED
;
6975 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6976 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6977 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6979 return CMD_WARNING_CONFIG_FAILED
;
6982 /* Old configuration check. */
6983 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6984 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
6987 vty_out(vty
, "There is already same aggregate network.\n");
6988 /* try to remove the old entry */
6989 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6991 vty_out(vty
, "Error deleting aggregate.\n");
6992 bgp_dest_unlock_node(dest
);
6993 return CMD_WARNING_CONFIG_FAILED
;
6997 /* Make aggregate address structure. */
6998 aggregate
= bgp_aggregate_new();
6999 aggregate
->summary_only
= summary_only
;
7001 /* Network operators MUST NOT locally generate any new
7002 * announcements containing AS_SET or AS_CONFED_SET. If they have
7003 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7004 * SHOULD withdraw those routes and re-announce routes for the
7005 * aggregate or component prefixes (i.e., the more-specific routes
7006 * subsumed by the previously aggregated route) without AS_SET
7007 * or AS_CONFED_SET in the updates.
7009 if (bgp
->reject_as_sets
) {
7010 if (as_set
== AGGREGATE_AS_SET
) {
7011 as_set_new
= AGGREGATE_AS_UNSET
;
7013 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7016 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7020 aggregate
->as_set
= as_set_new
;
7021 aggregate
->safi
= safi
;
7022 /* Override ORIGIN attribute if defined.
7023 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7024 * to IGP which is not what rfc4271 says.
7025 * This enables the same behavior, optionally.
7027 aggregate
->origin
= origin
;
7030 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7031 route_map_counter_decrement(aggregate
->rmap
.map
);
7032 aggregate
->rmap
.name
=
7033 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7034 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7035 route_map_counter_increment(aggregate
->rmap
.map
);
7037 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7039 /* Aggregate address insert into BGP routing table. */
7040 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
7045 DEFUN (aggregate_address
,
7046 aggregate_address_cmd
,
7047 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7048 "Configure BGP aggregate entries\n"
7049 "Aggregate prefix\n"
7050 "Generate AS set path information\n"
7051 "Filter more specific routes from updates\n"
7052 "Filter more specific routes from updates\n"
7053 "Generate AS set path information\n"
7054 "Apply route map to aggregate network\n"
7055 "Name of route map\n"
7059 "Unknown heritage\n")
7062 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
7063 char *prefix
= argv
[idx
]->arg
;
7065 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7066 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7067 : AGGREGATE_AS_UNSET
;
7069 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7070 ? AGGREGATE_SUMMARY_ONLY
7074 argv_find(argv
, argc
, "WORD", &idx
);
7076 rmap
= argv
[idx
]->arg
;
7079 if (argv_find(argv
, argc
, "origin", &idx
)) {
7080 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7081 origin
= BGP_ORIGIN_IGP
;
7082 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7083 origin
= BGP_ORIGIN_EGP
;
7084 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7085 origin
= BGP_ORIGIN_INCOMPLETE
;
7088 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
), rmap
,
7089 summary_only
, as_set
, origin
);
7092 DEFUN (aggregate_address_mask
,
7093 aggregate_address_mask_cmd
,
7094 "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>]",
7095 "Configure BGP aggregate entries\n"
7096 "Aggregate address\n"
7098 "Generate AS set path information\n"
7099 "Filter more specific routes from updates\n"
7100 "Filter more specific routes from updates\n"
7101 "Generate AS set path information\n"
7102 "Apply route map to aggregate network\n"
7103 "Name of route map\n"
7107 "Unknown heritage\n")
7110 argv_find(argv
, argc
, "A.B.C.D", &idx
);
7111 char *prefix
= argv
[idx
]->arg
;
7112 char *mask
= argv
[idx
+ 1]->arg
;
7115 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7116 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7117 : AGGREGATE_AS_UNSET
;
7119 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7120 ? AGGREGATE_SUMMARY_ONLY
7123 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
7125 rmap
= argv
[idx
]->arg
;
7127 char prefix_str
[BUFSIZ
];
7128 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
7131 vty_out(vty
, "%% Inconsistent address and mask\n");
7132 return CMD_WARNING_CONFIG_FAILED
;
7136 if (argv_find(argv
, argc
, "origin", &idx
)) {
7137 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7138 origin
= BGP_ORIGIN_IGP
;
7139 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7140 origin
= BGP_ORIGIN_EGP
;
7141 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7142 origin
= BGP_ORIGIN_INCOMPLETE
;
7145 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
7146 rmap
, summary_only
, as_set
, origin
);
7149 DEFUN (no_aggregate_address
,
7150 no_aggregate_address_cmd
,
7151 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7153 "Configure BGP aggregate entries\n"
7154 "Aggregate prefix\n"
7155 "Generate AS set path information\n"
7156 "Filter more specific routes from updates\n"
7157 "Filter more specific routes from updates\n"
7158 "Generate AS set path information\n"
7159 "Apply route map to aggregate network\n"
7160 "Name of route map\n"
7164 "Unknown heritage\n")
7167 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
7168 char *prefix
= argv
[idx
]->arg
;
7169 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
7172 DEFUN (no_aggregate_address_mask
,
7173 no_aggregate_address_mask_cmd
,
7174 "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>]",
7176 "Configure BGP aggregate entries\n"
7177 "Aggregate address\n"
7179 "Generate AS set path information\n"
7180 "Filter more specific routes from updates\n"
7181 "Filter more specific routes from updates\n"
7182 "Generate AS set path information\n"
7183 "Apply route map to aggregate network\n"
7184 "Name of route map\n"
7188 "Unknown heritage\n")
7191 argv_find(argv
, argc
, "A.B.C.D", &idx
);
7192 char *prefix
= argv
[idx
]->arg
;
7193 char *mask
= argv
[idx
+ 1]->arg
;
7195 char prefix_str
[BUFSIZ
];
7196 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
7199 vty_out(vty
, "%% Inconsistent address and mask\n");
7200 return CMD_WARNING_CONFIG_FAILED
;
7203 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
7206 DEFUN (ipv6_aggregate_address
,
7207 ipv6_aggregate_address_cmd
,
7208 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7209 "Configure BGP aggregate entries\n"
7210 "Aggregate prefix\n"
7211 "Generate AS set path information\n"
7212 "Filter more specific routes from updates\n"
7213 "Filter more specific routes from updates\n"
7214 "Generate AS set path information\n"
7215 "Apply route map to aggregate network\n"
7216 "Name of route map\n"
7220 "Unknown heritage\n")
7223 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7224 char *prefix
= argv
[idx
]->arg
;
7227 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7228 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7229 : AGGREGATE_AS_UNSET
;
7232 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7233 ? AGGREGATE_SUMMARY_ONLY
7236 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
7238 rmap
= argv
[idx
]->arg
;
7241 if (argv_find(argv
, argc
, "origin", &idx
)) {
7242 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7243 origin
= BGP_ORIGIN_IGP
;
7244 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7245 origin
= BGP_ORIGIN_EGP
;
7246 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7247 origin
= BGP_ORIGIN_INCOMPLETE
;
7250 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
7251 sum_only
, as_set
, origin
);
7254 DEFUN (no_ipv6_aggregate_address
,
7255 no_ipv6_aggregate_address_cmd
,
7256 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7258 "Configure BGP aggregate entries\n"
7259 "Aggregate prefix\n"
7260 "Generate AS set path information\n"
7261 "Filter more specific routes from updates\n"
7262 "Filter more specific routes from updates\n"
7263 "Generate AS set path information\n"
7264 "Apply route map to aggregate network\n"
7265 "Name of route map\n"
7269 "Unknown heritage\n")
7272 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7273 char *prefix
= argv
[idx
]->arg
;
7274 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7277 /* Redistribute route treatment. */
7278 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7279 const union g_addr
*nexthop
, ifindex_t ifindex
,
7280 enum nexthop_types_t nhtype
, uint32_t metric
,
7281 uint8_t type
, unsigned short instance
,
7284 struct bgp_path_info
*new;
7285 struct bgp_path_info
*bpi
;
7286 struct bgp_path_info rmap_path
;
7287 struct bgp_dest
*bn
;
7289 struct attr
*new_attr
;
7291 route_map_result_t ret
;
7292 struct bgp_redist
*red
;
7294 /* Make default attribute. */
7295 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7297 * This must not be NULL to satisfy Coverity SA
7299 assert(attr
.aspath
);
7302 case NEXTHOP_TYPE_IFINDEX
:
7304 case NEXTHOP_TYPE_IPV4
:
7305 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7306 attr
.nexthop
= nexthop
->ipv4
;
7308 case NEXTHOP_TYPE_IPV6
:
7309 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7310 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7311 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7313 case NEXTHOP_TYPE_BLACKHOLE
:
7314 switch (p
->family
) {
7316 attr
.nexthop
.s_addr
= INADDR_ANY
;
7319 memset(&attr
.mp_nexthop_global
, 0,
7320 sizeof(attr
.mp_nexthop_global
));
7321 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7326 attr
.nh_ifindex
= ifindex
;
7329 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7332 afi
= family2afi(p
->family
);
7334 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7336 struct attr attr_new
;
7338 /* Copy attribute for modification. */
7341 if (red
->redist_metric_flag
)
7342 attr_new
.med
= red
->redist_metric
;
7344 /* Apply route-map. */
7345 if (red
->rmap
.name
) {
7346 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7347 rmap_path
.peer
= bgp
->peer_self
;
7348 rmap_path
.attr
= &attr_new
;
7350 SET_FLAG(bgp
->peer_self
->rmap_type
,
7351 PEER_RMAP_TYPE_REDISTRIBUTE
);
7353 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7356 bgp
->peer_self
->rmap_type
= 0;
7358 if (ret
== RMAP_DENYMATCH
) {
7359 /* Free uninterned attribute. */
7360 bgp_attr_flush(&attr_new
);
7362 /* Unintern original. */
7363 aspath_unintern(&attr
.aspath
);
7364 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7369 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7370 bgp_attr_add_gshut_community(&attr_new
);
7372 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7373 SAFI_UNICAST
, p
, NULL
);
7375 new_attr
= bgp_attr_intern(&attr_new
);
7377 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
7378 if (bpi
->peer
== bgp
->peer_self
7379 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7383 /* Ensure the (source route) type is updated. */
7385 if (attrhash_cmp(bpi
->attr
, new_attr
)
7386 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7387 bgp_attr_unintern(&new_attr
);
7388 aspath_unintern(&attr
.aspath
);
7389 bgp_dest_unlock_node(bn
);
7392 /* The attribute is changed. */
7393 bgp_path_info_set_flag(bn
, bpi
,
7394 BGP_PATH_ATTR_CHANGED
);
7396 /* Rewrite BGP route information. */
7397 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7398 bgp_path_info_restore(bn
, bpi
);
7400 bgp_aggregate_decrement(
7401 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7402 bgp_attr_unintern(&bpi
->attr
);
7403 bpi
->attr
= new_attr
;
7404 bpi
->uptime
= bgp_clock();
7406 /* Process change. */
7407 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7409 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7410 bgp_dest_unlock_node(bn
);
7411 aspath_unintern(&attr
.aspath
);
7413 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7415 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7417 vpn_leak_from_vrf_update(
7418 bgp_get_default(), bgp
, bpi
);
7424 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7425 bgp
->peer_self
, new_attr
, bn
);
7426 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7428 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7429 bgp_path_info_add(bn
, new);
7430 bgp_dest_unlock_node(bn
);
7431 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7433 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7434 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7436 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7440 /* Unintern original. */
7441 aspath_unintern(&attr
.aspath
);
7444 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7445 unsigned short instance
)
7448 struct bgp_dest
*dest
;
7449 struct bgp_path_info
*pi
;
7450 struct bgp_redist
*red
;
7452 afi
= family2afi(p
->family
);
7454 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7456 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7457 SAFI_UNICAST
, p
, NULL
);
7459 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7460 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7464 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7465 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7467 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7470 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7471 bgp_path_info_delete(dest
, pi
);
7472 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7474 bgp_dest_unlock_node(dest
);
7478 /* Withdraw specified route type's route. */
7479 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7480 unsigned short instance
)
7482 struct bgp_dest
*dest
;
7483 struct bgp_path_info
*pi
;
7484 struct bgp_table
*table
;
7486 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7488 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
7489 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7490 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7491 && pi
->instance
== instance
)
7495 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7496 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7498 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7501 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
7502 pi
, afi
, SAFI_UNICAST
);
7503 bgp_path_info_delete(dest
, pi
);
7504 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7509 /* Static function to display route. */
7510 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
7511 json_object
*json
, bool wide
)
7517 if (p
->family
== AF_INET
) {
7521 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7524 json_object_string_add(json
, "prefix",
7525 inet_ntop(p
->family
,
7528 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7529 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7530 json_object_string_add(json
, "network", buf2
);
7532 } else if (p
->family
== AF_ETHERNET
) {
7533 prefix2str(p
, buf
, PREFIX_STRLEN
);
7534 len
= vty_out(vty
, "%s", buf
);
7535 } else if (p
->family
== AF_EVPN
) {
7539 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7542 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7543 } else if (p
->family
== AF_FLOWSPEC
) {
7544 route_vty_out_flowspec(vty
, p
, NULL
,
7546 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7547 NLRI_STRING_FORMAT_MIN
, json
);
7552 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7555 json_object_string_add(json
, "prefix",
7556 inet_ntop(p
->family
,
7559 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7560 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7561 json_object_string_add(json
, "network", buf2
);
7566 len
= wide
? (45 - len
) : (17 - len
);
7568 vty_out(vty
, "\n%*s", 20, " ");
7570 vty_out(vty
, "%*s", len
, " ");
7574 enum bgp_display_type
{
7578 /* Print the short form route status for a bgp_path_info */
7579 static void route_vty_short_status_out(struct vty
*vty
,
7580 struct bgp_path_info
*path
,
7581 json_object
*json_path
)
7585 /* Route status display. */
7586 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7587 json_object_boolean_true_add(json_path
, "removed");
7589 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7590 json_object_boolean_true_add(json_path
, "stale");
7592 if (path
->extra
&& path
->extra
->suppress
)
7593 json_object_boolean_true_add(json_path
, "suppressed");
7595 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7596 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7597 json_object_boolean_true_add(json_path
, "valid");
7600 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7601 json_object_boolean_true_add(json_path
, "history");
7603 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7604 json_object_boolean_true_add(json_path
, "damped");
7606 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7607 json_object_boolean_true_add(json_path
, "bestpath");
7609 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7610 json_object_boolean_true_add(json_path
, "multipath");
7612 /* Internal route. */
7613 if ((path
->peer
->as
)
7614 && (path
->peer
->as
== path
->peer
->local_as
))
7615 json_object_string_add(json_path
, "pathFrom",
7618 json_object_string_add(json_path
, "pathFrom",
7624 /* Route status display. */
7625 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7627 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7629 else if (path
->extra
&& path
->extra
->suppress
)
7631 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7632 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7638 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7640 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7642 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7644 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7649 /* Internal route. */
7650 if (path
->peer
&& (path
->peer
->as
)
7651 && (path
->peer
->as
== path
->peer
->local_as
))
7657 static char *bgp_nexthop_hostname(struct peer
*peer
,
7658 struct bgp_nexthop_cache
*bnc
)
7661 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
7662 return peer
->hostname
;
7666 /* called from terminal list command */
7667 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
7668 struct bgp_path_info
*path
, int display
, safi_t safi
,
7669 json_object
*json_paths
, bool wide
)
7672 struct attr
*attr
= path
->attr
;
7673 json_object
*json_path
= NULL
;
7674 json_object
*json_nexthops
= NULL
;
7675 json_object
*json_nexthop_global
= NULL
;
7676 json_object
*json_nexthop_ll
= NULL
;
7677 json_object
*json_ext_community
= NULL
;
7678 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7680 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7681 bool nexthop_othervrf
= false;
7682 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7683 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7684 char *nexthop_hostname
=
7685 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
7686 char esi_buf
[ESI_STR_LEN
];
7689 json_path
= json_object_new_object();
7691 /* short status lead text */
7692 route_vty_short_status_out(vty
, path
, json_path
);
7695 /* print prefix and mask */
7697 route_vty_out_route(p
, vty
, json_path
, wide
);
7699 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
7701 route_vty_out_route(p
, vty
, json_path
, wide
);
7705 * If vrf id of nexthop is different from that of prefix,
7706 * set up printable string to append
7708 if (path
->extra
&& path
->extra
->bgp_orig
) {
7709 const char *self
= "";
7714 nexthop_othervrf
= true;
7715 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7717 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7718 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7719 "@%s%s", VRFID_NONE_STR
, self
);
7721 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7722 path
->extra
->bgp_orig
->vrf_id
, self
);
7724 if (path
->extra
->bgp_orig
->inst_type
7725 != BGP_INSTANCE_TYPE_DEFAULT
)
7727 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7729 const char *self
= "";
7734 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7738 * For ENCAP and EVPN routes, nexthop address family is not
7739 * neccessarily the same as the prefix address family.
7740 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7741 * EVPN routes are also exchanged with a MP nexthop. Currently,
7743 * is only IPv4, the value will be present in either
7745 * attr->mp_nexthop_global_in
7747 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7750 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7754 snprintf(nexthop
, sizeof(nexthop
), "%s",
7755 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7759 snprintf(nexthop
, sizeof(nexthop
), "%s",
7760 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7764 snprintf(nexthop
, sizeof(nexthop
), "?");
7769 json_nexthop_global
= json_object_new_object();
7771 json_object_string_add(json_nexthop_global
, "ip",
7774 if (path
->peer
->hostname
)
7775 json_object_string_add(json_nexthop_global
,
7777 path
->peer
->hostname
);
7779 json_object_string_add(json_nexthop_global
, "afi",
7780 (af
== AF_INET
) ? "ipv4"
7782 json_object_boolean_true_add(json_nexthop_global
,
7785 if (nexthop_hostname
)
7786 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
7787 nexthop_hostname
, vrf_id_str
);
7789 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
7791 len
= wide
? (41 - len
) : (16 - len
);
7793 vty_out(vty
, "\n%*s", 36, " ");
7795 vty_out(vty
, "%*s", len
, " ");
7797 } else if (safi
== SAFI_EVPN
) {
7799 json_nexthop_global
= json_object_new_object();
7801 json_object_string_add(json_nexthop_global
, "ip",
7802 inet_ntoa(attr
->nexthop
));
7804 if (path
->peer
->hostname
)
7805 json_object_string_add(json_nexthop_global
,
7807 path
->peer
->hostname
);
7809 json_object_string_add(json_nexthop_global
, "afi",
7811 json_object_boolean_true_add(json_nexthop_global
,
7814 if (nexthop_hostname
)
7815 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7816 nexthop_hostname
, vrf_id_str
);
7818 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7821 len
= wide
? (41 - len
) : (16 - len
);
7823 vty_out(vty
, "\n%*s", 36, " ");
7825 vty_out(vty
, "%*s", len
, " ");
7827 } else if (safi
== SAFI_FLOWSPEC
) {
7828 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
7830 json_nexthop_global
= json_object_new_object();
7832 json_object_string_add(json_nexthop_global
,
7834 json_object_string_add(
7835 json_nexthop_global
, "ip",
7836 inet_ntoa(attr
->nexthop
));
7838 if (path
->peer
->hostname
)
7839 json_object_string_add(
7840 json_nexthop_global
, "hostname",
7841 path
->peer
->hostname
);
7843 json_object_boolean_true_add(
7844 json_nexthop_global
,
7847 if (nexthop_hostname
)
7848 len
= vty_out(vty
, "%pI4(%s)%s",
7853 len
= vty_out(vty
, "%pI4%s",
7857 len
= wide
? (41 - len
) : (16 - len
);
7859 vty_out(vty
, "\n%*s", 36, " ");
7861 vty_out(vty
, "%*s", len
, " ");
7864 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7866 json_nexthop_global
= json_object_new_object();
7868 json_object_string_add(json_nexthop_global
, "ip",
7869 inet_ntoa(attr
->nexthop
));
7871 if (path
->peer
->hostname
)
7872 json_object_string_add(json_nexthop_global
,
7874 path
->peer
->hostname
);
7876 json_object_string_add(json_nexthop_global
, "afi",
7878 json_object_boolean_true_add(json_nexthop_global
,
7881 if (nexthop_hostname
)
7882 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7883 nexthop_hostname
, vrf_id_str
);
7885 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7888 len
= wide
? (41 - len
) : (16 - len
);
7890 vty_out(vty
, "\n%*s", 36, " ");
7892 vty_out(vty
, "%*s", len
, " ");
7897 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7901 json_nexthop_global
= json_object_new_object();
7902 json_object_string_add(
7903 json_nexthop_global
, "ip",
7904 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7907 if (path
->peer
->hostname
)
7908 json_object_string_add(json_nexthop_global
,
7910 path
->peer
->hostname
);
7912 json_object_string_add(json_nexthop_global
, "afi",
7914 json_object_string_add(json_nexthop_global
, "scope",
7917 /* We display both LL & GL if both have been
7919 if ((attr
->mp_nexthop_len
7920 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7921 || (path
->peer
->conf_if
)) {
7922 json_nexthop_ll
= json_object_new_object();
7923 json_object_string_add(
7924 json_nexthop_ll
, "ip",
7926 &attr
->mp_nexthop_local
, buf
,
7929 if (path
->peer
->hostname
)
7930 json_object_string_add(
7931 json_nexthop_ll
, "hostname",
7932 path
->peer
->hostname
);
7934 json_object_string_add(json_nexthop_ll
, "afi",
7936 json_object_string_add(json_nexthop_ll
, "scope",
7939 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7940 &attr
->mp_nexthop_local
)
7942 && !attr
->mp_nexthop_prefer_global
)
7943 json_object_boolean_true_add(
7944 json_nexthop_ll
, "used");
7946 json_object_boolean_true_add(
7947 json_nexthop_global
, "used");
7949 json_object_boolean_true_add(
7950 json_nexthop_global
, "used");
7952 /* Display LL if LL/Global both in table unless
7953 * prefer-global is set */
7954 if (((attr
->mp_nexthop_len
7955 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7956 && !attr
->mp_nexthop_prefer_global
)
7957 || (path
->peer
->conf_if
)) {
7958 if (path
->peer
->conf_if
) {
7959 len
= vty_out(vty
, "%s",
7960 path
->peer
->conf_if
);
7961 /* len of IPv6 addr + max len of def
7963 len
= wide
? (41 - len
) : (16 - len
);
7966 vty_out(vty
, "\n%*s", 36, " ");
7968 vty_out(vty
, "%*s", len
, " ");
7970 if (nexthop_hostname
)
7973 &attr
->mp_nexthop_local
,
7979 &attr
->mp_nexthop_local
,
7982 len
= wide
? (41 - len
) : (16 - len
);
7985 vty_out(vty
, "\n%*s", 36, " ");
7987 vty_out(vty
, "%*s", len
, " ");
7990 if (nexthop_hostname
)
7991 len
= vty_out(vty
, "%pI6(%s)%s",
7992 &attr
->mp_nexthop_global
,
7996 len
= vty_out(vty
, "%pI6%s",
7997 &attr
->mp_nexthop_global
,
8000 len
= wide
? (41 - len
) : (16 - len
);
8003 vty_out(vty
, "\n%*s", 36, " ");
8005 vty_out(vty
, "%*s", len
, " ");
8011 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8013 json_object_int_add(json_path
, "metric", attr
->med
);
8015 vty_out(vty
, "%7u", attr
->med
);
8017 vty_out(vty
, "%10u", attr
->med
);
8018 else if (!json_paths
) {
8020 vty_out(vty
, "%*s", 7, " ");
8022 vty_out(vty
, "%*s", 10, " ");
8026 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8028 json_object_int_add(json_path
, "locPrf",
8031 vty_out(vty
, "%7u", attr
->local_pref
);
8032 else if (!json_paths
)
8036 json_object_int_add(json_path
, "weight", attr
->weight
);
8038 vty_out(vty
, "%7u ", attr
->weight
);
8042 json_object_string_add(
8043 json_path
, "peerId",
8044 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8050 json_object_string_add(json_path
, "path",
8053 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8058 json_object_string_add(json_path
, "origin",
8059 bgp_origin_long_str
[attr
->origin
]);
8061 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8064 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8065 json_object_string_add(json_path
, "esi",
8066 esi_to_str(&attr
->esi
,
8067 esi_buf
, sizeof(esi_buf
)));
8069 if (safi
== SAFI_EVPN
&&
8070 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8071 json_ext_community
= json_object_new_object();
8072 json_object_string_add(json_ext_community
,
8074 attr
->ecommunity
->str
);
8075 json_object_object_add(json_path
,
8076 "extendedCommunity",
8077 json_ext_community
);
8081 json_object_boolean_true_add(json_path
,
8082 "announceNexthopSelf");
8083 if (nexthop_othervrf
) {
8084 json_object_string_add(json_path
, "nhVrfName",
8087 json_object_int_add(json_path
, "nhVrfId",
8088 ((nexthop_vrfid
== VRF_UNKNOWN
)
8090 : (int)nexthop_vrfid
));
8095 if (json_nexthop_global
|| json_nexthop_ll
) {
8096 json_nexthops
= json_object_new_array();
8098 if (json_nexthop_global
)
8099 json_object_array_add(json_nexthops
,
8100 json_nexthop_global
);
8102 if (json_nexthop_ll
)
8103 json_object_array_add(json_nexthops
,
8106 json_object_object_add(json_path
, "nexthops",
8110 json_object_array_add(json_paths
, json_path
);
8114 if (safi
== SAFI_EVPN
) {
8115 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8116 vty_out(vty
, "%*s", 20, " ");
8117 vty_out(vty
, "ESI:%s\n",
8118 esi_to_str(&attr
->esi
,
8119 esi_buf
, sizeof(esi_buf
)));
8122 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8123 vty_out(vty
, "%*s", 20, " ");
8124 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8128 #ifdef ENABLE_BGP_VNC
8129 /* prints an additional line, indented, with VNC info, if
8131 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8132 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8137 /* called from terminal list command */
8138 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8139 struct attr
*attr
, safi_t safi
, bool use_json
,
8140 json_object
*json_ar
, bool wide
)
8142 json_object
*json_status
= NULL
;
8143 json_object
*json_net
= NULL
;
8147 /* Route status display. */
8149 json_status
= json_object_new_object();
8150 json_net
= json_object_new_object();
8157 /* print prefix and mask */
8159 if (safi
== SAFI_EVPN
)
8160 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8161 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8162 json_object_string_add(
8163 json_net
, "addrPrefix",
8164 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8166 json_object_int_add(json_net
, "prefixLen",
8168 prefix2str(p
, buff
, PREFIX_STRLEN
);
8169 json_object_string_add(json_net
, "network", buff
);
8172 route_vty_out_route(p
, vty
, NULL
, wide
);
8174 /* Print attribute */
8177 if (p
->family
== AF_INET
8178 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8179 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8180 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8181 json_object_string_add(
8182 json_net
, "nextHop",
8184 attr
->mp_nexthop_global_in
));
8186 json_object_string_add(
8187 json_net
, "nextHop",
8188 inet_ntoa(attr
->nexthop
));
8189 } else if (p
->family
== AF_INET6
8190 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8193 json_object_string_add(
8194 json_net
, "nextHopGlobal",
8196 &attr
->mp_nexthop_global
, buf
,
8198 } else if (p
->family
== AF_EVPN
&&
8199 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8200 json_object_string_add(json_net
,
8201 "nextHop", inet_ntoa(
8202 attr
->mp_nexthop_global_in
));
8205 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8206 json_object_int_add(json_net
, "metric",
8209 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8210 json_object_int_add(json_net
, "locPrf",
8213 json_object_int_add(json_net
, "weight", attr
->weight
);
8217 json_object_string_add(json_net
, "path",
8221 json_object_string_add(json_net
, "bgpOriginCode",
8222 bgp_origin_str
[attr
->origin
]);
8224 if (p
->family
== AF_INET
8225 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8226 || safi
== SAFI_EVPN
8227 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8228 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8229 || safi
== SAFI_EVPN
)
8230 vty_out(vty
, "%-16s",
8232 attr
->mp_nexthop_global_in
));
8234 vty_out(vty
, "%-41s",
8235 inet_ntoa(attr
->nexthop
));
8237 vty_out(vty
, "%-16s",
8238 inet_ntoa(attr
->nexthop
));
8239 } else if (p
->family
== AF_INET6
8240 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8246 &attr
->mp_nexthop_global
, buf
,
8248 len
= wide
? (41 - len
) : (16 - len
);
8250 vty_out(vty
, "\n%*s", 36, " ");
8252 vty_out(vty
, "%*s", len
, " ");
8255 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8257 vty_out(vty
, "%7u", attr
->med
);
8259 vty_out(vty
, "%10u", attr
->med
);
8265 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8266 vty_out(vty
, "%7u", attr
->local_pref
);
8270 vty_out(vty
, "%7u ", attr
->weight
);
8274 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8277 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8281 json_object_boolean_true_add(json_status
, "*");
8282 json_object_boolean_true_add(json_status
, ">");
8283 json_object_object_add(json_net
, "appliedStatusSymbols",
8286 prefix2str(p
, buff
, PREFIX_STRLEN
);
8287 json_object_object_add(json_ar
, buff
, json_net
);
8292 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
8293 struct bgp_path_info
*path
, int display
, safi_t safi
,
8296 json_object
*json_out
= NULL
;
8298 mpls_label_t label
= MPLS_INVALID_LABEL
;
8304 json_out
= json_object_new_object();
8306 /* short status lead text */
8307 route_vty_short_status_out(vty
, path
, json_out
);
8309 /* print prefix and mask */
8312 route_vty_out_route(p
, vty
, NULL
, false);
8314 vty_out(vty
, "%*s", 17, " ");
8317 /* Print attribute */
8319 if (((p
->family
== AF_INET
)
8320 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8321 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8322 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8323 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8324 || safi
== SAFI_EVPN
) {
8326 json_object_string_add(
8327 json_out
, "mpNexthopGlobalIn",
8328 inet_ntoa(attr
->mp_nexthop_global_in
));
8330 vty_out(vty
, "%-16s",
8331 inet_ntoa(attr
->mp_nexthop_global_in
));
8334 json_object_string_add(
8335 json_out
, "nexthop",
8336 inet_ntoa(attr
->nexthop
));
8338 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8340 } else if (((p
->family
== AF_INET6
)
8341 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8342 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8343 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8346 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8348 json_object_string_add(
8349 json_out
, "mpNexthopGlobalIn",
8351 &attr
->mp_nexthop_global
,
8352 buf_a
, sizeof(buf_a
)));
8356 &attr
->mp_nexthop_global
,
8357 buf_a
, sizeof(buf_a
)));
8358 } else if (attr
->mp_nexthop_len
8359 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8360 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8361 &attr
->mp_nexthop_global
,
8362 &attr
->mp_nexthop_local
);
8364 json_object_string_add(json_out
,
8365 "mpNexthopGlobalLocal",
8368 vty_out(vty
, "%s", buf_a
);
8372 label
= decode_label(&path
->extra
->label
[0]);
8374 if (bgp_is_valid_label(&label
)) {
8376 json_object_int_add(json_out
, "notag", label
);
8377 json_object_array_add(json
, json_out
);
8379 vty_out(vty
, "notag/%d", label
);
8385 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
8386 struct bgp_path_info
*path
, int display
,
8387 json_object
*json_paths
)
8390 char buf
[BUFSIZ
] = {0};
8391 json_object
*json_path
= NULL
;
8392 json_object
*json_nexthop
= NULL
;
8393 json_object
*json_overlay
= NULL
;
8399 json_path
= json_object_new_object();
8400 json_overlay
= json_object_new_object();
8401 json_nexthop
= json_object_new_object();
8404 /* short status lead text */
8405 route_vty_short_status_out(vty
, path
, json_path
);
8407 /* print prefix and mask */
8409 route_vty_out_route(p
, vty
, json_path
, false);
8411 vty_out(vty
, "%*s", 17, " ");
8413 /* Print attribute */
8416 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8420 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8422 vty_out(vty
, "%-16s", buf
);
8424 json_object_string_add(json_nexthop
, "ip", buf
);
8426 json_object_string_add(json_nexthop
, "afi", "ipv4");
8428 json_object_object_add(json_path
, "nexthop",
8433 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8434 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8436 vty_out(vty
, "%s(%s)", buf
, buf1
);
8438 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8440 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8443 json_object_string_add(json_nexthop
, "afi", "ipv6");
8445 json_object_object_add(json_path
, "nexthop",
8453 json_object_string_add(json_nexthop
, "Error",
8454 "Unsupported address-family");
8458 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8459 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8461 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8462 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8467 vty_out(vty
, "/%s", buf
);
8469 json_object_string_add(json_overlay
, "gw", buf
);
8471 if (attr
->ecommunity
) {
8473 struct ecommunity_val
*routermac
= ecommunity_lookup(
8474 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8475 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8478 mac
= ecom_mac2str((char *)routermac
->val
);
8481 vty_out(vty
, "/%s", mac
);
8483 json_object_string_add(json_overlay
, "rmac",
8486 XFREE(MTYPE_TMP
, mac
);
8493 json_object_object_add(json_path
, "overlay", json_overlay
);
8495 json_object_array_add(json_paths
, json_path
);
8499 /* dampening route */
8500 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8501 struct bgp_path_info
*path
, int display
,
8502 afi_t afi
, safi_t safi
, bool use_json
,
8507 char timebuf
[BGP_UPTIME_LEN
];
8509 /* short status lead text */
8510 route_vty_short_status_out(vty
, path
, json
);
8512 /* print prefix and mask */
8515 route_vty_out_route(p
, vty
, NULL
, false);
8517 vty_out(vty
, "%*s", 17, " ");
8520 len
= vty_out(vty
, "%s", path
->peer
->host
);
8524 vty_out(vty
, "\n%*s", 34, " ");
8527 json_object_int_add(json
, "peerHost", len
);
8529 vty_out(vty
, "%*s", len
, " ");
8533 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8534 safi
, use_json
, json
);
8537 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8538 BGP_UPTIME_LEN
, afi
, safi
,
8541 /* Print attribute */
8547 json_object_string_add(json
, "asPath",
8550 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8555 json_object_string_add(json
, "origin",
8556 bgp_origin_str
[attr
->origin
]);
8558 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8565 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8566 struct bgp_path_info
*path
, int display
,
8567 afi_t afi
, safi_t safi
, bool use_json
,
8571 struct bgp_damp_info
*bdi
;
8572 char timebuf
[BGP_UPTIME_LEN
];
8578 bdi
= path
->extra
->damp_info
;
8580 /* short status lead text */
8581 route_vty_short_status_out(vty
, path
, json
);
8583 /* print prefix and mask */
8586 route_vty_out_route(p
, vty
, NULL
, false);
8588 vty_out(vty
, "%*s", 17, " ");
8591 len
= vty_out(vty
, "%s", path
->peer
->host
);
8595 vty_out(vty
, "\n%*s", 33, " ");
8598 json_object_int_add(json
, "peerHost", len
);
8600 vty_out(vty
, "%*s", len
, " ");
8603 len
= vty_out(vty
, "%d", bdi
->flap
);
8610 json_object_int_add(json
, "bdiFlap", len
);
8612 vty_out(vty
, "%*s", len
, " ");
8616 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8619 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8620 BGP_UPTIME_LEN
, 0, NULL
));
8622 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8623 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8625 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8626 BGP_UPTIME_LEN
, afi
, safi
,
8630 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8631 BGP_UPTIME_LEN
, afi
,
8632 safi
, use_json
, json
));
8635 vty_out(vty
, "%*s ", 8, " ");
8638 /* Print attribute */
8644 json_object_string_add(json
, "asPath",
8647 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8652 json_object_string_add(json
, "origin",
8653 bgp_origin_str
[attr
->origin
]);
8655 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8661 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8662 int *first
, const char *header
,
8663 json_object
*json_adv_to
)
8665 char buf1
[INET6_ADDRSTRLEN
];
8666 json_object
*json_peer
= NULL
;
8669 /* 'advertised-to' is a dictionary of peers we have advertised
8671 * prefix too. The key is the peer's IP or swpX, the value is
8673 * hostname if we know it and "" if not.
8675 json_peer
= json_object_new_object();
8678 json_object_string_add(json_peer
, "hostname",
8682 json_object_object_add(json_adv_to
, peer
->conf_if
,
8685 json_object_object_add(
8687 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8691 vty_out(vty
, "%s", header
);
8696 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
8698 vty_out(vty
, " %s(%s)", peer
->hostname
,
8701 vty_out(vty
, " %s(%s)", peer
->hostname
,
8702 sockunion2str(&peer
->su
, buf1
,
8706 vty_out(vty
, " %s", peer
->conf_if
);
8709 sockunion2str(&peer
->su
, buf1
,
8715 static void route_vty_out_tx_ids(struct vty
*vty
,
8716 struct bgp_addpath_info_data
*d
)
8720 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8721 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8722 d
->addpath_tx_id
[i
],
8723 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8727 static const char *bgp_path_selection_reason2str(
8728 enum bgp_path_selection_reason reason
)
8731 case bgp_path_selection_none
:
8732 return "Nothing to Select";
8733 case bgp_path_selection_first
:
8734 return "First path received";
8735 case bgp_path_selection_evpn_sticky_mac
:
8736 return "EVPN Sticky Mac";
8737 case bgp_path_selection_evpn_seq
:
8738 return "EVPN sequence number";
8739 case bgp_path_selection_evpn_lower_ip
:
8740 return "EVPN lower IP";
8741 case bgp_path_selection_evpn_local_path
:
8742 return "EVPN local ES path";
8743 case bgp_path_selection_evpn_non_proxy
:
8744 return "EVPN non proxy";
8745 case bgp_path_selection_weight
:
8747 case bgp_path_selection_local_pref
:
8748 return "Local Pref";
8749 case bgp_path_selection_local_route
:
8750 return "Local Route";
8751 case bgp_path_selection_confed_as_path
:
8752 return "Confederation based AS Path";
8753 case bgp_path_selection_as_path
:
8755 case bgp_path_selection_origin
:
8757 case bgp_path_selection_med
:
8759 case bgp_path_selection_peer
:
8761 case bgp_path_selection_confed
:
8762 return "Confed Peer Type";
8763 case bgp_path_selection_igp_metric
:
8764 return "IGP Metric";
8765 case bgp_path_selection_older
:
8766 return "Older Path";
8767 case bgp_path_selection_router_id
:
8769 case bgp_path_selection_cluster_length
:
8770 return "Cluser length";
8771 case bgp_path_selection_stale
:
8772 return "Path Staleness";
8773 case bgp_path_selection_local_configured
:
8774 return "Locally configured route";
8775 case bgp_path_selection_neighbor_ip
:
8776 return "Neighbor IP";
8777 case bgp_path_selection_default
:
8778 return "Nothing left to compare";
8780 return "Invalid (internal error)";
8783 static void route_vty_out_detail_es_info(struct vty
*vty
,
8784 struct attr
*attr
, json_object
*json_path
)
8786 char esi_buf
[ESI_STR_LEN
];
8787 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
8788 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
8789 ATTR_ES_PEER_ROUTER
);
8790 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
8791 ATTR_ES_PEER_ACTIVE
);
8792 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
8793 ATTR_ES_PEER_PROXY
);
8795 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
8797 json_object
*json_es_info
= NULL
;
8799 json_object_string_add(
8802 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
8803 json_es_info
= json_object_new_object();
8805 json_object_boolean_true_add(
8806 json_es_info
, "localEs");
8808 json_object_boolean_true_add(
8809 json_es_info
, "peerActive");
8811 json_object_boolean_true_add(
8812 json_es_info
, "peerProxy");
8814 json_object_boolean_true_add(
8815 json_es_info
, "peerRouter");
8816 if (attr
->mm_sync_seqnum
)
8817 json_object_int_add(
8818 json_es_info
, "peerSeq",
8819 attr
->mm_sync_seqnum
);
8820 json_object_object_add(
8821 json_path
, "es_info",
8825 if (bgp_evpn_attr_is_sync(attr
))
8827 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
8829 es_local
? "local-es":"",
8830 peer_proxy
? "proxy " : "",
8831 peer_active
? "active ":"",
8832 peer_router
? "router ":"",
8833 attr
->mm_sync_seqnum
);
8835 vty_out(vty
, " ESI %s %s\n",
8837 es_local
? "local-es":"");
8841 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8842 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
8843 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8845 char buf
[INET6_ADDRSTRLEN
];
8847 char buf2
[EVPN_ROUTE_STRLEN
];
8848 struct attr
*attr
= path
->attr
;
8849 int sockunion_vty_out(struct vty
*, union sockunion
*);
8851 json_object
*json_bestpath
= NULL
;
8852 json_object
*json_cluster_list
= NULL
;
8853 json_object
*json_cluster_list_list
= NULL
;
8854 json_object
*json_ext_community
= NULL
;
8855 json_object
*json_last_update
= NULL
;
8856 json_object
*json_pmsi
= NULL
;
8857 json_object
*json_nexthop_global
= NULL
;
8858 json_object
*json_nexthop_ll
= NULL
;
8859 json_object
*json_nexthops
= NULL
;
8860 json_object
*json_path
= NULL
;
8861 json_object
*json_peer
= NULL
;
8862 json_object
*json_string
= NULL
;
8863 json_object
*json_adv_to
= NULL
;
8865 struct listnode
*node
, *nnode
;
8867 int addpath_capable
;
8869 unsigned int first_as
;
8871 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8873 char *nexthop_hostname
=
8874 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8877 json_path
= json_object_new_object();
8878 json_peer
= json_object_new_object();
8879 json_nexthop_global
= json_object_new_object();
8887 if (path
->extra
&& path
->extra
->num_labels
) {
8888 bgp_evpn_label2str(path
->extra
->label
,
8889 path
->extra
->num_labels
, tag_buf
,
8892 if (safi
== SAFI_EVPN
) {
8895 (struct prefix_evpn
*)
8896 bgp_dest_get_prefix(bn
),
8897 buf2
, sizeof(buf2
));
8898 vty_out(vty
, " Route %s", buf2
);
8899 if (tag_buf
[0] != '\0')
8900 vty_out(vty
, " VNI %s", tag_buf
);
8904 json_object_string_add(json_path
, "VNI",
8909 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8910 struct bgp_path_info
*parent_ri
;
8911 struct bgp_dest
*dest
, *pdest
;
8913 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8914 dest
= parent_ri
->net
;
8915 if (dest
&& dest
->pdest
) {
8916 pdest
= dest
->pdest
;
8918 (struct prefix_rd
*)bgp_dest_get_prefix(
8920 buf1
, sizeof(buf1
));
8921 if (is_pi_family_evpn(parent_ri
)) {
8923 (struct prefix_evpn
*)
8924 bgp_dest_get_prefix(
8926 buf2
, sizeof(buf2
));
8927 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8929 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8934 /* Line1 display AS-path, Aggregator */
8937 if (!attr
->aspath
->json
)
8938 aspath_str_update(attr
->aspath
, true);
8939 json_object_lock(attr
->aspath
->json
);
8940 json_object_object_add(json_path
, "aspath",
8941 attr
->aspath
->json
);
8943 if (attr
->aspath
->segments
)
8944 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8946 vty_out(vty
, " Local");
8950 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8952 json_object_boolean_true_add(json_path
, "removed");
8954 vty_out(vty
, ", (removed)");
8957 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8959 json_object_boolean_true_add(json_path
, "stale");
8961 vty_out(vty
, ", (stale)");
8964 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8966 json_object_int_add(json_path
, "aggregatorAs",
8967 attr
->aggregator_as
);
8968 json_object_string_add(
8969 json_path
, "aggregatorId",
8970 inet_ntoa(attr
->aggregator_addr
));
8971 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8972 json_object_boolean_true_add(
8973 json_path
, "aggregatorAsMalformed");
8975 json_object_boolean_false_add(
8976 json_path
, "aggregatorAsMalformed");
8978 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8980 ", (aggregated by %u(malformed) %s)",
8981 attr
->aggregator_as
,
8982 inet_ntoa(attr
->aggregator_addr
));
8984 vty_out(vty
, ", (aggregated by %u %s)",
8985 attr
->aggregator_as
,
8986 inet_ntoa(attr
->aggregator_addr
));
8990 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8991 PEER_FLAG_REFLECTOR_CLIENT
)) {
8993 json_object_boolean_true_add(json_path
,
8994 "rxedFromRrClient");
8996 vty_out(vty
, ", (Received from a RR-client)");
8999 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9000 PEER_FLAG_RSERVER_CLIENT
)) {
9002 json_object_boolean_true_add(json_path
,
9003 "rxedFromRsClient");
9005 vty_out(vty
, ", (Received from a RS-client)");
9008 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9010 json_object_boolean_true_add(json_path
,
9011 "dampeningHistoryEntry");
9013 vty_out(vty
, ", (history entry)");
9014 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9016 json_object_boolean_true_add(json_path
,
9017 "dampeningSuppressed");
9019 vty_out(vty
, ", (suppressed due to dampening)");
9025 /* Line2 display Next-hop, Neighbor, Router-id */
9026 /* Display the nexthop */
9027 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9029 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9030 || bn_p
->family
== AF_EVPN
)
9031 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9032 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9033 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9034 || safi
== SAFI_EVPN
) {
9036 json_object_string_add(
9037 json_nexthop_global
, "ip",
9038 inet_ntoa(attr
->mp_nexthop_global_in
));
9040 if (path
->peer
->hostname
)
9041 json_object_string_add(
9042 json_nexthop_global
, "hostname",
9043 path
->peer
->hostname
);
9045 if (nexthop_hostname
)
9046 vty_out(vty
, " %pI4(%s)",
9047 &attr
->mp_nexthop_global_in
,
9050 vty_out(vty
, " %pI4",
9051 &attr
->mp_nexthop_global_in
);
9055 json_object_string_add(
9056 json_nexthop_global
, "ip",
9057 inet_ntoa(attr
->nexthop
));
9059 if (path
->peer
->hostname
)
9060 json_object_string_add(
9061 json_nexthop_global
, "hostname",
9062 path
->peer
->hostname
);
9064 if (nexthop_hostname
)
9065 vty_out(vty
, " %pI4(%s)",
9069 vty_out(vty
, " %pI4",
9075 json_object_string_add(json_nexthop_global
, "afi",
9079 json_object_string_add(
9080 json_nexthop_global
, "ip",
9081 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9082 buf
, INET6_ADDRSTRLEN
));
9084 if (path
->peer
->hostname
)
9085 json_object_string_add(json_nexthop_global
,
9087 path
->peer
->hostname
);
9089 json_object_string_add(json_nexthop_global
, "afi",
9091 json_object_string_add(json_nexthop_global
, "scope",
9094 if (nexthop_hostname
)
9095 vty_out(vty
, " %pI6(%s)",
9096 &attr
->mp_nexthop_global
,
9099 vty_out(vty
, " %pI6",
9100 &attr
->mp_nexthop_global
);
9104 /* Display the IGP cost or 'inaccessible' */
9105 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9107 json_object_boolean_false_add(json_nexthop_global
,
9110 vty_out(vty
, " (inaccessible)");
9112 if (path
->extra
&& path
->extra
->igpmetric
) {
9114 json_object_int_add(json_nexthop_global
,
9116 path
->extra
->igpmetric
);
9118 vty_out(vty
, " (metric %u)",
9119 path
->extra
->igpmetric
);
9122 /* IGP cost is 0, display this only for json */
9125 json_object_int_add(json_nexthop_global
,
9130 json_object_boolean_true_add(json_nexthop_global
,
9134 /* Display peer "from" output */
9135 /* This path was originated locally */
9136 if (path
->peer
== bgp
->peer_self
) {
9138 if (safi
== SAFI_EVPN
9139 || (bn_p
->family
== AF_INET
9140 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9142 json_object_string_add(json_peer
, "peerId",
9145 vty_out(vty
, " from 0.0.0.0 ");
9148 json_object_string_add(json_peer
, "peerId",
9151 vty_out(vty
, " from :: ");
9155 json_object_string_add(json_peer
, "routerId",
9156 inet_ntoa(bgp
->router_id
));
9158 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
9161 /* We RXed this path from one of our peers */
9165 json_object_string_add(json_peer
, "peerId",
9166 sockunion2str(&path
->peer
->su
,
9169 json_object_string_add(json_peer
, "routerId",
9171 &path
->peer
->remote_id
,
9172 buf1
, sizeof(buf1
)));
9174 if (path
->peer
->hostname
)
9175 json_object_string_add(json_peer
, "hostname",
9176 path
->peer
->hostname
);
9178 if (path
->peer
->domainname
)
9179 json_object_string_add(json_peer
, "domainname",
9180 path
->peer
->domainname
);
9182 if (path
->peer
->conf_if
)
9183 json_object_string_add(json_peer
, "interface",
9184 path
->peer
->conf_if
);
9186 if (path
->peer
->conf_if
) {
9187 if (path
->peer
->hostname
9188 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9189 BGP_FLAG_SHOW_HOSTNAME
))
9190 vty_out(vty
, " from %s(%s)",
9191 path
->peer
->hostname
,
9192 path
->peer
->conf_if
);
9194 vty_out(vty
, " from %s",
9195 path
->peer
->conf_if
);
9197 if (path
->peer
->hostname
9198 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9199 BGP_FLAG_SHOW_HOSTNAME
))
9200 vty_out(vty
, " from %s(%s)",
9201 path
->peer
->hostname
,
9204 vty_out(vty
, " from %s",
9205 sockunion2str(&path
->peer
->su
,
9210 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9211 vty_out(vty
, " (%s)",
9212 inet_ntoa(attr
->originator_id
));
9214 vty_out(vty
, " (%s)",
9216 &path
->peer
->remote_id
, buf1
,
9222 * Note when vrfid of nexthop is different from that of prefix
9224 if (path
->extra
&& path
->extra
->bgp_orig
) {
9225 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9230 if (path
->extra
->bgp_orig
->inst_type
9231 == BGP_INSTANCE_TYPE_DEFAULT
)
9232 vn
= VRF_DEFAULT_NAME
;
9234 vn
= path
->extra
->bgp_orig
->name
;
9236 json_object_string_add(json_path
, "nhVrfName", vn
);
9238 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9239 json_object_int_add(json_path
, "nhVrfId", -1);
9241 json_object_int_add(json_path
, "nhVrfId",
9242 (int)nexthop_vrfid
);
9245 if (nexthop_vrfid
== VRF_UNKNOWN
)
9246 vty_out(vty
, " vrf ?");
9250 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9251 vty_out(vty
, " vrf %s(%u)",
9252 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9259 json_object_boolean_true_add(json_path
,
9260 "announceNexthopSelf");
9262 vty_out(vty
, " announce-nh-self");
9269 /* display the link-local nexthop */
9270 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9272 json_nexthop_ll
= json_object_new_object();
9273 json_object_string_add(
9274 json_nexthop_ll
, "ip",
9275 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9276 buf
, INET6_ADDRSTRLEN
));
9278 if (path
->peer
->hostname
)
9279 json_object_string_add(json_nexthop_ll
,
9281 path
->peer
->hostname
);
9283 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9284 json_object_string_add(json_nexthop_ll
, "scope",
9287 json_object_boolean_true_add(json_nexthop_ll
,
9290 if (!attr
->mp_nexthop_prefer_global
)
9291 json_object_boolean_true_add(json_nexthop_ll
,
9294 json_object_boolean_true_add(
9295 json_nexthop_global
, "used");
9297 vty_out(vty
, " (%s) %s\n",
9298 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9299 buf
, INET6_ADDRSTRLEN
),
9300 attr
->mp_nexthop_prefer_global
9305 /* If we do not have a link-local nexthop then we must flag the
9309 json_object_boolean_true_add(json_nexthop_global
,
9313 if (safi
== SAFI_EVPN
&&
9314 bgp_evpn_is_esi_valid(&attr
->esi
)) {
9315 route_vty_out_detail_es_info(vty
, attr
, json_path
);
9318 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9319 * Int/Ext/Local, Atomic, best */
9321 json_object_string_add(json_path
, "origin",
9322 bgp_origin_long_str
[attr
->origin
]);
9324 vty_out(vty
, " Origin %s",
9325 bgp_origin_long_str
[attr
->origin
]);
9327 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
9329 json_object_int_add(json_path
, "metric", attr
->med
);
9331 vty_out(vty
, ", metric %u", attr
->med
);
9334 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
9336 json_object_int_add(json_path
, "locPrf",
9339 vty_out(vty
, ", localpref %u", attr
->local_pref
);
9342 if (attr
->weight
!= 0) {
9344 json_object_int_add(json_path
, "weight", attr
->weight
);
9346 vty_out(vty
, ", weight %u", attr
->weight
);
9349 if (attr
->tag
!= 0) {
9351 json_object_int_add(json_path
, "tag", attr
->tag
);
9353 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9356 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9358 json_object_boolean_false_add(json_path
, "valid");
9360 vty_out(vty
, ", invalid");
9361 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9363 json_object_boolean_true_add(json_path
, "valid");
9365 vty_out(vty
, ", valid");
9368 if (path
->peer
!= bgp
->peer_self
) {
9369 if (path
->peer
->as
== path
->peer
->local_as
) {
9370 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9372 json_object_string_add(
9376 vty_out(vty
, ", confed-internal");
9379 json_object_string_add(
9380 json_peer
, "type", "internal");
9382 vty_out(vty
, ", internal");
9385 if (bgp_confederation_peers_check(bgp
,
9388 json_object_string_add(
9392 vty_out(vty
, ", confed-external");
9395 json_object_string_add(
9396 json_peer
, "type", "external");
9398 vty_out(vty
, ", external");
9401 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9403 json_object_boolean_true_add(json_path
, "aggregated");
9404 json_object_boolean_true_add(json_path
, "local");
9406 vty_out(vty
, ", aggregated, local");
9408 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9410 json_object_boolean_true_add(json_path
, "sourced");
9412 vty_out(vty
, ", sourced");
9415 json_object_boolean_true_add(json_path
, "sourced");
9416 json_object_boolean_true_add(json_path
, "local");
9418 vty_out(vty
, ", sourced, local");
9422 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9424 json_object_boolean_true_add(json_path
,
9427 vty_out(vty
, ", atomic-aggregate");
9430 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9431 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9432 && bgp_path_info_mpath_count(path
))) {
9434 json_object_boolean_true_add(json_path
, "multipath");
9436 vty_out(vty
, ", multipath");
9439 // Mark the bestpath(s)
9440 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9441 first_as
= aspath_get_first_as(attr
->aspath
);
9445 json_bestpath
= json_object_new_object();
9446 json_object_int_add(json_bestpath
, "bestpathFromAs",
9450 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9452 vty_out(vty
, ", bestpath-from-AS Local");
9456 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9459 json_bestpath
= json_object_new_object();
9460 json_object_boolean_true_add(json_bestpath
, "overall");
9461 json_object_string_add(
9462 json_bestpath
, "selectionReason",
9463 bgp_path_selection_reason2str(bn
->reason
));
9465 vty_out(vty
, ", best");
9466 vty_out(vty
, " (%s)",
9467 bgp_path_selection_reason2str(bn
->reason
));
9472 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9477 /* Line 4 display Community */
9478 if (attr
->community
) {
9480 if (!attr
->community
->json
)
9481 community_str(attr
->community
, true);
9482 json_object_lock(attr
->community
->json
);
9483 json_object_object_add(json_path
, "community",
9484 attr
->community
->json
);
9486 vty_out(vty
, " Community: %s\n",
9487 attr
->community
->str
);
9491 /* Line 5 display Extended-community */
9492 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9494 json_ext_community
= json_object_new_object();
9495 json_object_string_add(json_ext_community
, "string",
9496 attr
->ecommunity
->str
);
9497 json_object_object_add(json_path
, "extendedCommunity",
9498 json_ext_community
);
9500 vty_out(vty
, " Extended Community: %s\n",
9501 attr
->ecommunity
->str
);
9505 /* Line 6 display Large community */
9506 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9508 if (!attr
->lcommunity
->json
)
9509 lcommunity_str(attr
->lcommunity
, true);
9510 json_object_lock(attr
->lcommunity
->json
);
9511 json_object_object_add(json_path
, "largeCommunity",
9512 attr
->lcommunity
->json
);
9514 vty_out(vty
, " Large Community: %s\n",
9515 attr
->lcommunity
->str
);
9519 /* Line 7 display Originator, Cluster-id */
9520 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9521 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9522 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9524 json_object_string_add(
9525 json_path
, "originatorId",
9526 inet_ntoa(attr
->originator_id
));
9528 vty_out(vty
, " Originator: %s",
9529 inet_ntoa(attr
->originator_id
));
9532 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9536 json_cluster_list
= json_object_new_object();
9537 json_cluster_list_list
=
9538 json_object_new_array();
9540 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9542 json_string
= json_object_new_string(
9543 inet_ntoa(attr
->cluster
9545 json_object_array_add(
9546 json_cluster_list_list
,
9551 * struct cluster_list does not have
9552 * "str" variable like aspath and community
9553 * do. Add this someday if someone asks
9555 * json_object_string_add(json_cluster_list,
9556 * "string", attr->cluster->str);
9558 json_object_object_add(json_cluster_list
,
9560 json_cluster_list_list
);
9561 json_object_object_add(json_path
, "clusterList",
9564 vty_out(vty
, ", Cluster list: ");
9566 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9569 inet_ntoa(attr
->cluster
9579 if (path
->extra
&& path
->extra
->damp_info
)
9580 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9583 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9584 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9585 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9588 json_object_int_add(json_path
, "remoteLabel", label
);
9590 vty_out(vty
, " Remote label: %d\n", label
);
9594 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9595 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9597 json_object_string_add(json_path
, "remoteSid", buf
);
9599 vty_out(vty
, " Remote SID: %s\n", buf
);
9603 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9605 json_object_int_add(json_path
, "labelIndex",
9608 vty_out(vty
, " Label Index: %d\n",
9612 /* Line 8 display Addpath IDs */
9613 if (path
->addpath_rx_id
9614 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9616 json_object_int_add(json_path
, "addpathRxId",
9617 path
->addpath_rx_id
);
9619 /* Keep backwards compatibility with the old API
9620 * by putting TX All's ID in the old field
9622 json_object_int_add(
9623 json_path
, "addpathTxId",
9625 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9627 /* ... but create a specific field for each
9630 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9631 json_object_int_add(
9633 bgp_addpath_names(i
)->id_json_name
,
9634 path
->tx_addpath
.addpath_tx_id
[i
]);
9637 vty_out(vty
, " AddPath ID: RX %u, ",
9638 path
->addpath_rx_id
);
9640 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9644 /* If we used addpath to TX a non-bestpath we need to display
9645 * "Advertised to" on a path-by-path basis
9647 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9650 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9652 bgp_addpath_encode_tx(peer
, afi
, safi
);
9653 has_adj
= bgp_adj_out_lookup(
9655 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9656 &path
->tx_addpath
));
9658 if ((addpath_capable
&& has_adj
)
9659 || (!addpath_capable
&& has_adj
9660 && CHECK_FLAG(path
->flags
,
9661 BGP_PATH_SELECTED
))) {
9662 if (json_path
&& !json_adv_to
)
9663 json_adv_to
= json_object_new_object();
9665 route_vty_out_advertised_to(
9667 " Advertised to:", json_adv_to
);
9673 json_object_object_add(
9674 json_path
, "advertisedTo", json_adv_to
);
9683 /* Line 9 display Uptime */
9684 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9686 json_last_update
= json_object_new_object();
9687 json_object_int_add(json_last_update
, "epoch", tbuf
);
9688 json_object_string_add(json_last_update
, "string",
9690 json_object_object_add(json_path
, "lastUpdate",
9693 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9695 /* Line 10 display PMSI tunnel attribute, if present */
9696 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9698 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9699 PMSI_TNLTYPE_STR_DEFAULT
);
9702 json_pmsi
= json_object_new_object();
9703 json_object_string_add(json_pmsi
, "tunnelType", str
);
9704 json_object_int_add(json_pmsi
, "label",
9705 label2vni(&attr
->label
));
9706 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9708 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9709 str
, label2vni(&attr
->label
));
9712 /* We've constructed the json object for this path, add it to the json
9716 if (json_nexthop_global
|| json_nexthop_ll
) {
9717 json_nexthops
= json_object_new_array();
9719 if (json_nexthop_global
)
9720 json_object_array_add(json_nexthops
,
9721 json_nexthop_global
);
9723 if (json_nexthop_ll
)
9724 json_object_array_add(json_nexthops
,
9727 json_object_object_add(json_path
, "nexthops",
9731 json_object_object_add(json_path
, "peer", json_peer
);
9732 json_object_array_add(json_paths
, json_path
);
9736 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9737 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9738 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9740 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9741 const char *prefix_list_str
, afi_t afi
,
9742 safi_t safi
, enum bgp_show_type type
);
9743 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9744 const char *filter
, afi_t afi
, safi_t safi
,
9745 enum bgp_show_type type
);
9746 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9747 const char *rmap_str
, afi_t afi
, safi_t safi
,
9748 enum bgp_show_type type
);
9749 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9750 const char *com
, int exact
, afi_t afi
,
9752 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9753 const char *prefix
, afi_t afi
, safi_t safi
,
9754 enum bgp_show_type type
);
9755 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9756 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9758 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9759 const char *comstr
, int exact
, afi_t afi
,
9760 safi_t safi
, bool use_json
);
9763 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9764 struct bgp_table
*table
, enum bgp_show_type type
,
9765 void *output_arg
, bool use_json
, char *rd
,
9766 int is_last
, unsigned long *output_cum
,
9767 unsigned long *total_cum
,
9768 unsigned long *json_header_depth
, bool wide
)
9770 struct bgp_path_info
*pi
;
9771 struct bgp_dest
*dest
;
9774 unsigned long output_count
= 0;
9775 unsigned long total_count
= 0;
9777 json_object
*json_paths
= NULL
;
9780 if (output_cum
&& *output_cum
!= 0)
9783 if (use_json
&& !*json_header_depth
) {
9785 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9786 " \"localAS\": %u,\n \"routes\": { ",
9787 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9788 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9791 table
->version
, inet_ntoa(bgp
->router_id
),
9792 bgp
->default_local_pref
, bgp
->as
);
9793 *json_header_depth
= 2;
9795 vty_out(vty
, " \"routeDistinguishers\" : {");
9796 ++*json_header_depth
;
9800 if (use_json
&& rd
) {
9801 vty_out(vty
, " \"%s\" : { ", rd
);
9804 /* Start processing of routes. */
9805 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
9806 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
9808 pi
= bgp_dest_get_bgp_path_info(dest
);
9814 json_paths
= json_object_new_array();
9818 for (; pi
; pi
= pi
->next
) {
9820 if (type
== bgp_show_type_flap_statistics
9821 || type
== bgp_show_type_flap_neighbor
9822 || type
== bgp_show_type_dampend_paths
9823 || type
== bgp_show_type_damp_neighbor
) {
9824 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9827 if (type
== bgp_show_type_regexp
) {
9828 regex_t
*regex
= output_arg
;
9830 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9834 if (type
== bgp_show_type_prefix_list
) {
9835 struct prefix_list
*plist
= output_arg
;
9837 if (prefix_list_apply(plist
, dest_p
)
9841 if (type
== bgp_show_type_filter_list
) {
9842 struct as_list
*as_list
= output_arg
;
9844 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9845 != AS_FILTER_PERMIT
)
9848 if (type
== bgp_show_type_route_map
) {
9849 struct route_map
*rmap
= output_arg
;
9850 struct bgp_path_info path
;
9851 struct attr dummy_attr
;
9852 route_map_result_t ret
;
9854 dummy_attr
= *pi
->attr
;
9856 path
.peer
= pi
->peer
;
9857 path
.attr
= &dummy_attr
;
9859 ret
= route_map_apply(rmap
, dest_p
, RMAP_BGP
,
9861 if (ret
== RMAP_DENYMATCH
)
9864 if (type
== bgp_show_type_neighbor
9865 || type
== bgp_show_type_flap_neighbor
9866 || type
== bgp_show_type_damp_neighbor
) {
9867 union sockunion
*su
= output_arg
;
9869 if (pi
->peer
== NULL
9870 || pi
->peer
->su_remote
== NULL
9871 || !sockunion_same(pi
->peer
->su_remote
, su
))
9874 if (type
== bgp_show_type_cidr_only
) {
9875 uint32_t destination
;
9877 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
9878 if (IN_CLASSC(destination
)
9879 && dest_p
->prefixlen
== 24)
9881 if (IN_CLASSB(destination
)
9882 && dest_p
->prefixlen
== 16)
9884 if (IN_CLASSA(destination
)
9885 && dest_p
->prefixlen
== 8)
9888 if (type
== bgp_show_type_prefix_longer
) {
9890 if (!prefix_match(p
, dest_p
))
9893 if (type
== bgp_show_type_community_all
) {
9894 if (!pi
->attr
->community
)
9897 if (type
== bgp_show_type_community
) {
9898 struct community
*com
= output_arg
;
9900 if (!pi
->attr
->community
9901 || !community_match(pi
->attr
->community
,
9905 if (type
== bgp_show_type_community_exact
) {
9906 struct community
*com
= output_arg
;
9908 if (!pi
->attr
->community
9909 || !community_cmp(pi
->attr
->community
, com
))
9912 if (type
== bgp_show_type_community_list
) {
9913 struct community_list
*list
= output_arg
;
9915 if (!community_list_match(pi
->attr
->community
,
9919 if (type
== bgp_show_type_community_list_exact
) {
9920 struct community_list
*list
= output_arg
;
9922 if (!community_list_exact_match(
9923 pi
->attr
->community
, list
))
9926 if (type
== bgp_show_type_lcommunity
) {
9927 struct lcommunity
*lcom
= output_arg
;
9929 if (!pi
->attr
->lcommunity
9930 || !lcommunity_match(pi
->attr
->lcommunity
,
9935 if (type
== bgp_show_type_lcommunity_exact
) {
9936 struct lcommunity
*lcom
= output_arg
;
9938 if (!pi
->attr
->lcommunity
9939 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9943 if (type
== bgp_show_type_lcommunity_list
) {
9944 struct community_list
*list
= output_arg
;
9946 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9951 == bgp_show_type_lcommunity_list_exact
) {
9952 struct community_list
*list
= output_arg
;
9954 if (!lcommunity_list_exact_match(
9955 pi
->attr
->lcommunity
, list
))
9958 if (type
== bgp_show_type_lcommunity_all
) {
9959 if (!pi
->attr
->lcommunity
)
9962 if (type
== bgp_show_type_dampend_paths
9963 || type
== bgp_show_type_damp_neighbor
) {
9964 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9965 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9969 if (!use_json
&& header
) {
9970 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
9972 inet_ntoa(bgp
->router_id
));
9973 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9974 vty_out(vty
, "%s", VRFID_NONE_STR
);
9976 vty_out(vty
, "%u", bgp
->vrf_id
);
9978 vty_out(vty
, "Default local pref %u, ",
9979 bgp
->default_local_pref
);
9980 vty_out(vty
, "local AS %u\n", bgp
->as
);
9981 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9982 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9983 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9984 if (type
== bgp_show_type_dampend_paths
9985 || type
== bgp_show_type_damp_neighbor
)
9986 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9987 else if (type
== bgp_show_type_flap_statistics
9988 || type
== bgp_show_type_flap_neighbor
)
9989 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9991 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
9992 : BGP_SHOW_HEADER
));
9995 if (rd
!= NULL
&& !display
&& !output_count
) {
9998 "Route Distinguisher: %s\n",
10001 if (type
== bgp_show_type_dampend_paths
10002 || type
== bgp_show_type_damp_neighbor
)
10003 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10004 AFI_IP
, safi
, use_json
,
10006 else if (type
== bgp_show_type_flap_statistics
10007 || type
== bgp_show_type_flap_neighbor
)
10008 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10009 AFI_IP
, safi
, use_json
,
10012 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10022 /* encode prefix */
10023 if (dest_p
->family
== AF_FLOWSPEC
) {
10024 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10027 bgp_fs_nlri_get_string(
10029 dest_p
->u
.prefix_flowspec
.ptr
,
10030 dest_p
->u
.prefix_flowspec
.prefixlen
,
10031 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10032 family2afi(dest_p
->u
10033 .prefix_flowspec
.family
));
10035 vty_out(vty
, "\"%s/%d\": ", retstr
,
10036 dest_p
->u
.prefix_flowspec
10039 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10040 dest_p
->u
.prefix_flowspec
10044 vty_out(vty
, "\"%pFX\": ", dest_p
);
10046 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10049 json_object_to_json_string_ext(
10050 json_paths
, JSON_C_TO_STRING_PRETTY
));
10051 json_object_free(json_paths
);
10055 json_object_free(json_paths
);
10059 output_count
+= *output_cum
;
10060 *output_cum
= output_count
;
10063 total_count
+= *total_cum
;
10064 *total_cum
= total_count
;
10068 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10072 for (i
= 0; i
< *json_header_depth
; ++i
)
10073 vty_out(vty
, " } ");
10074 vty_out(vty
, "\n");
10078 /* No route is displayed */
10079 if (output_count
== 0) {
10080 if (type
== bgp_show_type_normal
)
10082 "No BGP prefixes displayed, %ld exist\n",
10086 "\nDisplayed %ld routes and %ld total paths\n",
10087 output_count
, total_count
);
10091 return CMD_SUCCESS
;
10094 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10095 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10096 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10098 struct bgp_dest
*dest
, *next
;
10099 unsigned long output_cum
= 0;
10100 unsigned long total_cum
= 0;
10101 unsigned long json_header_depth
= 0;
10102 struct bgp_table
*itable
;
10105 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10107 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10108 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10110 next
= bgp_route_next(dest
);
10111 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10114 itable
= bgp_dest_get_bgp_table_info(dest
);
10115 if (itable
!= NULL
) {
10116 struct prefix_rd prd
;
10117 char rd
[RD_ADDRSTRLEN
];
10119 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10120 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10121 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10122 use_json
, rd
, next
== NULL
, &output_cum
,
10123 &total_cum
, &json_header_depth
, false);
10129 if (output_cum
== 0)
10130 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10134 "\nDisplayed %ld routes and %ld total paths\n",
10135 output_cum
, total_cum
);
10137 return CMD_SUCCESS
;
10139 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10140 enum bgp_show_type type
, void *output_arg
, bool use_json
,
10143 struct bgp_table
*table
;
10144 unsigned long json_header_depth
= 0;
10147 bgp
= bgp_get_default();
10152 vty_out(vty
, "No BGP process is configured\n");
10154 vty_out(vty
, "{}\n");
10155 return CMD_WARNING
;
10158 table
= bgp
->rib
[afi
][safi
];
10159 /* use MPLS and ENCAP specific shows until they are merged */
10160 if (safi
== SAFI_MPLS_VPN
) {
10161 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10162 output_arg
, use_json
);
10165 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10166 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10167 output_arg
, use_json
,
10170 /* labeled-unicast routes live in the unicast table */
10171 else if (safi
== SAFI_LABELED_UNICAST
)
10172 safi
= SAFI_UNICAST
;
10174 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
10175 NULL
, 1, NULL
, NULL
, &json_header_depth
, wide
);
10178 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10179 safi_t safi
, bool use_json
,
10182 struct listnode
*node
, *nnode
;
10185 bool route_output
= false;
10188 vty_out(vty
, "{\n");
10190 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10191 route_output
= true;
10194 vty_out(vty
, ",\n");
10198 vty_out(vty
, "\"%s\":",
10199 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10203 vty_out(vty
, "\nInstance %s:\n",
10204 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10208 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10213 vty_out(vty
, "}\n");
10214 else if (!route_output
)
10215 vty_out(vty
, "%% BGP instance not found\n");
10218 /* Header of detailed BGP route information */
10219 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10220 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10221 afi_t afi
, safi_t safi
, json_object
*json
)
10223 struct bgp_path_info
*pi
;
10224 const struct prefix
*p
;
10226 struct listnode
*node
, *nnode
;
10227 char buf1
[RD_ADDRSTRLEN
];
10228 char buf2
[INET6_ADDRSTRLEN
];
10229 char buf3
[EVPN_ROUTE_STRLEN
];
10230 char prefix_str
[BUFSIZ
];
10234 int accept_own
= 0;
10235 int route_filter_translated_v4
= 0;
10236 int route_filter_v4
= 0;
10237 int route_filter_translated_v6
= 0;
10238 int route_filter_v6
= 0;
10239 int llgr_stale
= 0;
10241 int accept_own_nexthop
= 0;
10244 int no_advertise
= 0;
10248 int has_valid_label
= 0;
10249 mpls_label_t label
= 0;
10250 json_object
*json_adv_to
= NULL
;
10252 p
= bgp_dest_get_prefix(dest
);
10253 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10255 if (has_valid_label
)
10256 label
= label_pton(&dest
->local_label
);
10258 if (safi
== SAFI_EVPN
) {
10261 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
10262 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10263 : "", prd
? ":" : "",
10264 bgp_evpn_route2str((struct prefix_evpn
*)p
,
10265 buf3
, sizeof(buf3
)));
10267 json_object_string_add(json
, "rd",
10268 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
10270 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
10274 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
10275 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
10276 ? prefix_rd2str(prd
, buf1
,
10279 safi
== SAFI_MPLS_VPN
? ":" : "",
10280 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
10285 json_object_string_add(json
, "prefix",
10286 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
10289 if (has_valid_label
) {
10291 json_object_int_add(json
, "localLabel", label
);
10293 vty_out(vty
, "Local label: %d\n", label
);
10297 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
10298 vty_out(vty
, "not allocated\n");
10300 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
10302 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
10304 if (pi
->extra
&& pi
->extra
->suppress
)
10307 if (pi
->attr
->community
== NULL
)
10310 no_advertise
+= community_include(
10311 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
10312 no_export
+= community_include(pi
->attr
->community
,
10313 COMMUNITY_NO_EXPORT
);
10314 local_as
+= community_include(pi
->attr
->community
,
10315 COMMUNITY_LOCAL_AS
);
10316 accept_own
+= community_include(pi
->attr
->community
,
10317 COMMUNITY_ACCEPT_OWN
);
10318 route_filter_translated_v4
+= community_include(
10319 pi
->attr
->community
,
10320 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
10321 route_filter_translated_v6
+= community_include(
10322 pi
->attr
->community
,
10323 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
10324 route_filter_v4
+= community_include(
10325 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
10326 route_filter_v6
+= community_include(
10327 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
10328 llgr_stale
+= community_include(pi
->attr
->community
,
10329 COMMUNITY_LLGR_STALE
);
10330 no_llgr
+= community_include(pi
->attr
->community
,
10331 COMMUNITY_NO_LLGR
);
10332 accept_own_nexthop
+=
10333 community_include(pi
->attr
->community
,
10334 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
10335 blackhole
+= community_include(pi
->attr
->community
,
10336 COMMUNITY_BLACKHOLE
);
10337 no_peer
+= community_include(pi
->attr
->community
,
10338 COMMUNITY_NO_PEER
);
10343 vty_out(vty
, "Paths: (%d available", count
);
10345 vty_out(vty
, ", best #%d", best
);
10346 if (safi
== SAFI_UNICAST
) {
10347 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10348 vty_out(vty
, ", table %s",
10351 vty_out(vty
, ", vrf %s",
10355 vty_out(vty
, ", no best path");
10359 ", accept own local route exported and imported in different VRF");
10360 else if (route_filter_translated_v4
)
10362 ", mark translated RTs for VPNv4 route filtering");
10363 else if (route_filter_v4
)
10365 ", attach RT as-is for VPNv4 route filtering");
10366 else if (route_filter_translated_v6
)
10368 ", mark translated RTs for VPNv6 route filtering");
10369 else if (route_filter_v6
)
10371 ", attach RT as-is for VPNv6 route filtering");
10372 else if (llgr_stale
)
10374 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10377 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10378 else if (accept_own_nexthop
)
10380 ", accept local nexthop");
10381 else if (blackhole
)
10382 vty_out(vty
, ", inform peer to blackhole prefix");
10383 else if (no_export
)
10384 vty_out(vty
, ", not advertised to EBGP peer");
10385 else if (no_advertise
)
10386 vty_out(vty
, ", not advertised to any peer");
10388 vty_out(vty
, ", not advertised outside local AS");
10391 ", inform EBGP peer not to advertise to their EBGP peers");
10395 ", Advertisements suppressed by an aggregate.");
10396 vty_out(vty
, ")\n");
10399 /* If we are not using addpath then we can display Advertised to and
10401 * show what peers we advertised the bestpath to. If we are using
10403 * though then we must display Advertised to on a path-by-path basis. */
10404 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10405 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10406 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
10407 if (json
&& !json_adv_to
)
10408 json_adv_to
= json_object_new_object();
10410 route_vty_out_advertised_to(
10412 " Advertised to non peer-group peers:\n ",
10419 json_object_object_add(json
, "advertisedTo",
10424 vty_out(vty
, " Not advertised to any peer");
10425 vty_out(vty
, "\n");
10430 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10431 struct bgp_dest
*bgp_node
, struct vty
*vty
,
10432 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10433 json_object
*json
, enum bgp_path_type pathtype
,
10436 struct bgp_path_info
*pi
;
10438 char rdbuf
[RD_ADDRSTRLEN
];
10439 json_object
*json_header
= NULL
;
10440 json_object
*json_paths
= NULL
;
10442 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
10444 if (json
&& !json_paths
) {
10445 /* Instantiate json_paths only if path is valid */
10446 json_paths
= json_object_new_array();
10448 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10449 json_header
= json_object_new_object();
10451 json_header
= json
;
10455 route_vty_out_detail_header(
10456 vty
, bgp
, bgp_node
, pfx_rd
,
10457 AFI_IP
, safi
, json_header
);
10462 if (pathtype
== BGP_PATH_SHOW_ALL
10463 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10464 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10465 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10466 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10467 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10468 route_vty_out_detail(vty
, bgp
, bgp_node
,
10473 if (json
&& json_paths
) {
10474 json_object_object_add(json_header
, "paths", json_paths
);
10477 json_object_object_add(json
, rdbuf
, json_header
);
10481 /* Display specified route of BGP table. */
10482 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10483 struct bgp_table
*rib
, const char *ip_str
,
10484 afi_t afi
, safi_t safi
,
10485 struct prefix_rd
*prd
, int prefix_check
,
10486 enum bgp_path_type pathtype
, bool use_json
)
10490 struct prefix match
;
10491 struct bgp_dest
*dest
;
10492 struct bgp_dest
*rm
;
10493 struct bgp_table
*table
;
10494 json_object
*json
= NULL
;
10495 json_object
*json_paths
= NULL
;
10497 /* Check IP address argument. */
10498 ret
= str2prefix(ip_str
, &match
);
10500 vty_out(vty
, "address is malformed\n");
10501 return CMD_WARNING
;
10504 match
.family
= afi2family(afi
);
10507 json
= json_object_new_object();
10509 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10510 for (dest
= bgp_table_top(rib
); dest
;
10511 dest
= bgp_route_next(dest
)) {
10512 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10514 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
10516 table
= bgp_dest_get_bgp_table_info(dest
);
10520 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10523 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
10525 && rm_p
->prefixlen
!= match
.prefixlen
) {
10526 bgp_dest_unlock_node(rm
);
10530 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10531 bgp
, afi
, safi
, json
, pathtype
,
10534 bgp_dest_unlock_node(rm
);
10536 } else if (safi
== SAFI_EVPN
) {
10537 struct bgp_dest
*longest_pfx
;
10538 bool is_exact_pfxlen_match
= false;
10540 for (dest
= bgp_table_top(rib
); dest
;
10541 dest
= bgp_route_next(dest
)) {
10542 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10544 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
10546 table
= bgp_dest_get_bgp_table_info(dest
);
10550 longest_pfx
= NULL
;
10551 is_exact_pfxlen_match
= false;
10553 * Search through all the prefixes for a match. The
10554 * pfx's are enumerated in ascending order of pfxlens.
10555 * So, the last pfx match is the longest match. Set
10556 * is_exact_pfxlen_match when we get exact pfxlen match
10558 for (rm
= bgp_table_top(table
); rm
;
10559 rm
= bgp_route_next(rm
)) {
10560 const struct prefix
*rm_p
=
10561 bgp_dest_get_prefix(rm
);
10563 * Get prefixlen of the ip-prefix within type5
10566 if (evpn_type5_prefix_match(rm_p
, &match
)
10570 bgp_evpn_get_type5_prefixlen(
10572 if (type5_pfxlen
== match
.prefixlen
) {
10573 is_exact_pfxlen_match
= true;
10574 bgp_dest_unlock_node(rm
);
10583 if (prefix_check
&& !is_exact_pfxlen_match
)
10587 bgp_dest_lock_node(rm
);
10589 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10590 bgp
, afi
, safi
, json
, pathtype
,
10593 bgp_dest_unlock_node(rm
);
10595 } else if (safi
== SAFI_FLOWSPEC
) {
10597 json_paths
= json_object_new_array();
10599 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10600 &match
, prefix_check
,
10604 if (use_json
&& display
)
10605 json_object_object_add(json
, "paths", json_paths
);
10607 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
10608 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10610 || dest_p
->prefixlen
== match
.prefixlen
) {
10611 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
10612 safi
, json
, pathtype
,
10616 bgp_dest_unlock_node(dest
);
10621 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10622 json
, JSON_C_TO_STRING_PRETTY
|
10623 JSON_C_TO_STRING_NOSLASHESCAPE
));
10624 json_object_free(json
);
10627 vty_out(vty
, "%% Network not in table\n");
10628 return CMD_WARNING
;
10632 return CMD_SUCCESS
;
10635 /* Display specified route of Main RIB */
10636 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10637 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10638 int prefix_check
, enum bgp_path_type pathtype
,
10642 bgp
= bgp_get_default();
10645 vty_out(vty
, "No BGP process is configured\n");
10647 vty_out(vty
, "{}\n");
10648 return CMD_WARNING
;
10652 /* labeled-unicast routes live in the unicast table */
10653 if (safi
== SAFI_LABELED_UNICAST
)
10654 safi
= SAFI_UNICAST
;
10656 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10657 afi
, safi
, prd
, prefix_check
, pathtype
,
10661 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10662 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10663 safi_t safi
, bool uj
)
10665 struct lcommunity
*lcom
;
10671 b
= buffer_new(1024);
10672 for (i
= 0; i
< argc
; i
++) {
10674 buffer_putc(b
, ' ');
10676 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10678 buffer_putstr(b
, argv
[i
]->arg
);
10682 buffer_putc(b
, '\0');
10684 str
= buffer_getstr(b
);
10687 lcom
= lcommunity_str2com(str
);
10688 XFREE(MTYPE_TMP
, str
);
10690 vty_out(vty
, "%% Large-community malformed\n");
10691 return CMD_WARNING
;
10694 return bgp_show(vty
, bgp
, afi
, safi
,
10695 (exact
? bgp_show_type_lcommunity_exact
10696 : bgp_show_type_lcommunity
),
10700 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10701 const char *lcom
, bool exact
, afi_t afi
,
10702 safi_t safi
, bool uj
)
10704 struct community_list
*list
;
10706 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10707 LARGE_COMMUNITY_LIST_MASTER
);
10708 if (list
== NULL
) {
10709 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10711 return CMD_WARNING
;
10714 return bgp_show(vty
, bgp
, afi
, safi
,
10715 (exact
? bgp_show_type_lcommunity_list_exact
10716 : bgp_show_type_lcommunity_list
),
10720 DEFUN (show_ip_bgp_large_community_list
,
10721 show_ip_bgp_large_community_list_cmd
,
10722 "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]",
10726 BGP_INSTANCE_HELP_STR
10728 BGP_SAFI_WITH_LABEL_HELP_STR
10729 "Display routes matching the large-community-list\n"
10730 "large-community-list number\n"
10731 "large-community-list name\n"
10732 "Exact match of the large-communities\n"
10735 afi_t afi
= AFI_IP6
;
10736 safi_t safi
= SAFI_UNICAST
;
10738 bool exact_match
= 0;
10739 struct bgp
*bgp
= NULL
;
10740 bool uj
= use_json(argc
, argv
);
10745 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10748 return CMD_WARNING
;
10750 argv_find(argv
, argc
, "large-community-list", &idx
);
10752 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10754 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10757 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10758 exact_match
, afi
, safi
, uj
);
10760 DEFUN (show_ip_bgp_large_community
,
10761 show_ip_bgp_large_community_cmd
,
10762 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10766 BGP_INSTANCE_HELP_STR
10768 BGP_SAFI_WITH_LABEL_HELP_STR
10769 "Display routes matching the large-communities\n"
10770 "List of large-community numbers\n"
10771 "Exact match of the large-communities\n"
10774 afi_t afi
= AFI_IP6
;
10775 safi_t safi
= SAFI_UNICAST
;
10777 bool exact_match
= 0;
10778 struct bgp
*bgp
= NULL
;
10779 bool uj
= use_json(argc
, argv
);
10784 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10787 return CMD_WARNING
;
10789 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10790 if (argv_find(argv
, argc
, "exact-match", &idx
))
10792 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10793 exact_match
, afi
, safi
, uj
);
10795 return bgp_show(vty
, bgp
, afi
, safi
,
10796 bgp_show_type_lcommunity_all
, NULL
, uj
, false);
10799 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10800 safi_t safi
, struct json_object
*json_array
);
10801 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10802 safi_t safi
, struct json_object
*json
);
10805 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
10806 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10807 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10808 "Display number of prefixes for all afi/safi\n" JSON_STR
)
10810 bool uj
= use_json(argc
, argv
);
10811 struct bgp
*bgp
= NULL
;
10812 safi_t safi
= SAFI_UNICAST
;
10813 afi_t afi
= AFI_IP6
;
10815 struct json_object
*json_all
= NULL
;
10816 struct json_object
*json_afi_safi
= NULL
;
10818 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10821 return CMD_WARNING
;
10824 json_all
= json_object_new_object();
10826 FOREACH_AFI_SAFI (afi
, safi
) {
10828 * So limit output to those afi/safi pairs that
10829 * actually have something interesting in them
10831 if (strmatch(get_afi_safi_str(afi
, safi
, true),
10836 json_afi_safi
= json_object_new_array();
10837 json_object_object_add(
10839 get_afi_safi_str(afi
, safi
, true),
10842 json_afi_safi
= NULL
;
10845 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10850 json_object_to_json_string_ext(
10851 json_all
, JSON_C_TO_STRING_PRETTY
));
10852 json_object_free(json_all
);
10855 return CMD_SUCCESS
;
10858 /* BGP route print out function without JSON */
10859 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
10860 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
10861 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
10865 BGP_INSTANCE_HELP_STR
10868 "BGP RIB advertisement statistics\n"
10871 afi_t afi
= AFI_IP6
;
10872 safi_t safi
= SAFI_UNICAST
;
10873 struct bgp
*bgp
= NULL
;
10875 bool uj
= use_json(argc
, argv
);
10876 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10878 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10881 return CMD_WARNING
;
10884 json_afi_safi
= json_object_new_array();
10886 json_afi_safi
= NULL
;
10888 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10891 json
= json_object_new_object();
10892 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10894 vty_out(vty
, "%s", json_object_to_json_string_ext(
10895 json
, JSON_C_TO_STRING_PRETTY
));
10896 json_object_free(json
);
10901 /* BGP route print out function without JSON */
10902 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
10903 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10904 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10906 statistics [json]",
10907 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10908 BGP_SAFI_WITH_LABEL_HELP_STR
10909 "BGP RIB advertisement statistics\n" JSON_STR
)
10911 afi_t afi
= AFI_IP6
;
10912 safi_t safi
= SAFI_UNICAST
;
10913 struct bgp
*bgp
= NULL
;
10915 bool uj
= use_json(argc
, argv
);
10916 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10918 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10921 return CMD_WARNING
;
10924 json_afi_safi
= json_object_new_array();
10926 json_afi_safi
= NULL
;
10928 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10931 json
= json_object_new_object();
10932 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10935 json_object_to_json_string_ext(
10936 json
, JSON_C_TO_STRING_PRETTY
));
10937 json_object_free(json
);
10942 /* BGP route print out function without JSON */
10943 DEFUN(show_ip_bgp
, show_ip_bgp_cmd
,
10944 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10945 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10947 <dampening <parameters>\
10951 |community-list <(1-500)|WORD> [exact-match]\
10952 |A.B.C.D/M longer-prefixes\
10953 |X:X::X:X/M longer-prefixes\
10955 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10956 BGP_SAFI_WITH_LABEL_HELP_STR
10957 "Display detailed information about dampening\n"
10958 "Display detail of configured dampening parameters\n"
10959 "Display routes matching the route-map\n"
10960 "A route-map to match on\n"
10961 "Display routes conforming to the prefix-list\n"
10962 "Prefix-list name\n"
10963 "Display routes conforming to the filter-list\n"
10964 "Regular expression access list name\n"
10965 "Display routes matching the community-list\n"
10966 "community-list number\n"
10967 "community-list name\n"
10968 "Exact match of the communities\n"
10970 "Display route and more specific routes\n"
10972 "Display route and more specific routes\n")
10974 afi_t afi
= AFI_IP6
;
10975 safi_t safi
= SAFI_UNICAST
;
10976 int exact_match
= 0;
10977 struct bgp
*bgp
= NULL
;
10980 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10983 return CMD_WARNING
;
10985 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10986 if (argv_find(argv
, argc
, "parameters", &idx
))
10987 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10990 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10991 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10992 safi
, bgp_show_type_prefix_list
);
10994 if (argv_find(argv
, argc
, "filter-list", &idx
))
10995 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10996 safi
, bgp_show_type_filter_list
);
10998 if (argv_find(argv
, argc
, "route-map", &idx
))
10999 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11000 safi
, bgp_show_type_route_map
);
11002 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11003 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11004 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11006 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11007 exact_match
, afi
, safi
);
11009 /* prefix-longer */
11010 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11011 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11012 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11014 bgp_show_type_prefix_longer
);
11016 return CMD_WARNING
;
11019 /* BGP route print out function with JSON */
11020 DEFPY (show_ip_bgp_json
,
11021 show_ip_bgp_json_cmd
,
11022 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11024 |dampening <flap-statistics|dampened-paths>\
11025 |community [AA:NN|local-AS|no-advertise|no-export\
11026 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11027 |accept-own|accept-own-nexthop|route-filter-v6\
11028 |route-filter-v4|route-filter-translated-v6\
11029 |route-filter-translated-v4] [exact-match]\
11030 ] [json$uj | wide$wide]",
11034 BGP_INSTANCE_HELP_STR
11036 BGP_SAFI_WITH_LABEL_HELP_STR
11037 "Display only routes with non-natural netmasks\n"
11038 "Display detailed information about dampening\n"
11039 "Display flap statistics of routes\n"
11040 "Display paths suppressed due to dampening\n"
11041 "Display routes matching the communities\n"
11043 "Do not send outside local AS (well-known community)\n"
11044 "Do not advertise to any peer (well-known community)\n"
11045 "Do not export to next AS (well-known community)\n"
11046 "Graceful shutdown (well-known community)\n"
11047 "Do not export to any peer (well-known community)\n"
11048 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11049 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11050 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11051 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11052 "Should accept VPN route with local nexthop (well-known community)\n"
11053 "RT VPNv6 route filtering (well-known community)\n"
11054 "RT VPNv4 route filtering (well-known community)\n"
11055 "RT translated VPNv6 route filtering (well-known community)\n"
11056 "RT translated VPNv4 route filtering (well-known community)\n"
11057 "Exact match of the communities\n"
11059 "Increase table width for longer prefixes\n")
11061 afi_t afi
= AFI_IP6
;
11062 safi_t safi
= SAFI_UNICAST
;
11063 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11064 struct bgp
*bgp
= NULL
;
11066 int exact_match
= 0;
11071 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11074 return CMD_WARNING
;
11076 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11077 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
11080 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11081 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11082 return bgp_show(vty
, bgp
, afi
, safi
,
11083 bgp_show_type_dampend_paths
, NULL
, uj
,
11085 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11086 return bgp_show(vty
, bgp
, afi
, safi
,
11087 bgp_show_type_flap_statistics
, NULL
, uj
,
11091 if (argv_find(argv
, argc
, "community", &idx
)) {
11092 char *maybecomm
= NULL
;
11093 char *community
= NULL
;
11095 if (idx
+ 1 < argc
) {
11096 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11097 maybecomm
= argv
[idx
+ 1]->arg
;
11099 maybecomm
= argv
[idx
+ 1]->text
;
11102 if (maybecomm
&& !strmatch(maybecomm
, "json")
11103 && !strmatch(maybecomm
, "exact-match"))
11104 community
= maybecomm
;
11106 if (argv_find(argv
, argc
, "exact-match", &idx
))
11110 return bgp_show_community(vty
, bgp
, community
,
11111 exact_match
, afi
, safi
, uj
);
11113 return (bgp_show(vty
, bgp
, afi
, safi
,
11114 bgp_show_type_community_all
, NULL
, uj
,
11118 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
, wide
);
11121 DEFUN (show_ip_bgp_route
,
11122 show_ip_bgp_route_cmd
,
11123 "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]",
11127 BGP_INSTANCE_HELP_STR
11129 BGP_SAFI_WITH_LABEL_HELP_STR
11130 "Network in the BGP routing table to display\n"
11132 "Network in the BGP routing table to display\n"
11134 "Display only the bestpath\n"
11135 "Display only multipaths\n"
11138 int prefix_check
= 0;
11140 afi_t afi
= AFI_IP6
;
11141 safi_t safi
= SAFI_UNICAST
;
11142 char *prefix
= NULL
;
11143 struct bgp
*bgp
= NULL
;
11144 enum bgp_path_type path_type
;
11145 bool uj
= use_json(argc
, argv
);
11149 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11152 return CMD_WARNING
;
11156 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11157 return CMD_WARNING
;
11160 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11161 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
11162 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
11164 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11165 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11168 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
11169 && afi
!= AFI_IP6
) {
11171 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11172 return CMD_WARNING
;
11174 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
11175 && afi
!= AFI_IP
) {
11177 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11178 return CMD_WARNING
;
11181 prefix
= argv
[idx
]->arg
;
11183 /* [<bestpath|multipath>] */
11184 if (argv_find(argv
, argc
, "bestpath", &idx
))
11185 path_type
= BGP_PATH_SHOW_BESTPATH
;
11186 else if (argv_find(argv
, argc
, "multipath", &idx
))
11187 path_type
= BGP_PATH_SHOW_MULTIPATH
;
11189 path_type
= BGP_PATH_SHOW_ALL
;
11191 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
11195 DEFUN (show_ip_bgp_regexp
,
11196 show_ip_bgp_regexp_cmd
,
11197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
11201 BGP_INSTANCE_HELP_STR
11203 BGP_SAFI_WITH_LABEL_HELP_STR
11204 "Display routes matching the AS path regular expression\n"
11205 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11208 afi_t afi
= AFI_IP6
;
11209 safi_t safi
= SAFI_UNICAST
;
11210 struct bgp
*bgp
= NULL
;
11211 bool uj
= use_json(argc
, argv
);
11212 char *regstr
= NULL
;
11215 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11218 return CMD_WARNING
;
11220 // get index of regex
11221 if (argv_find(argv
, argc
, "REGEX", &idx
))
11222 regstr
= argv
[idx
]->arg
;
11225 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
11226 bgp_show_type_regexp
, uj
);
11229 DEFPY (show_ip_bgp_instance_all
,
11230 show_ip_bgp_instance_all_cmd
,
11231 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
11235 BGP_INSTANCE_ALL_HELP_STR
11237 BGP_SAFI_WITH_LABEL_HELP_STR
11239 "Increase table width for longer prefixes\n")
11241 afi_t afi
= AFI_IP
;
11242 safi_t safi
= SAFI_UNICAST
;
11243 struct bgp
*bgp
= NULL
;
11249 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11252 return CMD_WARNING
;
11254 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
, wide
);
11255 return CMD_SUCCESS
;
11258 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11259 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11265 if (!config_bgp_aspath_validate(regstr
)) {
11266 vty_out(vty
, "Invalid character in REGEX %s\n",
11268 return CMD_WARNING_CONFIG_FAILED
;
11271 regex
= bgp_regcomp(regstr
);
11273 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
11274 return CMD_WARNING
;
11277 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
, false);
11278 bgp_regex_free(regex
);
11282 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
11283 const char *prefix_list_str
, afi_t afi
,
11284 safi_t safi
, enum bgp_show_type type
)
11286 struct prefix_list
*plist
;
11288 plist
= prefix_list_lookup(afi
, prefix_list_str
);
11289 if (plist
== NULL
) {
11290 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
11292 return CMD_WARNING
;
11295 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0, false);
11298 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
11299 const char *filter
, afi_t afi
, safi_t safi
,
11300 enum bgp_show_type type
)
11302 struct as_list
*as_list
;
11304 as_list
= as_list_lookup(filter
);
11305 if (as_list
== NULL
) {
11306 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
11308 return CMD_WARNING
;
11311 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0, false);
11314 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
11315 const char *rmap_str
, afi_t afi
, safi_t safi
,
11316 enum bgp_show_type type
)
11318 struct route_map
*rmap
;
11320 rmap
= route_map_lookup_by_name(rmap_str
);
11322 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
11323 return CMD_WARNING
;
11326 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0, false);
11329 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11330 const char *comstr
, int exact
, afi_t afi
,
11331 safi_t safi
, bool use_json
)
11333 struct community
*com
;
11336 com
= community_str2com(comstr
);
11338 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
11339 return CMD_WARNING
;
11342 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11343 (exact
? bgp_show_type_community_exact
11344 : bgp_show_type_community
),
11345 com
, use_json
, false);
11346 community_free(&com
);
11351 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
11352 const char *com
, int exact
, afi_t afi
,
11355 struct community_list
*list
;
11357 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
11358 if (list
== NULL
) {
11359 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
11360 return CMD_WARNING
;
11363 return bgp_show(vty
, bgp
, afi
, safi
,
11364 (exact
? bgp_show_type_community_list_exact
11365 : bgp_show_type_community_list
),
11369 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
11370 const char *prefix
, afi_t afi
, safi_t safi
,
11371 enum bgp_show_type type
)
11378 ret
= str2prefix(prefix
, p
);
11380 vty_out(vty
, "%% Malformed Prefix\n");
11381 return CMD_WARNING
;
11384 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0, false);
11390 BGP_STATS_MAXBITLEN
= 0,
11392 BGP_STATS_PREFIXES
,
11394 BGP_STATS_UNAGGREGATEABLE
,
11395 BGP_STATS_MAX_AGGREGATEABLE
,
11396 BGP_STATS_AGGREGATES
,
11398 BGP_STATS_ASPATH_COUNT
,
11399 BGP_STATS_ASPATH_MAXHOPS
,
11400 BGP_STATS_ASPATH_TOTHOPS
,
11401 BGP_STATS_ASPATH_MAXSIZE
,
11402 BGP_STATS_ASPATH_TOTSIZE
,
11403 BGP_STATS_ASN_HIGHEST
,
11407 #define TABLE_STATS_IDX_VTY 0
11408 #define TABLE_STATS_IDX_JSON 1
11410 static const char *table_stats_strs
[][2] = {
11411 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
11412 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
11413 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
11414 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
11415 "unaggregateablePrefixes"},
11416 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
11417 "maximumAggregateablePrefixes"},
11418 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
11419 "bgpAggregateAdvertisements"},
11420 [BGP_STATS_SPACE
] = {"Address space advertised",
11421 "addressSpaceAdvertised"},
11422 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
11423 "advertisementsWithPaths"},
11424 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
11426 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
11428 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
11429 "averageAsPathLengthHops"},
11430 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
11431 "averageAsPathSizeBytes"},
11432 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
11433 [BGP_STATS_MAX
] = {NULL
, NULL
}
11436 struct bgp_table_stats
{
11437 struct bgp_table
*table
;
11438 unsigned long long counts
[BGP_STATS_MAX
];
11439 double total_space
;
11443 #define TALLY_SIGFIG 100000
11444 static unsigned long
11445 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
11447 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
11448 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
11449 unsigned long ret
= newtot
/ count
;
11451 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
11458 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
11459 struct bgp_table_stats
*ts
, unsigned int space
)
11461 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
11462 struct bgp_path_info
*pi
;
11463 const struct prefix
*rn_p
;
11468 if (!bgp_dest_has_bgp_path_info_data(dest
))
11471 rn_p
= bgp_dest_get_prefix(dest
);
11472 ts
->counts
[BGP_STATS_PREFIXES
]++;
11473 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
11476 ts
->counts
[BGP_STATS_AVGPLEN
]
11477 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
11478 ts
->counts
[BGP_STATS_AVGPLEN
],
11482 /* check if the prefix is included by any other announcements */
11483 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
11484 pdest
= bgp_dest_parent_nolock(pdest
);
11486 if (pdest
== NULL
|| pdest
== top
) {
11487 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
11488 /* announced address space */
11490 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
11491 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
11492 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11495 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11496 ts
->counts
[BGP_STATS_RIB
]++;
11498 if (CHECK_FLAG(pi
->attr
->flag
,
11499 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11500 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11502 /* as-path stats */
11503 if (pi
->attr
->aspath
) {
11504 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11505 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11506 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11508 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11510 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11511 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11513 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11514 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11516 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11517 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11519 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11520 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11521 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11523 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11524 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11525 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11528 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11529 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11534 static int bgp_table_stats_walker(struct thread
*t
)
11536 struct bgp_dest
*dest
, *ndest
;
11537 struct bgp_dest
*top
;
11538 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11539 unsigned int space
= 0;
11541 if (!(top
= bgp_table_top(ts
->table
)))
11544 switch (ts
->table
->afi
) {
11546 space
= IPV4_MAX_BITLEN
;
11549 space
= IPV6_MAX_BITLEN
;
11555 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11557 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
11558 if (ts
->table
->safi
== SAFI_MPLS_VPN
11559 || ts
->table
->safi
== SAFI_ENCAP
11560 || ts
->table
->safi
== SAFI_EVPN
) {
11561 struct bgp_table
*table
;
11563 table
= bgp_dest_get_bgp_table_info(dest
);
11567 top
= bgp_table_top(table
);
11568 for (ndest
= bgp_table_top(table
); ndest
;
11569 ndest
= bgp_route_next(ndest
))
11570 bgp_table_stats_rn(ndest
, top
, ts
, space
);
11572 bgp_table_stats_rn(dest
, top
, ts
, space
);
11579 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
11580 struct json_object
*json_array
)
11582 struct listnode
*node
, *nnode
;
11585 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
11586 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11589 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11590 safi_t safi
, struct json_object
*json_array
)
11592 struct bgp_table_stats ts
;
11594 int ret
= CMD_SUCCESS
;
11596 struct json_object
*json
= NULL
;
11599 json
= json_object_new_object();
11601 if (!bgp
->rib
[afi
][safi
]) {
11602 char warning_msg
[50];
11604 snprintf(warning_msg
, sizeof(warning_msg
),
11605 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
11609 vty_out(vty
, "%s\n", warning_msg
);
11611 json_object_string_add(json
, "warning", warning_msg
);
11614 goto end_table_stats
;
11618 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
11619 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
11621 json_object_string_add(json
, "instance", bgp
->name_pretty
);
11623 /* labeled-unicast routes live in the unicast table */
11624 if (safi
== SAFI_LABELED_UNICAST
)
11625 safi
= SAFI_UNICAST
;
11627 memset(&ts
, 0, sizeof(ts
));
11628 ts
.table
= bgp
->rib
[afi
][safi
];
11629 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11631 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11632 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
11633 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
11638 case BGP_STATS_ASPATH_AVGHOPS
:
11639 case BGP_STATS_ASPATH_AVGSIZE
:
11640 case BGP_STATS_AVGPLEN
:
11641 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11642 vty_out (vty
, "%12.2f",
11643 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11646 case BGP_STATS_ASPATH_TOTHOPS
:
11647 case BGP_STATS_ASPATH_TOTSIZE
:
11650 temp_buf
, sizeof(temp_buf
), "%12.2f",
11652 ? (float)ts
.counts
[i
]
11654 [BGP_STATS_ASPATH_COUNT
]
11656 vty_out(vty
, "%-30s: %s",
11657 table_stats_strs
[i
]
11658 [TABLE_STATS_IDX_VTY
],
11661 json_object_double_add(
11663 table_stats_strs
[i
]
11664 [TABLE_STATS_IDX_JSON
],
11666 ? (double)ts
.counts
[i
]
11667 / (double)ts
.counts
11668 [BGP_STATS_ASPATH_COUNT
]
11672 case BGP_STATS_TOTPLEN
:
11675 temp_buf
, sizeof(temp_buf
), "%12.2f",
11677 ? (float)ts
.counts
[i
]
11679 [BGP_STATS_PREFIXES
]
11681 vty_out(vty
, "%-30s: %s",
11682 table_stats_strs
[i
]
11683 [TABLE_STATS_IDX_VTY
],
11686 json_object_double_add(
11688 table_stats_strs
[i
]
11689 [TABLE_STATS_IDX_JSON
],
11691 ? (double)ts
.counts
[i
]
11692 / (double)ts
.counts
11693 [BGP_STATS_PREFIXES
]
11697 case BGP_STATS_SPACE
:
11699 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
11701 vty_out(vty
, "%-30s: %s\n",
11702 table_stats_strs
[i
]
11703 [TABLE_STATS_IDX_VTY
],
11706 json_object_double_add(
11708 table_stats_strs
[i
]
11709 [TABLE_STATS_IDX_JSON
],
11710 (double)ts
.total_space
);
11712 if (afi
== AFI_IP6
) {
11714 snprintf(temp_buf
, sizeof(temp_buf
),
11717 * pow(2.0, -128 + 32));
11718 vty_out(vty
, "%30s: %s\n",
11719 "/32 equivalent %s\n",
11722 json_object_double_add(
11723 json
, "/32equivalent",
11724 (double)(ts
.total_space
11729 snprintf(temp_buf
, sizeof(temp_buf
),
11732 * pow(2.0, -128 + 48));
11733 vty_out(vty
, "%30s: %s\n",
11734 "/48 equivalent %s\n",
11737 json_object_double_add(
11738 json
, "/48equivalent",
11739 (double)(ts
.total_space
11745 snprintf(temp_buf
, sizeof(temp_buf
),
11747 ts
.total_space
* 100.
11749 vty_out(vty
, "%30s: %s\n",
11750 "% announced ", temp_buf
);
11752 json_object_double_add(
11753 json
, "%announced",
11754 (double)(ts
.total_space
* 100.
11758 snprintf(temp_buf
, sizeof(temp_buf
),
11761 * pow(2.0, -32 + 8));
11762 vty_out(vty
, "%30s: %s\n",
11763 "/8 equivalent ", temp_buf
);
11765 json_object_double_add(
11766 json
, "/8equivalent",
11767 (double)(ts
.total_space
11768 * pow(2.0, -32 + 8)));
11771 snprintf(temp_buf
, sizeof(temp_buf
),
11774 * pow(2.0, -32 + 24));
11775 vty_out(vty
, "%30s: %s\n",
11776 "/24 equivalent ", temp_buf
);
11778 json_object_double_add(
11779 json
, "/24equivalent",
11780 (double)(ts
.total_space
11781 * pow(2.0, -32 + 24)));
11787 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
11789 vty_out(vty
, "%-30s: %s",
11790 table_stats_strs
[i
]
11791 [TABLE_STATS_IDX_VTY
],
11794 json_object_int_add(
11796 table_stats_strs
[i
]
11797 [TABLE_STATS_IDX_JSON
],
11802 vty_out(vty
, "\n");
11806 json_object_array_add(json_array
, json
);
11810 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11811 safi_t safi
, struct json_object
*json_array
)
11814 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
11815 return CMD_SUCCESS
;
11818 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11830 PCOUNT_BPATH_SELECTED
,
11831 PCOUNT_PFCNT
, /* the figure we display to users */
11835 static const char *const pcount_strs
[] = {
11836 [PCOUNT_ADJ_IN
] = "Adj-in",
11837 [PCOUNT_DAMPED
] = "Damped",
11838 [PCOUNT_REMOVED
] = "Removed",
11839 [PCOUNT_HISTORY
] = "History",
11840 [PCOUNT_STALE
] = "Stale",
11841 [PCOUNT_VALID
] = "Valid",
11842 [PCOUNT_ALL
] = "All RIB",
11843 [PCOUNT_COUNTED
] = "PfxCt counted",
11844 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
11845 [PCOUNT_PFCNT
] = "Useable",
11846 [PCOUNT_MAX
] = NULL
,
11849 struct peer_pcounts
{
11850 unsigned int count
[PCOUNT_MAX
];
11851 const struct peer
*peer
;
11852 const struct bgp_table
*table
;
11856 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
11858 const struct bgp_adj_in
*ain
;
11859 const struct bgp_path_info
*pi
;
11860 const struct peer
*peer
= pc
->peer
;
11862 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11863 if (ain
->peer
== peer
)
11864 pc
->count
[PCOUNT_ADJ_IN
]++;
11866 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11868 if (pi
->peer
!= peer
)
11871 pc
->count
[PCOUNT_ALL
]++;
11873 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11874 pc
->count
[PCOUNT_DAMPED
]++;
11875 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11876 pc
->count
[PCOUNT_HISTORY
]++;
11877 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11878 pc
->count
[PCOUNT_REMOVED
]++;
11879 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11880 pc
->count
[PCOUNT_STALE
]++;
11881 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11882 pc
->count
[PCOUNT_VALID
]++;
11883 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11884 pc
->count
[PCOUNT_PFCNT
]++;
11885 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11886 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
11888 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11889 pc
->count
[PCOUNT_COUNTED
]++;
11890 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11892 EC_LIB_DEVELOPMENT
,
11893 "Attempting to count but flags say it is unusable");
11895 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11897 EC_LIB_DEVELOPMENT
,
11898 "Not counted but flags say we should");
11903 static int bgp_peer_count_walker(struct thread
*t
)
11905 struct bgp_dest
*rn
, *rm
;
11906 const struct bgp_table
*table
;
11907 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11909 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11910 || pc
->safi
== SAFI_EVPN
) {
11911 /* Special handling for 2-level routing tables. */
11912 for (rn
= bgp_table_top(pc
->table
); rn
;
11913 rn
= bgp_route_next(rn
)) {
11914 table
= bgp_dest_get_bgp_table_info(rn
);
11916 for (rm
= bgp_table_top(table
); rm
;
11917 rm
= bgp_route_next(rm
))
11918 bgp_peer_count_proc(rm
, pc
);
11921 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11922 bgp_peer_count_proc(rn
, pc
);
11927 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11928 safi_t safi
, bool use_json
)
11930 struct peer_pcounts pcounts
= {.peer
= peer
};
11932 json_object
*json
= NULL
;
11933 json_object
*json_loop
= NULL
;
11936 json
= json_object_new_object();
11937 json_loop
= json_object_new_object();
11940 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11941 || !peer
->bgp
->rib
[afi
][safi
]) {
11943 json_object_string_add(
11945 "No such neighbor or address family");
11946 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11947 json_object_free(json
);
11949 vty_out(vty
, "%% No such neighbor or address family\n");
11951 return CMD_WARNING
;
11954 memset(&pcounts
, 0, sizeof(pcounts
));
11955 pcounts
.peer
= peer
;
11956 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11957 pcounts
.safi
= safi
;
11959 /* in-place call via thread subsystem so as to record execution time
11960 * stats for the thread-walk (i.e. ensure this can't be blamed on
11961 * on just vty_read()).
11963 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11966 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11967 json_object_string_add(json
, "multiProtocol",
11968 get_afi_safi_str(afi
, safi
, true));
11969 json_object_int_add(json
, "pfxCounter",
11970 peer
->pcount
[afi
][safi
]);
11972 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11973 json_object_int_add(json_loop
, pcount_strs
[i
],
11976 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11978 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11979 json_object_string_add(json
, "pfxctDriftFor",
11981 json_object_string_add(
11982 json
, "recommended",
11983 "Please report this bug, with the above command output");
11985 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11986 json
, JSON_C_TO_STRING_PRETTY
));
11987 json_object_free(json
);
11991 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
11992 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11993 peer
->hostname
, peer
->host
,
11994 get_afi_safi_str(afi
, safi
, false));
11996 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11997 get_afi_safi_str(afi
, safi
, false));
12000 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12001 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12003 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12004 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12007 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12008 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12010 "Please report this bug, with the above command output\n");
12014 return CMD_SUCCESS
;
12017 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12018 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12019 "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]",
12023 BGP_INSTANCE_HELP_STR
12026 "Detailed information on TCP and BGP neighbor connections\n"
12027 "Neighbor to display information about\n"
12028 "Neighbor to display information about\n"
12029 "Neighbor on BGP configured interface\n"
12030 "Display detailed prefix count information\n"
12033 afi_t afi
= AFI_IP6
;
12034 safi_t safi
= SAFI_UNICAST
;
12037 struct bgp
*bgp
= NULL
;
12038 bool uj
= use_json(argc
, argv
);
12043 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12046 return CMD_WARNING
;
12048 argv_find(argv
, argc
, "neighbors", &idx
);
12049 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12051 return CMD_WARNING
;
12053 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12056 #ifdef KEEP_OLD_VPN_COMMANDS
12057 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12058 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12059 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12064 "Display information about all VPNv4 NLRIs\n"
12065 "Detailed information on TCP and BGP neighbor connections\n"
12066 "Neighbor to display information about\n"
12067 "Neighbor to display information about\n"
12068 "Neighbor on BGP configured interface\n"
12069 "Display detailed prefix count information\n"
12074 bool uj
= use_json(argc
, argv
);
12076 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12078 return CMD_WARNING
;
12080 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12083 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12084 show_ip_bgp_vpn_all_route_prefix_cmd
,
12085 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12090 "Display information about all VPNv4 NLRIs\n"
12091 "Network in the BGP routing table to display\n"
12092 "Network in the BGP routing table to display\n"
12096 char *network
= NULL
;
12097 struct bgp
*bgp
= bgp_get_default();
12099 vty_out(vty
, "Can't find default instance\n");
12100 return CMD_WARNING
;
12103 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12104 network
= argv
[idx
]->arg
;
12105 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12106 network
= argv
[idx
]->arg
;
12108 vty_out(vty
, "Unable to figure out Network\n");
12109 return CMD_WARNING
;
12112 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12113 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12115 #endif /* KEEP_OLD_VPN_COMMANDS */
12117 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12118 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12119 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12124 "Network in the BGP routing table to display\n"
12125 "Network in the BGP routing table to display\n"
12126 "Network in the BGP routing table to display\n"
12127 "Network in the BGP routing table to display\n"
12131 char *network
= NULL
;
12132 int prefix_check
= 0;
12134 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12135 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12136 network
= argv
[idx
]->arg
;
12137 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12138 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12139 network
= argv
[idx
]->arg
;
12142 vty_out(vty
, "Unable to figure out Network\n");
12143 return CMD_WARNING
;
12145 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12146 prefix_check
, BGP_PATH_SHOW_ALL
,
12147 use_json(argc
, argv
));
12150 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12151 struct bgp_table
*table
, int *header1
,
12152 int *header2
, json_object
*json
,
12153 json_object
*json_scode
,
12154 json_object
*json_ocode
, bool wide
)
12156 uint64_t version
= table
? table
->version
: 0;
12160 json_object_int_add(json
, "bgpTableVersion", version
);
12161 json_object_string_add(json
, "bgpLocalRouterId",
12162 inet_ntoa(bgp
->router_id
));
12163 json_object_int_add(json
, "defaultLocPrf",
12164 bgp
->default_local_pref
);
12165 json_object_int_add(json
, "localAS", bgp
->as
);
12166 json_object_object_add(json
, "bgpStatusCodes",
12168 json_object_object_add(json
, "bgpOriginCodes",
12172 "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12173 version
, inet_ntoa(bgp
->router_id
));
12174 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12175 vty_out(vty
, "%s", VRFID_NONE_STR
);
12177 vty_out(vty
, "%u", bgp
->vrf_id
);
12178 vty_out(vty
, "\n");
12179 vty_out(vty
, "Default local pref %u, ",
12180 bgp
->default_local_pref
);
12181 vty_out(vty
, "local AS %u\n", bgp
->as
);
12182 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12183 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12184 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12190 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
12191 : BGP_SHOW_HEADER
));
12196 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12197 safi_t safi
, enum bgp_show_adj_route_type type
,
12198 const char *rmap_name
, bool use_json
,
12199 json_object
*json
, bool wide
)
12201 struct bgp_table
*table
;
12202 struct bgp_adj_in
*ain
;
12203 struct bgp_adj_out
*adj
;
12204 unsigned long output_count
= 0;
12205 unsigned long filtered_count
= 0;
12206 struct bgp_dest
*dest
;
12212 struct update_subgroup
*subgrp
;
12213 json_object
*json_scode
= NULL
;
12214 json_object
*json_ocode
= NULL
;
12215 json_object
*json_ar
= NULL
;
12216 struct peer_af
*paf
;
12217 bool route_filtered
;
12220 json_scode
= json_object_new_object();
12221 json_ocode
= json_object_new_object();
12222 json_ar
= json_object_new_object();
12224 json_object_string_add(json_scode
, "suppressed", "s");
12225 json_object_string_add(json_scode
, "damped", "d");
12226 json_object_string_add(json_scode
, "history", "h");
12227 json_object_string_add(json_scode
, "valid", "*");
12228 json_object_string_add(json_scode
, "best", ">");
12229 json_object_string_add(json_scode
, "multipath", "=");
12230 json_object_string_add(json_scode
, "internal", "i");
12231 json_object_string_add(json_scode
, "ribFailure", "r");
12232 json_object_string_add(json_scode
, "stale", "S");
12233 json_object_string_add(json_scode
, "removed", "R");
12235 json_object_string_add(json_ocode
, "igp", "i");
12236 json_object_string_add(json_ocode
, "egp", "e");
12237 json_object_string_add(json_ocode
, "incomplete", "?");
12244 json_object_string_add(json
, "alert", "no BGP");
12245 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12246 json_object_free(json
);
12248 vty_out(vty
, "%% No bgp\n");
12252 /* labeled-unicast routes live in the unicast table */
12253 if (safi
== SAFI_LABELED_UNICAST
)
12254 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
12256 table
= bgp
->rib
[afi
][safi
];
12258 output_count
= filtered_count
= 0;
12259 subgrp
= peer_subgroup(peer
, afi
, safi
);
12261 if (type
== bgp_show_adj_route_advertised
&& subgrp
12262 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
12264 json_object_int_add(json
, "bgpTableVersion",
12266 json_object_string_add(json
, "bgpLocalRouterId",
12267 inet_ntoa(bgp
->router_id
));
12268 json_object_int_add(json
, "defaultLocPrf",
12269 bgp
->default_local_pref
);
12270 json_object_int_add(json
, "localAS", bgp
->as
);
12271 json_object_object_add(json
, "bgpStatusCodes",
12273 json_object_object_add(json
, "bgpOriginCodes",
12275 json_object_string_add(
12276 json
, "bgpOriginatingDefaultNetwork",
12277 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12279 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12280 table
->version
, inet_ntoa(bgp
->router_id
));
12281 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12282 vty_out(vty
, "%s", VRFID_NONE_STR
);
12284 vty_out(vty
, "%u", bgp
->vrf_id
);
12285 vty_out(vty
, "\n");
12286 vty_out(vty
, "Default local pref %u, ",
12287 bgp
->default_local_pref
);
12288 vty_out(vty
, "local AS %u\n", bgp
->as
);
12289 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12290 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12291 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12293 vty_out(vty
, "Originating default network %s\n\n",
12294 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12299 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
12300 if (type
== bgp_show_adj_route_received
12301 || type
== bgp_show_adj_route_filtered
) {
12302 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
12303 if (ain
->peer
!= peer
)
12306 show_adj_route_header(
12307 vty
, bgp
, table
, &header1
, &header2
,
12308 json
, json_scode
, json_ocode
, wide
);
12311 route_filtered
= false;
12313 /* Filter prefix using distribute list,
12314 * filter list or prefix list
12316 const struct prefix
*rn_p
=
12317 bgp_dest_get_prefix(dest
);
12318 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
12321 route_filtered
= true;
12323 /* Filter prefix using route-map */
12324 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
12325 safi
, rmap_name
, NULL
,
12328 if (type
== bgp_show_adj_route_filtered
&&
12329 !route_filtered
&& ret
!= RMAP_DENY
) {
12330 bgp_attr_undup(&attr
, ain
->attr
);
12334 if (type
== bgp_show_adj_route_received
&&
12335 (route_filtered
|| ret
== RMAP_DENY
))
12338 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
12339 use_json
, json_ar
, wide
);
12340 bgp_attr_undup(&attr
, ain
->attr
);
12343 } else if (type
== bgp_show_adj_route_advertised
) {
12344 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
12345 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
12346 if (paf
->peer
!= peer
|| !adj
->attr
)
12349 show_adj_route_header(
12350 vty
, bgp
, table
, &header1
,
12351 &header2
, json
, json_scode
,
12354 const struct prefix
*rn_p
=
12355 bgp_dest_get_prefix(dest
);
12358 ret
= bgp_output_modifier(
12359 peer
, rn_p
, &attr
, afi
, safi
,
12362 if (ret
!= RMAP_DENY
) {
12364 vty
, rn_p
, &attr
, safi
,
12372 bgp_attr_undup(&attr
, adj
->attr
);
12374 } else if (type
== bgp_show_adj_route_bestpath
) {
12375 struct bgp_path_info
*pi
;
12377 show_adj_route_header(vty
, bgp
, table
, &header1
,
12378 &header2
, json
, json_scode
,
12381 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
12383 if (pi
->peer
!= peer
)
12386 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12389 route_vty_out_tmp(vty
,
12390 bgp_dest_get_prefix(dest
),
12391 pi
->attr
, safi
, use_json
,
12399 json_object_object_add(json
, "advertisedRoutes", json_ar
);
12400 json_object_int_add(json
, "totalPrefixCounter", output_count
);
12401 json_object_int_add(json
, "filteredPrefixCounter",
12404 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12405 json
, JSON_C_TO_STRING_PRETTY
));
12407 if (!output_count
&& !filtered_count
) {
12408 json_object_free(json_scode
);
12409 json_object_free(json_ocode
);
12412 json_object_free(json
);
12413 } else if (output_count
> 0) {
12414 if (filtered_count
> 0)
12416 "\nTotal number of prefixes %ld (%ld filtered)\n",
12417 output_count
, filtered_count
);
12419 vty_out(vty
, "\nTotal number of prefixes %ld\n",
12424 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12425 safi_t safi
, enum bgp_show_adj_route_type type
,
12426 const char *rmap_name
, bool use_json
, bool wide
)
12428 json_object
*json
= NULL
;
12431 json
= json_object_new_object();
12433 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12435 json_object_string_add(
12437 "No such neighbor or address family");
12438 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12439 json_object_free(json
);
12441 vty_out(vty
, "%% No such neighbor or address family\n");
12443 return CMD_WARNING
;
12446 if ((type
== bgp_show_adj_route_received
12447 || type
== bgp_show_adj_route_filtered
)
12448 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
12449 PEER_FLAG_SOFT_RECONFIG
)) {
12451 json_object_string_add(
12453 "Inbound soft reconfiguration not enabled");
12454 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12455 json_object_free(json
);
12458 "%% Inbound soft reconfiguration not enabled\n");
12460 return CMD_WARNING
;
12463 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
,
12466 return CMD_SUCCESS
;
12469 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
12470 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
12471 "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]",
12475 BGP_INSTANCE_HELP_STR
12477 BGP_SAFI_WITH_LABEL_HELP_STR
12478 "Detailed information on TCP and BGP neighbor connections\n"
12479 "Neighbor to display information about\n"
12480 "Neighbor to display information about\n"
12481 "Neighbor on BGP configured interface\n"
12482 "Display the routes selected by best path\n"
12484 "Increase table width for longer prefixes\n")
12486 afi_t afi
= AFI_IP6
;
12487 safi_t safi
= SAFI_UNICAST
;
12488 char *rmap_name
= NULL
;
12489 char *peerstr
= NULL
;
12490 struct bgp
*bgp
= NULL
;
12492 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
12495 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12499 return CMD_WARNING
;
12501 argv_find(argv
, argc
, "neighbors", &idx
);
12502 peerstr
= argv
[++idx
]->arg
;
12504 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12506 return CMD_WARNING
;
12508 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
, wide
);
12511 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
12512 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
12513 "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]",
12517 BGP_INSTANCE_HELP_STR
12519 BGP_SAFI_WITH_LABEL_HELP_STR
12520 "Detailed information on TCP and BGP neighbor connections\n"
12521 "Neighbor to display information about\n"
12522 "Neighbor to display information about\n"
12523 "Neighbor on BGP configured interface\n"
12524 "Display the routes advertised to a BGP neighbor\n"
12525 "Display the received routes from neighbor\n"
12526 "Display the filtered routes received from neighbor\n"
12527 "Route-map to modify the attributes\n"
12528 "Name of the route map\n"
12530 "Increase table width for longer prefixes\n")
12532 afi_t afi
= AFI_IP6
;
12533 safi_t safi
= SAFI_UNICAST
;
12534 char *rmap_name
= NULL
;
12535 char *peerstr
= NULL
;
12536 struct bgp
*bgp
= NULL
;
12538 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
12544 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12547 return CMD_WARNING
;
12549 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12550 argv_find(argv
, argc
, "neighbors", &idx
);
12551 peerstr
= argv
[++idx
]->arg
;
12553 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12555 return CMD_WARNING
;
12557 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
12558 type
= bgp_show_adj_route_advertised
;
12559 else if (argv_find(argv
, argc
, "received-routes", &idx
))
12560 type
= bgp_show_adj_route_received
;
12561 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
12562 type
= bgp_show_adj_route_filtered
;
12564 if (argv_find(argv
, argc
, "route-map", &idx
))
12565 rmap_name
= argv
[++idx
]->arg
;
12567 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
, wide
);
12570 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
12571 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
12572 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
12578 "Address Family modifier\n"
12579 "Detailed information on TCP and BGP neighbor connections\n"
12580 "Neighbor to display information about\n"
12581 "Neighbor to display information about\n"
12582 "Neighbor on BGP configured interface\n"
12583 "Display information received from a BGP neighbor\n"
12584 "Display the prefixlist filter\n"
12587 afi_t afi
= AFI_IP6
;
12588 safi_t safi
= SAFI_UNICAST
;
12589 char *peerstr
= NULL
;
12592 union sockunion su
;
12598 /* show [ip] bgp */
12599 if (argv_find(argv
, argc
, "ip", &idx
))
12601 /* [<ipv4|ipv6> [unicast]] */
12602 if (argv_find(argv
, argc
, "ipv4", &idx
))
12604 if (argv_find(argv
, argc
, "ipv6", &idx
))
12606 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12607 argv_find(argv
, argc
, "neighbors", &idx
);
12608 peerstr
= argv
[++idx
]->arg
;
12610 bool uj
= use_json(argc
, argv
);
12612 ret
= str2sockunion(peerstr
, &su
);
12614 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
12617 vty_out(vty
, "{}\n");
12620 "%% Malformed address or name: %s\n",
12622 return CMD_WARNING
;
12625 peer
= peer_lookup(NULL
, &su
);
12628 vty_out(vty
, "{}\n");
12630 vty_out(vty
, "No peer\n");
12631 return CMD_WARNING
;
12635 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
12636 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
12639 vty_out(vty
, "Address Family: %s\n",
12640 get_afi_safi_str(afi
, safi
, false));
12641 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
12644 vty_out(vty
, "{}\n");
12646 vty_out(vty
, "No functional output\n");
12649 return CMD_SUCCESS
;
12652 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
12653 afi_t afi
, safi_t safi
,
12654 enum bgp_show_type type
, bool use_json
)
12656 /* labeled-unicast routes live in the unicast table */
12657 if (safi
== SAFI_LABELED_UNICAST
)
12658 safi
= SAFI_UNICAST
;
12660 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12662 json_object
*json_no
= NULL
;
12663 json_no
= json_object_new_object();
12664 json_object_string_add(
12665 json_no
, "warning",
12666 "No such neighbor or address family");
12667 vty_out(vty
, "%s\n",
12668 json_object_to_json_string(json_no
));
12669 json_object_free(json_no
);
12671 vty_out(vty
, "%% No such neighbor or address family\n");
12672 return CMD_WARNING
;
12675 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
,
12679 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12680 show_ip_bgp_flowspec_routes_detailed_cmd
,
12681 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12685 BGP_INSTANCE_HELP_STR
12688 "Detailed information on flowspec entries\n"
12691 afi_t afi
= AFI_IP
;
12692 safi_t safi
= SAFI_UNICAST
;
12693 struct bgp
*bgp
= NULL
;
12695 bool uj
= use_json(argc
, argv
);
12700 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12703 return CMD_WARNING
;
12705 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
,
12709 DEFUN (show_ip_bgp_neighbor_routes
,
12710 show_ip_bgp_neighbor_routes_cmd
,
12711 "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]",
12715 BGP_INSTANCE_HELP_STR
12717 BGP_SAFI_WITH_LABEL_HELP_STR
12718 "Detailed information on TCP and BGP neighbor connections\n"
12719 "Neighbor to display information about\n"
12720 "Neighbor to display information about\n"
12721 "Neighbor on BGP configured interface\n"
12722 "Display flap statistics of the routes learned from neighbor\n"
12723 "Display the dampened routes received from neighbor\n"
12724 "Display routes learned from neighbor\n"
12727 char *peerstr
= NULL
;
12728 struct bgp
*bgp
= NULL
;
12729 afi_t afi
= AFI_IP6
;
12730 safi_t safi
= SAFI_UNICAST
;
12732 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12734 bool uj
= use_json(argc
, argv
);
12739 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12742 return CMD_WARNING
;
12744 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12745 argv_find(argv
, argc
, "neighbors", &idx
);
12746 peerstr
= argv
[++idx
]->arg
;
12748 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12750 return CMD_WARNING
;
12752 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12753 sh_type
= bgp_show_type_flap_neighbor
;
12754 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12755 sh_type
= bgp_show_type_damp_neighbor
;
12756 else if (argv_find(argv
, argc
, "routes", &idx
))
12757 sh_type
= bgp_show_type_neighbor
;
12759 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12762 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12764 struct bgp_distance
{
12765 /* Distance value for the IP source prefix. */
12768 /* Name of the access-list to be matched. */
12772 DEFUN (show_bgp_afi_vpn_rd_route
,
12773 show_bgp_afi_vpn_rd_route_cmd
,
12774 "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]",
12778 "Address Family modifier\n"
12779 "Display information for a route distinguisher\n"
12780 "Route Distinguisher\n"
12781 "Network in the BGP routing table to display\n"
12782 "Network in the BGP routing table to display\n"
12786 struct prefix_rd prd
;
12787 afi_t afi
= AFI_MAX
;
12790 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12791 vty_out(vty
, "%% Malformed Address Family\n");
12792 return CMD_WARNING
;
12795 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12797 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12798 return CMD_WARNING
;
12801 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12802 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12805 static struct bgp_distance
*bgp_distance_new(void)
12807 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12810 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12812 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12815 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12816 const char *ip_str
, const char *access_list_str
)
12823 struct bgp_dest
*dest
;
12824 struct bgp_distance
*bdistance
;
12826 afi
= bgp_node_afi(vty
);
12827 safi
= bgp_node_safi(vty
);
12829 ret
= str2prefix(ip_str
, &p
);
12831 vty_out(vty
, "Malformed prefix\n");
12832 return CMD_WARNING_CONFIG_FAILED
;
12835 distance
= atoi(distance_str
);
12837 /* Get BGP distance node. */
12838 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
12839 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12841 bgp_dest_unlock_node(dest
);
12843 bdistance
= bgp_distance_new();
12844 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
12847 /* Set distance value. */
12848 bdistance
->distance
= distance
;
12850 /* Reset access-list configuration. */
12851 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12852 if (access_list_str
)
12853 bdistance
->access_list
=
12854 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12856 return CMD_SUCCESS
;
12859 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12860 const char *ip_str
, const char *access_list_str
)
12867 struct bgp_dest
*dest
;
12868 struct bgp_distance
*bdistance
;
12870 afi
= bgp_node_afi(vty
);
12871 safi
= bgp_node_safi(vty
);
12873 ret
= str2prefix(ip_str
, &p
);
12875 vty_out(vty
, "Malformed prefix\n");
12876 return CMD_WARNING_CONFIG_FAILED
;
12879 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
12881 vty_out(vty
, "Can't find specified prefix\n");
12882 return CMD_WARNING_CONFIG_FAILED
;
12885 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12886 distance
= atoi(distance_str
);
12888 if (bdistance
->distance
!= distance
) {
12889 vty_out(vty
, "Distance does not match configured\n");
12890 return CMD_WARNING_CONFIG_FAILED
;
12893 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12894 bgp_distance_free(bdistance
);
12896 bgp_dest_set_bgp_path_info(dest
, NULL
);
12897 bgp_dest_unlock_node(dest
);
12898 bgp_dest_unlock_node(dest
);
12900 return CMD_SUCCESS
;
12903 /* Apply BGP information to distance method. */
12904 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
12905 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12907 struct bgp_dest
*dest
;
12910 struct bgp_distance
*bdistance
;
12911 struct access_list
*alist
;
12912 struct bgp_static
*bgp_static
;
12917 peer
= pinfo
->peer
;
12919 if (pinfo
->attr
->distance
)
12920 return pinfo
->attr
->distance
;
12922 /* Check source address. */
12923 sockunion2hostprefix(&peer
->su
, &q
);
12924 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12926 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
12927 bgp_dest_unlock_node(dest
);
12929 if (bdistance
->access_list
) {
12930 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12932 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12933 return bdistance
->distance
;
12935 return bdistance
->distance
;
12938 /* Backdoor check. */
12939 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12941 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
12942 bgp_dest_unlock_node(dest
);
12944 if (bgp_static
->backdoor
) {
12945 if (bgp
->distance_local
[afi
][safi
])
12946 return bgp
->distance_local
[afi
][safi
];
12948 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12952 if (peer
->sort
== BGP_PEER_EBGP
) {
12953 if (bgp
->distance_ebgp
[afi
][safi
])
12954 return bgp
->distance_ebgp
[afi
][safi
];
12955 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12957 if (bgp
->distance_ibgp
[afi
][safi
])
12958 return bgp
->distance_ibgp
[afi
][safi
];
12959 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12963 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12964 * we should tell ZEBRA update the routes for a specific
12965 * AFI/SAFI to reflect changes in RIB.
12967 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12969 safi_t update_safi
)
12974 FOREACH_AFI_SAFI (afi
, safi
) {
12975 if (!bgp_fibupd_safi(safi
))
12978 if (afi
!= update_afi
&& safi
!= update_safi
)
12981 if (BGP_DEBUG(zebra
, ZEBRA
))
12983 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12984 __func__
, afi
, safi
);
12985 bgp_zebra_announce_table(bgp
, afi
, safi
);
12989 DEFUN (bgp_distance
,
12991 "distance bgp (1-255) (1-255) (1-255)",
12992 "Define an administrative distance\n"
12994 "Distance for routes external to the AS\n"
12995 "Distance for routes internal to the AS\n"
12996 "Distance for local routes\n")
12998 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12999 int idx_number
= 2;
13000 int idx_number_2
= 3;
13001 int idx_number_3
= 4;
13002 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
13003 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
13004 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
13008 afi
= bgp_node_afi(vty
);
13009 safi
= bgp_node_safi(vty
);
13011 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
13012 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
13013 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
13014 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
13015 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
13016 bgp
->distance_local
[afi
][safi
] = distance_local
;
13017 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13019 return CMD_SUCCESS
;
13022 DEFUN (no_bgp_distance
,
13023 no_bgp_distance_cmd
,
13024 "no distance bgp [(1-255) (1-255) (1-255)]",
13026 "Define an administrative distance\n"
13028 "Distance for routes external to the AS\n"
13029 "Distance for routes internal to the AS\n"
13030 "Distance for local routes\n")
13032 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13036 afi
= bgp_node_afi(vty
);
13037 safi
= bgp_node_safi(vty
);
13039 if (bgp
->distance_ebgp
[afi
][safi
] != 0
13040 || bgp
->distance_ibgp
[afi
][safi
] != 0
13041 || bgp
->distance_local
[afi
][safi
] != 0) {
13042 bgp
->distance_ebgp
[afi
][safi
] = 0;
13043 bgp
->distance_ibgp
[afi
][safi
] = 0;
13044 bgp
->distance_local
[afi
][safi
] = 0;
13045 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13047 return CMD_SUCCESS
;
13051 DEFUN (bgp_distance_source
,
13052 bgp_distance_source_cmd
,
13053 "distance (1-255) A.B.C.D/M",
13054 "Define an administrative distance\n"
13055 "Administrative distance\n"
13056 "IP source prefix\n")
13058 int idx_number
= 1;
13059 int idx_ipv4_prefixlen
= 2;
13060 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13061 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13062 return CMD_SUCCESS
;
13065 DEFUN (no_bgp_distance_source
,
13066 no_bgp_distance_source_cmd
,
13067 "no distance (1-255) A.B.C.D/M",
13069 "Define an administrative distance\n"
13070 "Administrative distance\n"
13071 "IP source prefix\n")
13073 int idx_number
= 2;
13074 int idx_ipv4_prefixlen
= 3;
13075 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13076 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13077 return CMD_SUCCESS
;
13080 DEFUN (bgp_distance_source_access_list
,
13081 bgp_distance_source_access_list_cmd
,
13082 "distance (1-255) A.B.C.D/M WORD",
13083 "Define an administrative distance\n"
13084 "Administrative distance\n"
13085 "IP source prefix\n"
13086 "Access list name\n")
13088 int idx_number
= 1;
13089 int idx_ipv4_prefixlen
= 2;
13091 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13092 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13093 return CMD_SUCCESS
;
13096 DEFUN (no_bgp_distance_source_access_list
,
13097 no_bgp_distance_source_access_list_cmd
,
13098 "no distance (1-255) A.B.C.D/M WORD",
13100 "Define an administrative distance\n"
13101 "Administrative distance\n"
13102 "IP source prefix\n"
13103 "Access list name\n")
13105 int idx_number
= 2;
13106 int idx_ipv4_prefixlen
= 3;
13108 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13109 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13110 return CMD_SUCCESS
;
13113 DEFUN (ipv6_bgp_distance_source
,
13114 ipv6_bgp_distance_source_cmd
,
13115 "distance (1-255) X:X::X:X/M",
13116 "Define an administrative distance\n"
13117 "Administrative distance\n"
13118 "IP source prefix\n")
13120 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
13121 return CMD_SUCCESS
;
13124 DEFUN (no_ipv6_bgp_distance_source
,
13125 no_ipv6_bgp_distance_source_cmd
,
13126 "no distance (1-255) X:X::X:X/M",
13128 "Define an administrative distance\n"
13129 "Administrative distance\n"
13130 "IP source prefix\n")
13132 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
13133 return CMD_SUCCESS
;
13136 DEFUN (ipv6_bgp_distance_source_access_list
,
13137 ipv6_bgp_distance_source_access_list_cmd
,
13138 "distance (1-255) X:X::X:X/M WORD",
13139 "Define an administrative distance\n"
13140 "Administrative distance\n"
13141 "IP source prefix\n"
13142 "Access list name\n")
13144 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
13145 return CMD_SUCCESS
;
13148 DEFUN (no_ipv6_bgp_distance_source_access_list
,
13149 no_ipv6_bgp_distance_source_access_list_cmd
,
13150 "no distance (1-255) X:X::X:X/M WORD",
13152 "Define an administrative distance\n"
13153 "Administrative distance\n"
13154 "IP source prefix\n"
13155 "Access list name\n")
13157 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
13158 return CMD_SUCCESS
;
13161 DEFUN (bgp_damp_set
,
13163 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13164 "BGP Specific commands\n"
13165 "Enable route-flap dampening\n"
13166 "Half-life time for the penalty\n"
13167 "Value to start reusing a route\n"
13168 "Value to start suppressing a route\n"
13169 "Maximum duration to suppress a stable route\n")
13171 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13172 int idx_half_life
= 2;
13174 int idx_suppress
= 4;
13175 int idx_max_suppress
= 5;
13176 int half
= DEFAULT_HALF_LIFE
* 60;
13177 int reuse
= DEFAULT_REUSE
;
13178 int suppress
= DEFAULT_SUPPRESS
;
13179 int max
= 4 * half
;
13182 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13183 reuse
= atoi(argv
[idx_reuse
]->arg
);
13184 suppress
= atoi(argv
[idx_suppress
]->arg
);
13185 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
13186 } else if (argc
== 3) {
13187 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13192 * These can't be 0 but our SA doesn't understand the
13193 * way our cli is constructed
13197 if (suppress
< reuse
) {
13199 "Suppress value cannot be less than reuse value \n");
13203 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
13204 reuse
, suppress
, max
);
13207 DEFUN (bgp_damp_unset
,
13208 bgp_damp_unset_cmd
,
13209 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13211 "BGP Specific commands\n"
13212 "Enable route-flap dampening\n"
13213 "Half-life time for the penalty\n"
13214 "Value to start reusing a route\n"
13215 "Value to start suppressing a route\n"
13216 "Maximum duration to suppress a stable route\n")
13218 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13219 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
13222 /* Display specified route of BGP table. */
13223 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
13224 const char *ip_str
, afi_t afi
, safi_t safi
,
13225 struct prefix_rd
*prd
, int prefix_check
)
13228 struct prefix match
;
13229 struct bgp_dest
*dest
;
13230 struct bgp_dest
*rm
;
13231 struct bgp_path_info
*pi
;
13232 struct bgp_path_info
*pi_temp
;
13234 struct bgp_table
*table
;
13236 /* BGP structure lookup. */
13238 bgp
= bgp_lookup_by_name(view_name
);
13240 vty_out(vty
, "%% Can't find BGP instance %s\n",
13242 return CMD_WARNING
;
13245 bgp
= bgp_get_default();
13247 vty_out(vty
, "%% No BGP process is configured\n");
13248 return CMD_WARNING
;
13252 /* Check IP address argument. */
13253 ret
= str2prefix(ip_str
, &match
);
13255 vty_out(vty
, "%% address is malformed\n");
13256 return CMD_WARNING
;
13259 match
.family
= afi2family(afi
);
13261 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13262 || (safi
== SAFI_EVPN
)) {
13263 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
13264 dest
= bgp_route_next(dest
)) {
13265 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13267 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
13269 table
= bgp_dest_get_bgp_table_info(dest
);
13272 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
13275 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
13278 || rm_p
->prefixlen
== match
.prefixlen
) {
13279 pi
= bgp_dest_get_bgp_path_info(rm
);
13281 if (pi
->extra
&& pi
->extra
->damp_info
) {
13282 pi_temp
= pi
->next
;
13283 bgp_damp_info_free(
13284 pi
->extra
->damp_info
,
13292 bgp_dest_unlock_node(rm
);
13295 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
13297 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13300 || dest_p
->prefixlen
== match
.prefixlen
) {
13301 pi
= bgp_dest_get_bgp_path_info(dest
);
13303 if (pi
->extra
&& pi
->extra
->damp_info
) {
13304 pi_temp
= pi
->next
;
13305 bgp_damp_info_free(
13306 pi
->extra
->damp_info
,
13314 bgp_dest_unlock_node(dest
);
13318 return CMD_SUCCESS
;
13321 DEFUN (clear_ip_bgp_dampening
,
13322 clear_ip_bgp_dampening_cmd
,
13323 "clear ip bgp dampening",
13327 "Clear route flap dampening information\n")
13329 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
13330 return CMD_SUCCESS
;
13333 DEFUN (clear_ip_bgp_dampening_prefix
,
13334 clear_ip_bgp_dampening_prefix_cmd
,
13335 "clear ip bgp dampening A.B.C.D/M",
13339 "Clear route flap dampening information\n"
13342 int idx_ipv4_prefixlen
= 4;
13343 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
13344 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
13347 DEFUN (clear_ip_bgp_dampening_address
,
13348 clear_ip_bgp_dampening_address_cmd
,
13349 "clear ip bgp dampening A.B.C.D",
13353 "Clear route flap dampening information\n"
13354 "Network to clear damping information\n")
13357 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
13358 SAFI_UNICAST
, NULL
, 0);
13361 DEFUN (clear_ip_bgp_dampening_address_mask
,
13362 clear_ip_bgp_dampening_address_mask_cmd
,
13363 "clear ip bgp dampening A.B.C.D A.B.C.D",
13367 "Clear route flap dampening information\n"
13368 "Network to clear damping information\n"
13372 int idx_ipv4_2
= 5;
13374 char prefix_str
[BUFSIZ
];
13376 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
13379 vty_out(vty
, "%% Inconsistent address and mask\n");
13380 return CMD_WARNING
;
13383 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
13387 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
13389 struct vty
*vty
= arg
;
13390 struct peer
*peer
= bucket
->data
;
13391 char buf
[SU_ADDRSTRLEN
];
13393 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
13394 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
13397 DEFUN (show_bgp_listeners
,
13398 show_bgp_listeners_cmd
,
13399 "show bgp listeners",
13402 "Display Listen Sockets and who created them\n")
13404 bgp_dump_listener_info(vty
);
13406 return CMD_SUCCESS
;
13409 DEFUN (show_bgp_peerhash
,
13410 show_bgp_peerhash_cmd
,
13411 "show bgp peerhash",
13414 "Display information about the BGP peerhash\n")
13416 struct list
*instances
= bm
->bgp
;
13417 struct listnode
*node
;
13420 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
13421 vty_out(vty
, "BGP: %s\n", bgp
->name
);
13422 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
13426 return CMD_SUCCESS
;
13429 /* also used for encap safi */
13430 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
13431 afi_t afi
, safi_t safi
)
13433 struct bgp_dest
*pdest
;
13434 struct bgp_dest
*dest
;
13435 struct bgp_table
*table
;
13436 const struct prefix
*p
;
13437 const struct prefix_rd
*prd
;
13438 struct bgp_static
*bgp_static
;
13439 mpls_label_t label
;
13440 char buf
[SU_ADDRSTRLEN
];
13441 char rdbuf
[RD_ADDRSTRLEN
];
13443 /* Network configuration. */
13444 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13445 pdest
= bgp_route_next(pdest
)) {
13446 table
= bgp_dest_get_bgp_table_info(pdest
);
13450 for (dest
= bgp_table_top(table
); dest
;
13451 dest
= bgp_route_next(dest
)) {
13452 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13453 if (bgp_static
== NULL
)
13456 p
= bgp_dest_get_prefix(dest
);
13457 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13460 /* "network" configuration display. */
13461 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13462 label
= decode_label(&bgp_static
->label
);
13464 vty_out(vty
, " network %s/%d rd %s",
13465 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
13467 p
->prefixlen
, rdbuf
);
13468 if (safi
== SAFI_MPLS_VPN
)
13469 vty_out(vty
, " label %u", label
);
13471 if (bgp_static
->rmap
.name
)
13472 vty_out(vty
, " route-map %s",
13473 bgp_static
->rmap
.name
);
13475 if (bgp_static
->backdoor
)
13476 vty_out(vty
, " backdoor");
13478 vty_out(vty
, "\n");
13483 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
13484 afi_t afi
, safi_t safi
)
13486 struct bgp_dest
*pdest
;
13487 struct bgp_dest
*dest
;
13488 struct bgp_table
*table
;
13489 const struct prefix
*p
;
13490 const struct prefix_rd
*prd
;
13491 struct bgp_static
*bgp_static
;
13492 char buf
[PREFIX_STRLEN
* 2];
13493 char buf2
[SU_ADDRSTRLEN
];
13494 char rdbuf
[RD_ADDRSTRLEN
];
13495 char esi_buf
[ESI_BYTES
];
13497 /* Network configuration. */
13498 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13499 pdest
= bgp_route_next(pdest
)) {
13500 table
= bgp_dest_get_bgp_table_info(pdest
);
13504 for (dest
= bgp_table_top(table
); dest
;
13505 dest
= bgp_route_next(dest
)) {
13506 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13507 if (bgp_static
== NULL
)
13510 char *macrouter
= NULL
;
13512 if (bgp_static
->router_mac
)
13513 macrouter
= prefix_mac2str(
13514 bgp_static
->router_mac
, NULL
, 0);
13515 if (bgp_static
->eth_s_id
)
13516 esi_to_str(bgp_static
->eth_s_id
,
13517 esi_buf
, sizeof(esi_buf
));
13518 p
= bgp_dest_get_prefix(dest
);
13519 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
13521 /* "network" configuration display. */
13522 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13523 if (p
->u
.prefix_evpn
.route_type
== 5) {
13524 char local_buf
[PREFIX_STRLEN
];
13525 uint8_t family
= is_evpn_prefix_ipaddr_v4((
13526 struct prefix_evpn
*)p
)
13530 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
13531 local_buf
, PREFIX_STRLEN
);
13532 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
13533 p
->u
.prefix_evpn
.prefix_addr
13534 .ip_prefix_length
);
13536 prefix2str(p
, buf
, sizeof(buf
));
13539 if (bgp_static
->gatewayIp
.family
== AF_INET
13540 || bgp_static
->gatewayIp
.family
== AF_INET6
)
13541 inet_ntop(bgp_static
->gatewayIp
.family
,
13542 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
13545 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
13547 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
13548 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
13551 XFREE(MTYPE_TMP
, macrouter
);
13556 /* Configuration of static route announcement and aggregate
13558 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13561 struct bgp_dest
*dest
;
13562 const struct prefix
*p
;
13563 struct bgp_static
*bgp_static
;
13564 struct bgp_aggregate
*bgp_aggregate
;
13565 char buf
[SU_ADDRSTRLEN
];
13567 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
13568 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
13572 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
13573 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
13577 /* Network configuration. */
13578 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
13579 dest
= bgp_route_next(dest
)) {
13580 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13581 if (bgp_static
== NULL
)
13584 p
= bgp_dest_get_prefix(dest
);
13586 vty_out(vty
, " network %s/%d",
13587 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13590 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
13591 vty_out(vty
, " label-index %u",
13592 bgp_static
->label_index
);
13594 if (bgp_static
->rmap
.name
)
13595 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
13597 if (bgp_static
->backdoor
)
13598 vty_out(vty
, " backdoor");
13600 vty_out(vty
, "\n");
13603 /* Aggregate-address configuration. */
13604 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
13605 dest
= bgp_route_next(dest
)) {
13606 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
13607 if (bgp_aggregate
== NULL
)
13610 p
= bgp_dest_get_prefix(dest
);
13612 vty_out(vty
, " aggregate-address %s/%d",
13613 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13616 if (bgp_aggregate
->as_set
)
13617 vty_out(vty
, " as-set");
13619 if (bgp_aggregate
->summary_only
)
13620 vty_out(vty
, " summary-only");
13622 if (bgp_aggregate
->rmap
.name
)
13623 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
13625 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
13626 vty_out(vty
, " origin %s",
13627 bgp_origin2str(bgp_aggregate
->origin
));
13629 vty_out(vty
, "\n");
13633 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13636 struct bgp_dest
*dest
;
13637 struct bgp_distance
*bdistance
;
13639 /* Distance configuration. */
13640 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
13641 && bgp
->distance_local
[afi
][safi
]
13642 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
13643 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
13644 || bgp
->distance_local
[afi
][safi
]
13645 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
13646 vty_out(vty
, " distance bgp %d %d %d\n",
13647 bgp
->distance_ebgp
[afi
][safi
],
13648 bgp
->distance_ibgp
[afi
][safi
],
13649 bgp
->distance_local
[afi
][safi
]);
13652 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
13653 dest
= bgp_route_next(dest
)) {
13654 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13655 if (bdistance
!= NULL
)
13656 vty_out(vty
, " distance %d %pRN %s\n",
13657 bdistance
->distance
, dest
,
13658 bdistance
->access_list
? bdistance
->access_list
13663 /* Allocate routing table structure and install commands. */
13664 void bgp_route_init(void)
13669 /* Init BGP distance table. */
13670 FOREACH_AFI_SAFI (afi
, safi
)
13671 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
13673 /* IPv4 BGP commands. */
13674 install_element(BGP_NODE
, &bgp_table_map_cmd
);
13675 install_element(BGP_NODE
, &bgp_network_cmd
);
13676 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
13678 install_element(BGP_NODE
, &aggregate_address_cmd
);
13679 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
13680 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
13681 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
13683 /* IPv4 unicast configuration. */
13684 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
13685 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
13686 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
13688 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
13689 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
13690 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
13691 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
13693 /* IPv4 multicast configuration. */
13694 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
13695 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
13696 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
13697 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
13698 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
13699 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
13700 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13702 /* IPv4 labeled-unicast configuration. */
13703 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
13704 install_element(BGP_IPV4L_NODE
, &aggregate_address_cmd
);
13705 install_element(BGP_IPV4L_NODE
, &aggregate_address_mask_cmd
);
13706 install_element(BGP_IPV4L_NODE
, &no_aggregate_address_cmd
);
13707 install_element(BGP_IPV4L_NODE
, &no_aggregate_address_mask_cmd
);
13709 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13710 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13711 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
13712 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
13713 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13714 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13715 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13716 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
13718 install_element(VIEW_NODE
,
13719 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13720 install_element(VIEW_NODE
,
13721 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
13722 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13723 install_element(VIEW_NODE
,
13724 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13725 #ifdef KEEP_OLD_VPN_COMMANDS
13726 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13727 #endif /* KEEP_OLD_VPN_COMMANDS */
13728 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13729 install_element(VIEW_NODE
,
13730 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13732 /* BGP dampening clear commands */
13733 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13734 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13736 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13737 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13740 install_element(ENABLE_NODE
,
13741 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13742 #ifdef KEEP_OLD_VPN_COMMANDS
13743 install_element(ENABLE_NODE
,
13744 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13745 #endif /* KEEP_OLD_VPN_COMMANDS */
13747 /* New config IPv6 BGP commands. */
13748 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13749 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13750 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13752 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13753 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13755 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13757 /* IPv6 labeled unicast address family. */
13758 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
13759 install_element(BGP_IPV6L_NODE
, &ipv6_aggregate_address_cmd
);
13760 install_element(BGP_IPV6L_NODE
, &no_ipv6_aggregate_address_cmd
);
13762 install_element(BGP_NODE
, &bgp_distance_cmd
);
13763 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13764 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13765 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13766 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13767 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13768 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13769 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13770 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13771 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13772 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13773 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13774 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13775 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13776 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13777 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13778 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13779 install_element(BGP_IPV4M_NODE
,
13780 &no_bgp_distance_source_access_list_cmd
);
13781 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13782 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13783 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13784 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13785 install_element(BGP_IPV6_NODE
,
13786 &ipv6_bgp_distance_source_access_list_cmd
);
13787 install_element(BGP_IPV6_NODE
,
13788 &no_ipv6_bgp_distance_source_access_list_cmd
);
13789 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13790 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13791 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13792 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13793 install_element(BGP_IPV6M_NODE
,
13794 &ipv6_bgp_distance_source_access_list_cmd
);
13795 install_element(BGP_IPV6M_NODE
,
13796 &no_ipv6_bgp_distance_source_access_list_cmd
);
13798 /* BGP dampening */
13799 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13800 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13801 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13802 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13803 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13804 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13805 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
13806 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
13807 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
13808 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
13809 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
13810 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
13811 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
13812 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
13814 /* Large Communities */
13815 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13816 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13818 /* show bgp ipv4 flowspec detailed */
13819 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13821 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
13822 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13825 void bgp_route_finish(void)
13830 FOREACH_AFI_SAFI (afi
, safi
) {
13831 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13832 bgp_distance_table
[afi
][safi
] = NULL
;