1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "sockunion.h"
38 #include "workqueue.h"
43 #include "lib_errors.h"
45 #include "bgpd/bgpd.h"
46 #include "bgpd/bgp_table.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_attr.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_errors.h"
51 #include "bgpd/bgp_aspath.h"
52 #include "bgpd/bgp_regex.h"
53 #include "bgpd/bgp_community.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_clist.h"
57 #include "bgpd/bgp_packet.h"
58 #include "bgpd/bgp_filter.h"
59 #include "bgpd/bgp_fsm.h"
60 #include "bgpd/bgp_mplsvpn.h"
61 #include "bgpd/bgp_nexthop.h"
62 #include "bgpd/bgp_damp.h"
63 #include "bgpd/bgp_advertise.h"
64 #include "bgpd/bgp_zebra.h"
65 #include "bgpd/bgp_vty.h"
66 #include "bgpd/bgp_mpath.h"
67 #include "bgpd/bgp_nht.h"
68 #include "bgpd/bgp_updgrp.h"
69 #include "bgpd/bgp_label.h"
70 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/bgp_mac.h"
72 #include "bgpd/bgp_network.h"
75 #include "bgpd/rfapi/rfapi_backend.h"
76 #include "bgpd/rfapi/vnc_import_bgp.h"
77 #include "bgpd/rfapi/vnc_export_bgp.h"
79 #include "bgpd/bgp_encap_types.h"
80 #include "bgpd/bgp_encap_tlv.h"
81 #include "bgpd/bgp_evpn.h"
82 #include "bgpd/bgp_evpn_mh.h"
83 #include "bgpd/bgp_evpn_vty.h"
84 #include "bgpd/bgp_flowspec.h"
85 #include "bgpd/bgp_flowspec_util.h"
86 #include "bgpd/bgp_pbr.h"
88 #ifndef VTYSH_EXTRACT_PL
89 #include "bgpd/bgp_route_clippy.c"
92 /* Extern from bgp_dump.c */
93 extern const char *bgp_origin_str
[];
94 extern const char *bgp_origin_long_str
[];
95 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
97 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
98 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
99 static const struct message bgp_pmsi_tnltype_str
[] = {
100 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
101 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
102 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
103 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
104 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
105 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
106 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
107 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
111 #define VRFID_NONE_STR "-"
113 DEFINE_HOOK(bgp_process
,
114 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
115 struct peer
*peer
, bool withdraw
),
116 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
119 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
120 safi_t safi
, const struct prefix
*p
,
121 struct prefix_rd
*prd
)
123 struct bgp_dest
*dest
;
124 struct bgp_dest
*pdest
= NULL
;
128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
129 || (safi
== SAFI_EVPN
)) {
130 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
132 if (!bgp_dest_has_bgp_path_info_data(pdest
))
133 bgp_dest_set_bgp_table_info(
134 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
136 bgp_dest_unlock_node(pdest
);
137 table
= bgp_dest_get_bgp_table_info(pdest
);
140 dest
= bgp_node_get(table
, p
);
142 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
143 || (safi
== SAFI_EVPN
))
149 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
150 safi_t safi
, const struct prefix
*p
,
151 struct prefix_rd
*prd
)
153 struct bgp_dest
*dest
;
154 struct bgp_dest
*pdest
= NULL
;
159 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
160 || (safi
== SAFI_EVPN
)) {
161 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
165 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
166 bgp_dest_unlock_node(pdest
);
170 table
= bgp_dest_get_bgp_table_info(pdest
);
173 dest
= bgp_node_lookup(table
, p
);
178 /* Allocate bgp_path_info_extra */
179 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
181 struct bgp_path_info_extra
*new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
183 sizeof(struct bgp_path_info_extra
));
184 new->label
[0] = MPLS_INVALID_LABEL
;
186 new->bgp_fs_pbr
= NULL
;
187 new->bgp_fs_iprule
= NULL
;
191 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
193 struct bgp_path_info_extra
*e
;
195 if (!extra
|| !*extra
)
200 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
205 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
218 bpi
= bgp_path_info_lock(bpi
);
219 refcount
= bpi
->net
->lock
- 1;
220 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
223 bgp_path_info_unlock(bpi
);
225 bgp_path_info_unlock(e
->parent
);
230 bgp_unlock(e
->bgp_orig
);
232 if ((*extra
)->bgp_fs_iprule
)
233 list_delete(&((*extra
)->bgp_fs_iprule
));
234 if ((*extra
)->bgp_fs_pbr
)
235 list_delete(&((*extra
)->bgp_fs_pbr
));
236 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
239 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
242 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
245 pi
->extra
= bgp_path_info_extra_new();
249 /* Free bgp route information. */
250 static void bgp_path_info_free(struct bgp_path_info
*path
)
252 bgp_attr_unintern(&path
->attr
);
254 bgp_unlink_nexthop(path
);
255 bgp_path_info_extra_free(&path
->extra
);
256 bgp_path_info_mpath_free(&path
->mpath
);
258 bgp_addpath_free_info_data(&path
->tx_addpath
,
259 &path
->net
->tx_addpath
);
261 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
263 XFREE(MTYPE_BGP_ROUTE
, path
);
266 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
272 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
274 assert(path
&& path
->lock
> 0);
277 if (path
->lock
== 0) {
279 zlog_debug ("%s: unlocked and freeing", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
282 bgp_path_info_free(path
);
289 zlog_debug ("%s: unlocked to 1", __func__
);
290 zlog_backtrace (LOG_DEBUG
);
297 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
298 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
301 struct bgp_path_info
*old_pi
, *nextpi
;
302 bool set_flag
= false;
303 struct bgp
*bgp
= NULL
;
304 struct bgp_table
*table
= NULL
;
308 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
309 * then the route selection is deferred
311 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
314 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
315 if (BGP_DEBUG(update
, UPDATE_OUT
))
317 "Route %pRN is in workqueue and being processed, not deferred.",
318 bgp_dest_to_rnode(dest
));
323 table
= bgp_dest_table(dest
);
330 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
331 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
332 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
335 /* Route selection is deferred if there is a stale path which
336 * which indicates peer is in restart mode
338 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
339 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
342 /* If the peer is graceful restart capable and peer is
343 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
346 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
347 && BGP_PEER_RESTARTING_MODE(peer
)
349 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
357 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
360 if (set_flag
&& table
) {
361 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
362 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
363 if (dest
->rt_node
== NULL
)
364 dest
->rt_node
= listnode_add(
365 bgp
->gr_info
[afi
][safi
].route_list
,
367 if (BGP_DEBUG(update
, UPDATE_OUT
))
368 zlog_debug("DEFER route %pRN, dest %p, node %p",
369 dest
, dest
, dest
->rt_node
);
376 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
378 struct bgp_path_info
*top
;
380 top
= bgp_dest_get_bgp_path_info(dest
);
386 bgp_dest_set_bgp_path_info(dest
, pi
);
388 bgp_path_info_lock(pi
);
389 bgp_dest_lock_node(dest
);
390 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
391 bgp_dest_set_defer_flag(dest
, false);
394 /* Do the actual removal of info from RIB, for use by bgp_process
395 completion callback *only* */
396 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
399 pi
->next
->prev
= pi
->prev
;
401 pi
->prev
->next
= pi
->next
;
403 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
405 bgp_path_info_mpath_dequeue(pi
);
406 bgp_path_info_unlock(pi
);
407 bgp_dest_unlock_node(dest
);
410 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
412 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
413 /* set of previous already took care of pcount */
414 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
417 /* undo the effects of a previous call to bgp_path_info_delete; typically
418 called when a route is deleted and then quickly re-added before the
419 deletion has been processed */
420 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
422 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
423 /* unset of previous already took care of pcount */
424 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
427 /* Adjust pcount as required */
428 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
430 struct bgp_table
*table
;
432 assert(dest
&& bgp_dest_table(dest
));
433 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
435 table
= bgp_dest_table(dest
);
437 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
440 if (!BGP_PATH_COUNTABLE(pi
)
441 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
443 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
445 /* slight hack, but more robust against errors. */
446 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
447 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
449 flog_err(EC_LIB_DEVELOPMENT
,
450 "Asked to decrement 0 prefix count for peer");
451 } else if (BGP_PATH_COUNTABLE(pi
)
452 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
453 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
454 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
458 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
459 struct bgp_path_info
*pi2
)
461 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
464 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
465 * This is here primarily to keep prefix-count in check.
467 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
470 SET_FLAG(pi
->flags
, flag
);
472 /* early bath if we know it's not a flag that changes countability state
474 if (!CHECK_FLAG(flag
,
475 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
478 bgp_pcount_adjust(dest
, pi
);
481 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
484 UNSET_FLAG(pi
->flags
, flag
);
486 /* early bath if we know it's not a flag that changes countability state
488 if (!CHECK_FLAG(flag
,
489 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
492 bgp_pcount_adjust(dest
, pi
);
495 /* Get MED value. If MED value is missing and "bgp bestpath
496 missing-as-worst" is specified, treat it as the worst value. */
497 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
499 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
502 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
509 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
511 if (pi
->addpath_rx_id
)
512 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
515 sprintf(buf
, "path %s", pi
->peer
->host
);
518 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
520 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
521 struct bgp_path_info
*exist
, int *paths_eq
,
522 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
523 char *pfx_buf
, afi_t afi
, safi_t safi
,
524 enum bgp_path_selection_reason
*reason
)
526 struct attr
*newattr
, *existattr
;
527 bgp_peer_sort_t new_sort
;
528 bgp_peer_sort_t exist_sort
;
534 uint32_t exist_weight
;
535 uint32_t newm
, existm
;
536 struct in_addr new_id
;
537 struct in_addr exist_id
;
540 int internal_as_route
;
543 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
544 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
546 uint32_t exist_mm_seq
;
558 *reason
= bgp_path_selection_none
;
560 zlog_debug("%s: new is NULL", pfx_buf
);
565 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
568 *reason
= bgp_path_selection_first
;
570 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
576 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
577 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
578 pfx_buf
, new_buf
, new->flags
, exist_buf
,
583 existattr
= exist
->attr
;
585 /* For EVPN routes, we cannot just go by local vs remote, we have to
586 * look at the MAC mobility sequence number, if present.
588 if (safi
== SAFI_EVPN
) {
589 /* This is an error condition described in RFC 7432 Section
591 * states that in this scenario "the PE MUST alert the operator"
593 * does not state what other action to take. In order to provide
595 * consistency in this scenario we are going to prefer the path
599 if (newattr
->sticky
!= existattr
->sticky
) {
602 bgp_dest_get_prefix(new->net
), pfx_buf
,
603 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
604 bgp_path_info_path_with_addpath_rx_str(new,
606 bgp_path_info_path_with_addpath_rx_str(
610 if (newattr
->sticky
&& !existattr
->sticky
) {
611 *reason
= bgp_path_selection_evpn_sticky_mac
;
614 "%s: %s wins over %s due to sticky MAC flag",
615 pfx_buf
, new_buf
, exist_buf
);
619 if (!newattr
->sticky
&& existattr
->sticky
) {
620 *reason
= bgp_path_selection_evpn_sticky_mac
;
623 "%s: %s loses to %s due to sticky MAC flag",
624 pfx_buf
, new_buf
, exist_buf
);
629 new_esi
= bgp_evpn_attr_get_esi(newattr
);
630 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
631 if (bgp_evpn_is_esi_valid(new_esi
) &&
632 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
638 /* If both paths have the same non-zero ES and
639 * one path is local it wins.
640 * PS: Note the local path wins even if the remote
641 * has the higher MM seq. The local path's
642 * MM seq will be fixed up to match the highest
643 * rem seq, subsequently.
646 char esi_buf
[ESI_STR_LEN
];
648 if (bgp_evpn_is_path_local(bgp
, new)) {
649 *reason
= bgp_path_selection_evpn_local_path
;
652 "%s: %s wins over %s as ES %s is same and local",
653 pfx_buf
, new_buf
, exist_buf
,
654 esi_to_str(new_esi
, esi_buf
,
658 if (bgp_evpn_is_path_local(bgp
, exist
)) {
659 *reason
= bgp_path_selection_evpn_local_path
;
662 "%s: %s loses to %s as ES %s is same and local",
663 pfx_buf
, new_buf
, exist_buf
,
664 esi_to_str(new_esi
, esi_buf
,
670 new_mm_seq
= mac_mobility_seqnum(newattr
);
671 exist_mm_seq
= mac_mobility_seqnum(existattr
);
673 if (new_mm_seq
> exist_mm_seq
) {
674 *reason
= bgp_path_selection_evpn_seq
;
677 "%s: %s wins over %s due to MM seq %u > %u",
678 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
683 if (new_mm_seq
< exist_mm_seq
) {
684 *reason
= bgp_path_selection_evpn_seq
;
687 "%s: %s loses to %s due to MM seq %u < %u",
688 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
693 /* if the sequence numbers and ESI are the same and one path
694 * is non-proxy it wins (over proxy)
696 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
697 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
698 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
699 old_proxy
!= new_proxy
) {
701 *reason
= bgp_path_selection_evpn_non_proxy
;
704 "%s: %s wins over %s, same seq/es and non-proxy",
705 pfx_buf
, new_buf
, exist_buf
);
709 *reason
= bgp_path_selection_evpn_non_proxy
;
712 "%s: %s loses to %s, same seq/es and non-proxy",
713 pfx_buf
, new_buf
, exist_buf
);
718 * if sequence numbers are the same path with the lowest IP
721 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
723 *reason
= bgp_path_selection_evpn_lower_ip
;
726 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
727 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
728 inet_ntoa(new->attr
->nexthop
));
732 *reason
= bgp_path_selection_evpn_lower_ip
;
735 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
736 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
737 inet_ntoa(new->attr
->nexthop
));
742 /* 1. Weight check. */
743 new_weight
= newattr
->weight
;
744 exist_weight
= existattr
->weight
;
746 if (new_weight
> exist_weight
) {
747 *reason
= bgp_path_selection_weight
;
749 zlog_debug("%s: %s wins over %s due to weight %d > %d",
750 pfx_buf
, new_buf
, exist_buf
, new_weight
,
755 if (new_weight
< exist_weight
) {
756 *reason
= bgp_path_selection_weight
;
758 zlog_debug("%s: %s loses to %s due to weight %d < %d",
759 pfx_buf
, new_buf
, exist_buf
, new_weight
,
764 /* 2. Local preference check. */
765 new_pref
= exist_pref
= bgp
->default_local_pref
;
767 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
768 new_pref
= newattr
->local_pref
;
769 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
770 exist_pref
= existattr
->local_pref
;
772 if (new_pref
> exist_pref
) {
773 *reason
= bgp_path_selection_local_pref
;
776 "%s: %s wins over %s due to localpref %d > %d",
777 pfx_buf
, new_buf
, exist_buf
, new_pref
,
782 if (new_pref
< exist_pref
) {
783 *reason
= bgp_path_selection_local_pref
;
786 "%s: %s loses to %s due to localpref %d < %d",
787 pfx_buf
, new_buf
, exist_buf
, new_pref
,
792 /* 3. Local route check. We prefer:
794 * - BGP_ROUTE_AGGREGATE
795 * - BGP_ROUTE_REDISTRIBUTE
797 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
798 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
799 *reason
= bgp_path_selection_local_route
;
802 "%s: %s wins over %s due to preferred BGP_ROUTE type",
803 pfx_buf
, new_buf
, exist_buf
);
807 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
808 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
809 *reason
= bgp_path_selection_local_route
;
812 "%s: %s loses to %s due to preferred BGP_ROUTE type",
813 pfx_buf
, new_buf
, exist_buf
);
817 /* 4. AS path length check. */
818 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
819 int exist_hops
= aspath_count_hops(existattr
->aspath
);
820 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
822 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
825 aspath_hops
= aspath_count_hops(newattr
->aspath
);
826 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
828 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
829 *reason
= bgp_path_selection_confed_as_path
;
832 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
833 pfx_buf
, new_buf
, exist_buf
,
835 (exist_hops
+ exist_confeds
));
839 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
840 *reason
= bgp_path_selection_confed_as_path
;
843 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
844 pfx_buf
, new_buf
, exist_buf
,
846 (exist_hops
+ exist_confeds
));
850 int newhops
= aspath_count_hops(newattr
->aspath
);
852 if (newhops
< exist_hops
) {
853 *reason
= bgp_path_selection_as_path
;
856 "%s: %s wins over %s due to aspath hopcount %d < %d",
857 pfx_buf
, new_buf
, exist_buf
,
858 newhops
, exist_hops
);
862 if (newhops
> exist_hops
) {
863 *reason
= bgp_path_selection_as_path
;
866 "%s: %s loses to %s due to aspath hopcount %d > %d",
867 pfx_buf
, new_buf
, exist_buf
,
868 newhops
, exist_hops
);
874 /* 5. Origin check. */
875 if (newattr
->origin
< existattr
->origin
) {
876 *reason
= bgp_path_selection_origin
;
878 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
879 pfx_buf
, new_buf
, exist_buf
,
880 bgp_origin_long_str
[newattr
->origin
],
881 bgp_origin_long_str
[existattr
->origin
]);
885 if (newattr
->origin
> existattr
->origin
) {
886 *reason
= bgp_path_selection_origin
;
888 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
889 pfx_buf
, new_buf
, exist_buf
,
890 bgp_origin_long_str
[newattr
->origin
],
891 bgp_origin_long_str
[existattr
->origin
]);
896 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
897 && aspath_count_hops(existattr
->aspath
) == 0);
898 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
899 && aspath_count_confeds(existattr
->aspath
) > 0
900 && aspath_count_hops(newattr
->aspath
) == 0
901 && aspath_count_hops(existattr
->aspath
) == 0);
903 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
904 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
905 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
906 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
907 || internal_as_route
) {
908 new_med
= bgp_med_value(new->attr
, bgp
);
909 exist_med
= bgp_med_value(exist
->attr
, bgp
);
911 if (new_med
< exist_med
) {
912 *reason
= bgp_path_selection_med
;
915 "%s: %s wins over %s due to MED %d < %d",
916 pfx_buf
, new_buf
, exist_buf
, new_med
,
921 if (new_med
> exist_med
) {
922 *reason
= bgp_path_selection_med
;
925 "%s: %s loses to %s due to MED %d > %d",
926 pfx_buf
, new_buf
, exist_buf
, new_med
,
932 /* 7. Peer type check. */
933 new_sort
= new->peer
->sort
;
934 exist_sort
= exist
->peer
->sort
;
936 if (new_sort
== BGP_PEER_EBGP
937 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
938 *reason
= bgp_path_selection_peer
;
941 "%s: %s wins over %s due to eBGP peer > iBGP peer",
942 pfx_buf
, new_buf
, exist_buf
);
946 if (exist_sort
== BGP_PEER_EBGP
947 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
948 *reason
= bgp_path_selection_peer
;
951 "%s: %s loses to %s due to iBGP peer < eBGP peer",
952 pfx_buf
, new_buf
, exist_buf
);
956 /* 8. IGP metric check. */
960 newm
= new->extra
->igpmetric
;
962 existm
= exist
->extra
->igpmetric
;
967 "%s: %s wins over %s due to IGP metric %d < %d",
968 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
975 "%s: %s loses to %s due to IGP metric %d > %d",
976 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
980 /* 9. Same IGP metric. Compare the cluster list length as
981 representative of IGP hops metric. Rewrite the metric value
982 pair (newm, existm) with the cluster list length. Prefer the
983 path with smaller cluster list length. */
984 if (newm
== existm
) {
985 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
986 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
987 && (mpath_cfg
== NULL
989 mpath_cfg
->ibgp_flags
,
990 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
991 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
992 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
997 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
998 pfx_buf
, new_buf
, exist_buf
,
1003 if (newm
> existm
) {
1006 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1007 pfx_buf
, new_buf
, exist_buf
,
1014 /* 10. confed-external vs. confed-internal */
1015 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1016 if (new_sort
== BGP_PEER_CONFED
1017 && exist_sort
== BGP_PEER_IBGP
) {
1018 *reason
= bgp_path_selection_confed
;
1021 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1022 pfx_buf
, new_buf
, exist_buf
);
1026 if (exist_sort
== BGP_PEER_CONFED
1027 && new_sort
== BGP_PEER_IBGP
) {
1028 *reason
= bgp_path_selection_confed
;
1031 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1032 pfx_buf
, new_buf
, exist_buf
);
1037 /* 11. Maximum path check. */
1038 if (newm
== existm
) {
1039 /* If one path has a label but the other does not, do not treat
1040 * them as equals for multipath
1042 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1044 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1047 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1048 pfx_buf
, new_buf
, exist_buf
);
1049 } else if (CHECK_FLAG(bgp
->flags
,
1050 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1053 * For the two paths, all comparison steps till IGP
1055 * have succeeded - including AS_PATH hop count. Since
1057 * bestpath as-path multipath-relax' knob is on, we
1059 * an exact match of AS_PATH. Thus, mark the paths are
1061 * That will trigger both these paths to get into the
1069 "%s: %s and %s are equal via multipath-relax",
1070 pfx_buf
, new_buf
, exist_buf
);
1071 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1072 if (aspath_cmp(new->attr
->aspath
,
1073 exist
->attr
->aspath
)) {
1078 "%s: %s and %s are equal via matching aspaths",
1079 pfx_buf
, new_buf
, exist_buf
);
1081 } else if (new->peer
->as
== exist
->peer
->as
) {
1086 "%s: %s and %s are equal via same remote-as",
1087 pfx_buf
, new_buf
, exist_buf
);
1091 * TODO: If unequal cost ibgp multipath is enabled we can
1092 * mark the paths as equal here instead of returning
1097 "%s: %s wins over %s after IGP metric comparison",
1098 pfx_buf
, new_buf
, exist_buf
);
1101 "%s: %s loses to %s after IGP metric comparison",
1102 pfx_buf
, new_buf
, exist_buf
);
1104 *reason
= bgp_path_selection_igp_metric
;
1108 /* 12. If both paths are external, prefer the path that was received
1109 first (the oldest one). This step minimizes route-flap, since a
1110 newer path won't displace an older one, even if it was the
1111 preferred route based on the additional decision criteria below. */
1112 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1113 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1114 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1115 *reason
= bgp_path_selection_older
;
1118 "%s: %s wins over %s due to oldest external",
1119 pfx_buf
, new_buf
, exist_buf
);
1123 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1124 *reason
= bgp_path_selection_older
;
1127 "%s: %s loses to %s due to oldest external",
1128 pfx_buf
, new_buf
, exist_buf
);
1133 /* 13. Router-ID comparision. */
1134 /* If one of the paths is "stale", the corresponding peer router-id will
1135 * be 0 and would always win over the other path. If originator id is
1136 * used for the comparision, it will decide which path is better.
1138 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1139 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1141 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1142 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1143 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1145 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1147 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1148 *reason
= bgp_path_selection_router_id
;
1151 "%s: %s wins over %s due to Router-ID comparison",
1152 pfx_buf
, new_buf
, exist_buf
);
1156 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1157 *reason
= bgp_path_selection_router_id
;
1160 "%s: %s loses to %s due to Router-ID comparison",
1161 pfx_buf
, new_buf
, exist_buf
);
1165 /* 14. Cluster length comparision. */
1166 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1167 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1169 if (new_cluster
< exist_cluster
) {
1170 *reason
= bgp_path_selection_cluster_length
;
1173 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1174 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1179 if (new_cluster
> exist_cluster
) {
1180 *reason
= bgp_path_selection_cluster_length
;
1183 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1184 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1189 /* 15. Neighbor address comparision. */
1190 /* Do this only if neither path is "stale" as stale paths do not have
1191 * valid peer information (as the connection may or may not be up).
1193 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1194 *reason
= bgp_path_selection_stale
;
1197 "%s: %s wins over %s due to latter path being STALE",
1198 pfx_buf
, new_buf
, exist_buf
);
1202 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1203 *reason
= bgp_path_selection_stale
;
1206 "%s: %s loses to %s due to former path being STALE",
1207 pfx_buf
, new_buf
, exist_buf
);
1211 /* locally configured routes to advertise do not have su_remote */
1212 if (new->peer
->su_remote
== NULL
) {
1213 *reason
= bgp_path_selection_local_configured
;
1216 if (exist
->peer
->su_remote
== NULL
) {
1217 *reason
= bgp_path_selection_local_configured
;
1221 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1224 *reason
= bgp_path_selection_neighbor_ip
;
1227 "%s: %s loses to %s due to Neighor IP comparison",
1228 pfx_buf
, new_buf
, exist_buf
);
1233 *reason
= bgp_path_selection_neighbor_ip
;
1236 "%s: %s wins over %s due to Neighor IP comparison",
1237 pfx_buf
, new_buf
, exist_buf
);
1241 *reason
= bgp_path_selection_default
;
1243 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1244 pfx_buf
, new_buf
, exist_buf
);
1250 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1251 struct bgp_path_info
*exist
, int *paths_eq
)
1253 enum bgp_path_selection_reason reason
;
1254 char pfx_buf
[PREFIX2STR_BUFFER
];
1256 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1257 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1260 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1261 * is preferred, or 0 if they are the same (usually will only occur if
1262 * multipath is enabled
1263 * This version is compatible with */
1264 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1265 struct bgp_path_info
*exist
, char *pfx_buf
,
1266 afi_t afi
, safi_t safi
,
1267 enum bgp_path_selection_reason
*reason
)
1271 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1285 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1286 const struct prefix
*p
,
1287 struct attr
*attr
, afi_t afi
,
1290 struct bgp_filter
*filter
;
1292 filter
= &peer
->filter
[afi
][safi
];
1294 #define FILTER_EXIST_WARN(F, f, filter) \
1295 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1296 zlog_debug("%s: Could not find configured input %s-list %s!", \
1297 peer->host, #f, F##_IN_NAME(filter));
1299 if (DISTRIBUTE_IN_NAME(filter
)) {
1300 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1302 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1306 if (PREFIX_LIST_IN_NAME(filter
)) {
1307 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1309 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1313 if (FILTER_LIST_IN_NAME(filter
)) {
1314 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1316 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1321 return FILTER_PERMIT
;
1322 #undef FILTER_EXIST_WARN
1325 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1326 const struct prefix
*p
,
1327 struct attr
*attr
, afi_t afi
,
1330 struct bgp_filter
*filter
;
1332 filter
= &peer
->filter
[afi
][safi
];
1334 #define FILTER_EXIST_WARN(F, f, filter) \
1335 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1336 zlog_debug("%s: Could not find configured output %s-list %s!", \
1337 peer->host, #f, F##_OUT_NAME(filter));
1339 if (DISTRIBUTE_OUT_NAME(filter
)) {
1340 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1342 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1346 if (PREFIX_LIST_OUT_NAME(filter
)) {
1347 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1349 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1354 if (FILTER_LIST_OUT_NAME(filter
)) {
1355 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1357 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1362 return FILTER_PERMIT
;
1363 #undef FILTER_EXIST_WARN
1366 /* If community attribute includes no_export then return 1. */
1367 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1369 if (attr
->community
) {
1370 /* NO_ADVERTISE check. */
1371 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1374 /* NO_EXPORT check. */
1375 if (peer
->sort
== BGP_PEER_EBGP
1376 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1379 /* NO_EXPORT_SUBCONFED check. */
1380 if (peer
->sort
== BGP_PEER_EBGP
1381 || peer
->sort
== BGP_PEER_CONFED
)
1382 if (community_include(attr
->community
,
1383 COMMUNITY_NO_EXPORT_SUBCONFED
))
1389 /* Route reflection loop check. */
1390 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1392 struct in_addr cluster_id
;
1394 if (attr
->cluster
) {
1395 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1396 cluster_id
= peer
->bgp
->cluster_id
;
1398 cluster_id
= peer
->bgp
->router_id
;
1400 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1406 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1407 struct attr
*attr
, afi_t afi
, safi_t safi
,
1408 const char *rmap_name
, mpls_label_t
*label
,
1409 uint32_t num_labels
, struct bgp_dest
*dest
)
1411 struct bgp_filter
*filter
;
1412 struct bgp_path_info rmap_path
= { 0 };
1413 struct bgp_path_info_extra extra
= { 0 };
1414 route_map_result_t ret
;
1415 struct route_map
*rmap
= NULL
;
1417 filter
= &peer
->filter
[afi
][safi
];
1419 /* Apply default weight value. */
1420 if (peer
->weight
[afi
][safi
])
1421 attr
->weight
= peer
->weight
[afi
][safi
];
1424 rmap
= route_map_lookup_by_name(rmap_name
);
1429 if (ROUTE_MAP_IN_NAME(filter
)) {
1430 rmap
= ROUTE_MAP_IN(filter
);
1437 /* Route map apply. */
1439 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1440 /* Duplicate current value to new strucutre for modification. */
1441 rmap_path
.peer
= peer
;
1442 rmap_path
.attr
= attr
;
1443 rmap_path
.extra
= &extra
;
1444 rmap_path
.net
= dest
;
1446 extra
.num_labels
= num_labels
;
1447 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1448 memcpy(extra
.label
, label
,
1449 num_labels
* sizeof(mpls_label_t
));
1451 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1453 /* Apply BGP route map to the attribute. */
1454 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1456 peer
->rmap_type
= 0;
1458 if (ret
== RMAP_DENYMATCH
)
1464 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1465 struct attr
*attr
, afi_t afi
, safi_t safi
,
1466 const char *rmap_name
)
1468 struct bgp_path_info rmap_path
;
1469 route_map_result_t ret
;
1470 struct route_map
*rmap
= NULL
;
1474 * So if we get to this point and have no rmap_name
1475 * we want to just show the output as it currently
1481 /* Apply default weight value. */
1482 if (peer
->weight
[afi
][safi
])
1483 attr
->weight
= peer
->weight
[afi
][safi
];
1485 rmap
= route_map_lookup_by_name(rmap_name
);
1488 * If we have a route map name and we do not find
1489 * the routemap that means we have an implicit
1495 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1496 /* Route map apply. */
1497 /* Duplicate current value to new strucutre for modification. */
1498 rmap_path
.peer
= peer
;
1499 rmap_path
.attr
= attr
;
1501 rmap_type
= peer
->rmap_type
;
1502 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1504 /* Apply BGP route map to the attribute. */
1505 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1507 peer
->rmap_type
= rmap_type
;
1509 if (ret
== RMAP_DENYMATCH
)
1511 * caller has multiple error paths with bgp_attr_flush()
1518 /* If this is an EBGP peer with remove-private-AS */
1519 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1520 struct peer
*peer
, struct attr
*attr
)
1522 if (peer
->sort
== BGP_PEER_EBGP
1523 && (peer_af_flag_check(peer
, afi
, safi
,
1524 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1525 || peer_af_flag_check(peer
, afi
, safi
,
1526 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1527 || peer_af_flag_check(peer
, afi
, safi
,
1528 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1529 || peer_af_flag_check(peer
, afi
, safi
,
1530 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1531 // Take action on the entire aspath
1532 if (peer_af_flag_check(peer
, afi
, safi
,
1533 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1534 || peer_af_flag_check(peer
, afi
, safi
,
1535 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1536 if (peer_af_flag_check(
1538 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1539 attr
->aspath
= aspath_replace_private_asns(
1540 attr
->aspath
, bgp
->as
, peer
->as
);
1542 // The entire aspath consists of private ASNs so create
1544 else if (aspath_private_as_check(attr
->aspath
))
1545 attr
->aspath
= aspath_empty_get();
1547 // There are some public and some private ASNs, remove
1550 attr
->aspath
= aspath_remove_private_asns(
1551 attr
->aspath
, peer
->as
);
1554 // 'all' was not specified so the entire aspath must be private
1556 // for us to do anything
1557 else if (aspath_private_as_check(attr
->aspath
)) {
1558 if (peer_af_flag_check(
1560 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1561 attr
->aspath
= aspath_replace_private_asns(
1562 attr
->aspath
, bgp
->as
, peer
->as
);
1564 attr
->aspath
= aspath_empty_get();
1569 /* If this is an EBGP peer with as-override */
1570 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1571 struct peer
*peer
, struct attr
*attr
)
1573 if (peer
->sort
== BGP_PEER_EBGP
1574 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1575 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1576 attr
->aspath
= aspath_replace_specific_asn(
1577 attr
->aspath
, peer
->as
, bgp
->as
);
1581 void bgp_attr_add_gshut_community(struct attr
*attr
)
1583 struct community
*old
;
1584 struct community
*new;
1585 struct community
*merge
;
1586 struct community
*gshut
;
1588 old
= attr
->community
;
1589 gshut
= community_str2com("graceful-shutdown");
1594 merge
= community_merge(community_dup(old
), gshut
);
1596 if (old
->refcnt
== 0)
1597 community_free(&old
);
1599 new = community_uniq_sort(merge
);
1600 community_free(&merge
);
1602 new = community_dup(gshut
);
1605 community_free(&gshut
);
1606 attr
->community
= new;
1607 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1609 /* When we add the graceful-shutdown community we must also
1610 * lower the local-preference */
1611 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1612 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1616 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1618 if (family
== AF_INET
) {
1619 attr
->nexthop
.s_addr
= INADDR_ANY
;
1620 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1622 if (family
== AF_INET6
)
1623 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1624 if (family
== AF_EVPN
)
1625 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1628 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1629 struct update_subgroup
*subgrp
,
1630 const struct prefix
*p
, struct attr
*attr
)
1632 struct bgp_filter
*filter
;
1635 struct peer
*onlypeer
;
1637 struct attr
*piattr
;
1638 char buf
[PREFIX_STRLEN
];
1639 route_map_result_t ret
;
1644 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1645 bool nh_reset
= false;
1648 if (DISABLE_BGP_ANNOUNCE
)
1651 afi
= SUBGRP_AFI(subgrp
);
1652 safi
= SUBGRP_SAFI(subgrp
);
1653 peer
= SUBGRP_PEER(subgrp
);
1655 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1656 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1659 filter
= &peer
->filter
[afi
][safi
];
1660 bgp
= SUBGRP_INST(subgrp
);
1661 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1664 #ifdef ENABLE_BGP_VNC
1665 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1666 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1667 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1670 * direct and direct_ext type routes originate internally even
1671 * though they can have peer pointers that reference other
1674 prefix2str(p
, buf
, PREFIX_STRLEN
);
1675 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1681 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1682 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1683 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1684 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1686 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1691 /* With addpath we may be asked to TX all kinds of paths so make sure
1693 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1694 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1695 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1699 /* If this is not the bestpath then check to see if there is an enabled
1701 * feature that requires us to advertise it */
1702 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1703 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1708 /* Aggregate-address suppress check. */
1709 if (pi
->extra
&& pi
->extra
->suppress
)
1710 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1715 * If we are doing VRF 2 VRF leaking via the import
1716 * statement, we want to prevent the route going
1717 * off box as that the RT and RD created are localy
1718 * significant and globaly useless.
1720 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1721 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1724 /* If it's labeled safi, make sure the route has a valid label. */
1725 if (safi
== SAFI_LABELED_UNICAST
) {
1726 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1727 if (!bgp_is_valid_label(&label
)) {
1728 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1729 zlog_debug("u%" PRIu64
":s%" PRIu64
" %s/%d is filtered - no label (%p)",
1730 subgrp
->update_group
->id
, subgrp
->id
,
1731 inet_ntop(p
->family
, &p
->u
.prefix
,
1732 buf
, SU_ADDRSTRLEN
),
1733 p
->prefixlen
, &label
);
1738 /* Do not send back route to sender. */
1739 if (onlypeer
&& from
== onlypeer
) {
1743 /* Do not send the default route in the BGP table if the neighbor is
1744 * configured for default-originate */
1745 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1746 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1747 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1749 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1753 /* Transparency check. */
1754 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1755 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1760 /* If community is not disabled check the no-export and local. */
1761 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1762 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1764 "subgrpannouncecheck: community filter check fail");
1768 /* If the attribute has originator-id and it is same as remote
1770 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1771 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1772 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1774 "%s [Update:SEND] %s originator-id is same as remote router-id",
1776 prefix2str(p
, buf
, sizeof(buf
)));
1780 /* ORF prefix-list filter check */
1781 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1782 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1783 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1784 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1785 if (peer
->orf_plist
[afi
][safi
]) {
1786 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1788 if (bgp_debug_update(NULL
, p
,
1789 subgrp
->update_group
, 0))
1791 "%s [Update:SEND] %s is filtered via ORF",
1799 /* Output filter check. */
1800 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1801 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1802 zlog_debug("%s [Update:SEND] %s is filtered",
1803 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1807 /* AS path loop check. */
1808 if (onlypeer
&& onlypeer
->as_path_loop_detection
1809 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1810 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1812 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1813 onlypeer
->host
, onlypeer
->as
);
1817 /* If we're a CONFED we need to loop check the CONFED ID too */
1818 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1819 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1820 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1822 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1823 peer
->host
, bgp
->confed_id
);
1828 /* Route-Reflect check. */
1829 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1834 /* IBGP reflection check. */
1835 if (reflect
&& !samepeer_safe
) {
1836 /* A route from a Client peer. */
1837 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1838 PEER_FLAG_REFLECTOR_CLIENT
)) {
1839 /* Reflect to all the Non-Client peers and also to the
1840 Client peers other than the originator. Originator
1842 is already done. So there is noting to do. */
1843 /* no bgp client-to-client reflection check. */
1844 if (CHECK_FLAG(bgp
->flags
,
1845 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1846 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1847 PEER_FLAG_REFLECTOR_CLIENT
))
1850 /* A route from a Non-client peer. Reflect to all other
1852 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1853 PEER_FLAG_REFLECTOR_CLIENT
))
1858 /* For modify attribute, copy it to temporary structure. */
1861 /* If local-preference is not set. */
1862 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1863 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1864 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1865 attr
->local_pref
= bgp
->default_local_pref
;
1868 /* If originator-id is not set and the route is to be reflected,
1869 set the originator id */
1871 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1872 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1873 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1876 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1878 if (peer
->sort
== BGP_PEER_EBGP
1879 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1880 if (from
!= bgp
->peer_self
&& !transparent
1881 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1882 PEER_FLAG_MED_UNCHANGED
))
1884 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1887 /* Since the nexthop attribute can vary per peer, it is not explicitly
1889 * in announce check, only certain flags and length (or number of
1891 * -- for IPv6/MP_REACH) are set here in order to guide the update
1893 * code in setting the nexthop(s) on a per peer basis in
1895 * Typically, the source nexthop in the attribute is preserved but in
1897 * scenarios where we know it will always be overwritten, we reset the
1898 * nexthop to "0" in an attempt to achieve better Update packing. An
1899 * example of this is when a prefix from each of 2 IBGP peers needs to
1901 * announced to an EBGP peer (and they have the same attributes barring
1905 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1907 #define NEXTHOP_IS_V6 \
1908 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1909 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1910 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1911 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1913 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1915 * the peer (group) is configured to receive link-local nexthop
1917 * and it is available in the prefix OR we're not reflecting the route,
1918 * link-local nexthop address is valid and
1919 * the peer (group) to whom we're going to announce is on a shared
1921 * and this is either a self-originated route or the peer is EBGP.
1922 * By checking if nexthop LL address is valid we are sure that
1923 * we do not announce LL address as `::`.
1925 if (NEXTHOP_IS_V6
) {
1926 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1927 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1928 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1929 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1931 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1932 && peer
->shared_network
1933 && (from
== bgp
->peer_self
1934 || peer
->sort
== BGP_PEER_EBGP
))) {
1935 attr
->mp_nexthop_len
=
1936 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1939 /* Clear off link-local nexthop in source, whenever it is not
1941 * ensure more prefixes share the same attribute for
1944 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1945 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1946 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1949 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1950 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1952 /* Route map & unsuppress-map apply. */
1953 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1954 struct bgp_path_info rmap_path
= {0};
1955 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1956 struct attr dummy_attr
= {0};
1958 /* Fill temp path_info */
1959 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
1962 /* don't confuse inbound and outbound setting */
1963 RESET_FLAG(attr
->rmap_change_flags
);
1966 * The route reflector is not allowed to modify the attributes
1967 * of the reflected IBGP routes unless explicitly allowed.
1969 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1970 && !CHECK_FLAG(bgp
->flags
,
1971 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1973 rmap_path
.attr
= &dummy_attr
;
1976 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1978 if (pi
->extra
&& pi
->extra
->suppress
)
1979 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1980 RMAP_BGP
, &rmap_path
);
1982 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1983 RMAP_BGP
, &rmap_path
);
1985 peer
->rmap_type
= 0;
1987 if (ret
== RMAP_DENYMATCH
) {
1988 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1989 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1990 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1992 bgp_attr_flush(attr
);
1997 /* RFC 8212 to prevent route leaks.
1998 * This specification intends to improve this situation by requiring the
1999 * explicit configuration of both BGP Import and Export Policies for any
2000 * External BGP (EBGP) session such as customers, peers, or
2001 * confederation boundaries for all enabled address families. Through
2002 * codification of the aforementioned requirement, operators will
2003 * benefit from consistent behavior across different BGP
2006 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2007 if (!bgp_outbound_policy_exists(peer
, filter
))
2010 /* draft-ietf-idr-deprecate-as-set-confed-set
2011 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2012 * Eventually, This document (if approved) updates RFC 4271
2013 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2014 * and obsoletes RFC 6472.
2016 if (peer
->bgp
->reject_as_sets
)
2017 if (aspath_check_as_sets(attr
->aspath
))
2020 /* Codification of AS 0 Processing */
2021 if (aspath_check_as_zero(attr
->aspath
))
2024 if (bgp_in_graceful_shutdown(bgp
)) {
2025 if (peer
->sort
== BGP_PEER_IBGP
2026 || peer
->sort
== BGP_PEER_CONFED
) {
2027 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2028 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2030 bgp_attr_add_gshut_community(attr
);
2034 /* After route-map has been applied, we check to see if the nexthop to
2035 * be carried in the attribute (that is used for the announcement) can
2036 * be cleared off or not. We do this in all cases where we would be
2037 * setting the nexthop to "ourselves". For IPv6, we only need to
2039 * the global nexthop here; the link-local nexthop would have been
2041 * already, and if not, it is required by the update formation code.
2042 * Also see earlier comments in this function.
2045 * If route-map has performed some operation on the nexthop or the peer
2046 * configuration says to pass it unchanged, we cannot reset the nexthop
2047 * here, so only attempt to do it if these aren't true. Note that the
2048 * route-map handler itself might have cleared the nexthop, if for
2050 * it is configured as 'peer-address'.
2052 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2053 piattr
->rmap_change_flags
)
2055 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2056 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2057 /* We can reset the nexthop, if setting (or forcing) it to
2059 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2060 PEER_FLAG_NEXTHOP_SELF
)
2061 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2062 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2064 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2065 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2066 subgroup_announce_reset_nhop(
2067 (peer_cap_enhe(peer
, afi
, safi
)
2073 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2074 /* Can also reset the nexthop if announcing to EBGP, but
2076 * no peer in the subgroup is on a shared subnet.
2077 * Note: 3rd party nexthop currently implemented for
2080 if ((p
->family
== AF_INET
) &&
2081 (!bgp_subgrp_multiaccess_check_v4(
2084 subgroup_announce_reset_nhop(
2085 (peer_cap_enhe(peer
, afi
, safi
)
2092 if ((p
->family
== AF_INET6
) &&
2093 (!bgp_subgrp_multiaccess_check_v6(
2094 piattr
->mp_nexthop_global
,
2096 subgroup_announce_reset_nhop(
2097 (peer_cap_enhe(peer
, afi
, safi
)
2106 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2108 * This flag is used for leaked vpn-vrf routes
2110 int family
= p
->family
;
2112 if (peer_cap_enhe(peer
, afi
, safi
))
2115 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2117 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2118 __func__
, family2str(family
));
2119 subgroup_announce_reset_nhop(family
, attr
);
2124 /* If IPv6/MP and nexthop does not have any override and happens
2126 * be a link-local address, reset it so that we don't pass along
2128 * source's link-local IPv6 address to recipients who may not be
2130 * the same interface.
2132 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2133 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2134 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2140 * When the next hop is set to ourselves, if all multipaths have
2141 * link-bandwidth announce the cumulative bandwidth as that makes
2142 * the most sense. However, don't modify if the link-bandwidth has
2143 * been explicitly set by user policy.
2146 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2147 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2148 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2149 attr
->ecommunity
= ecommunity_replace_linkbw(
2150 bgp
->as
, attr
->ecommunity
, cum_bw
);
2155 static int bgp_route_select_timer_expire(struct thread
*thread
)
2157 struct afi_safi_info
*info
;
2162 info
= THREAD_ARG(thread
);
2167 if (BGP_DEBUG(update
, UPDATE_OUT
))
2168 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2171 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2173 XFREE(MTYPE_TMP
, info
);
2175 /* Best path selection */
2176 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2179 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2180 struct bgp_maxpaths_cfg
*mpath_cfg
,
2181 struct bgp_path_info_pair
*result
, afi_t afi
,
2184 struct bgp_path_info
*new_select
;
2185 struct bgp_path_info
*old_select
;
2186 struct bgp_path_info
*pi
;
2187 struct bgp_path_info
*pi1
;
2188 struct bgp_path_info
*pi2
;
2189 struct bgp_path_info
*nextpi
= NULL
;
2190 int paths_eq
, do_mpath
, debug
;
2191 struct list mp_list
;
2192 char pfx_buf
[PREFIX2STR_BUFFER
];
2193 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2195 bgp_mp_list_init(&mp_list
);
2197 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2199 debug
= bgp_debug_bestpath(dest
);
2202 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2204 dest
->reason
= bgp_path_selection_none
;
2205 /* bgp deterministic-med */
2207 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2209 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2210 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2212 bgp_path_info_unset_flag(dest
, pi1
,
2213 BGP_PATH_DMED_SELECTED
);
2215 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2217 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2219 if (BGP_PATH_HOLDDOWN(pi1
))
2221 if (pi1
->peer
!= bgp
->peer_self
)
2222 if (pi1
->peer
->status
!= Established
)
2227 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2228 if (CHECK_FLAG(pi2
->flags
,
2229 BGP_PATH_DMED_CHECK
))
2231 if (BGP_PATH_HOLDDOWN(pi2
))
2233 if (pi2
->peer
!= bgp
->peer_self
2236 PEER_STATUS_NSF_WAIT
))
2237 if (pi2
->peer
->status
2241 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2243 && !aspath_cmp_left_confed(
2248 if (bgp_path_info_cmp(
2249 bgp
, pi2
, new_select
,
2250 &paths_eq
, mpath_cfg
, debug
,
2253 bgp_path_info_unset_flag(
2255 BGP_PATH_DMED_SELECTED
);
2259 bgp_path_info_set_flag(
2260 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2263 bgp_path_info_set_flag(dest
, new_select
,
2264 BGP_PATH_DMED_CHECK
);
2265 bgp_path_info_set_flag(dest
, new_select
,
2266 BGP_PATH_DMED_SELECTED
);
2269 bgp_path_info_path_with_addpath_rx_str(
2270 new_select
, path_buf
);
2271 zlog_debug("%s: %s is the bestpath from AS %u",
2273 aspath_get_first_as(
2274 new_select
->attr
->aspath
));
2279 /* Check old selected route and new selected route. */
2282 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2283 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2284 enum bgp_path_selection_reason reason
;
2286 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2289 if (BGP_PATH_HOLDDOWN(pi
)) {
2290 /* reap REMOVED routes, if needs be
2291 * selected route must stay for a while longer though
2293 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2294 && (pi
!= old_select
))
2295 bgp_path_info_reap(dest
, pi
);
2298 zlog_debug("%s: pi %p in holddown", __func__
,
2304 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2305 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2306 if (pi
->peer
->status
!= Established
) {
2310 "%s: pi %p non self peer %s not estab state",
2311 __func__
, pi
, pi
->peer
->host
);
2316 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2317 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2318 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2320 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2324 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2326 reason
= dest
->reason
;
2327 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2328 debug
, pfx_buf
, afi
, safi
,
2330 if (new_select
== NULL
&&
2331 reason
!= bgp_path_selection_none
)
2332 dest
->reason
= reason
;
2337 /* Now that we know which path is the bestpath see if any of the other
2339 * qualify as multipaths
2343 bgp_path_info_path_with_addpath_rx_str(new_select
,
2346 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2348 "%s: After path selection, newbest is %s oldbest was %s",
2350 old_select
? old_select
->peer
->host
: "NONE");
2353 if (do_mpath
&& new_select
) {
2354 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2355 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2358 bgp_path_info_path_with_addpath_rx_str(
2361 if (pi
== new_select
) {
2364 "%s: %s is the bestpath, add to the multipath list",
2366 bgp_mp_list_add(&mp_list
, pi
);
2370 if (BGP_PATH_HOLDDOWN(pi
))
2373 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2374 && !CHECK_FLAG(pi
->peer
->sflags
,
2375 PEER_STATUS_NSF_WAIT
))
2376 if (pi
->peer
->status
!= Established
)
2379 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2382 "%s: %s has the same nexthop as the bestpath, skip it",
2387 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2388 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2394 "%s: %s is equivalent to the bestpath, add to the multipath list",
2396 bgp_mp_list_add(&mp_list
, pi
);
2401 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2403 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2404 bgp_mp_list_clear(&mp_list
);
2406 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2408 result
->old
= old_select
;
2409 result
->new = new_select
;
2415 * A new route/change in bestpath of an existing route. Evaluate the path
2416 * for advertisement to the subgroup.
2418 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2419 struct bgp_path_info
*selected
,
2420 struct bgp_dest
*dest
,
2421 uint32_t addpath_tx_id
)
2423 const struct prefix
*p
;
2424 struct peer
*onlypeer
;
2429 p
= bgp_dest_get_prefix(dest
);
2430 afi
= SUBGRP_AFI(subgrp
);
2431 safi
= SUBGRP_SAFI(subgrp
);
2432 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2435 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2436 char buf_prefix
[PREFIX_STRLEN
];
2437 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2438 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2442 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2443 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2444 PEER_STATUS_ORF_WAIT_REFRESH
))
2447 memset(&attr
, 0, sizeof(struct attr
));
2448 /* It's initialized in bgp_announce_check() */
2450 /* Announcement to the subgroup. If the route is filtered withdraw it.
2453 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
))
2454 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
, selected
);
2456 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2460 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2462 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2467 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2468 * This is called at the end of route processing.
2470 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2472 struct bgp_path_info
*pi
;
2474 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2475 if (BGP_PATH_HOLDDOWN(pi
))
2477 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2478 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2483 * Has the route changed from the RIB's perspective? This is invoked only
2484 * if the route selection returns the same best route as earlier - to
2485 * determine if we need to update zebra or not.
2487 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2489 struct bgp_path_info
*mpinfo
;
2491 /* If this is multipath, check all selected paths for any nexthop
2492 * change or attribute change. Some attribute changes (e.g., community)
2493 * aren't of relevance to the RIB, but we'll update zebra to ensure
2494 * we handle the case of BGP nexthop change. This is the behavior
2495 * when the best path has an attribute change anyway.
2497 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2498 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2499 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2503 * If this is multipath, check all selected paths for any nexthop change
2505 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2506 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2507 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2508 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2512 /* Nothing has changed from the RIB's perspective. */
2516 struct bgp_process_queue
{
2518 STAILQ_HEAD(, bgp_dest
) pqueue
;
2519 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2521 unsigned int queued
;
2524 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2525 safi_t safi
, struct bgp_dest
*dest
,
2526 struct bgp_path_info
*new_select
,
2527 struct bgp_path_info
*old_select
)
2529 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2531 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2534 if (advertise_type5_routes(bgp
, afi
) && new_select
2535 && is_route_injectable_into_evpn(new_select
)) {
2537 /* apply the route-map */
2538 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2539 route_map_result_t ret
;
2540 struct bgp_path_info rmap_path
;
2541 struct bgp_path_info_extra rmap_path_extra
;
2542 struct attr dummy_attr
;
2544 dummy_attr
= *new_select
->attr
;
2546 /* Fill temp path_info */
2547 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2548 new_select
, new_select
->peer
,
2551 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2553 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2554 p
, RMAP_BGP
, &rmap_path
);
2556 if (ret
== RMAP_DENYMATCH
) {
2557 bgp_attr_flush(&dummy_attr
);
2558 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2561 bgp_evpn_advertise_type5_route(
2562 bgp
, p
, &dummy_attr
, afi
, safi
);
2564 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2567 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2568 && is_route_injectable_into_evpn(old_select
))
2569 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2573 * old_select = The old best path
2574 * new_select = the new best path
2576 * if (!old_select && new_select)
2577 * We are sending new information on.
2579 * if (old_select && new_select) {
2580 * if (new_select != old_select)
2581 * We have a new best path send a change
2583 * We've received a update with new attributes that needs
2587 * if (old_select && !new_select)
2588 * We have no eligible route that we can announce or the rn
2591 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2592 afi_t afi
, safi_t safi
)
2594 struct bgp_path_info
*new_select
;
2595 struct bgp_path_info
*old_select
;
2596 struct bgp_path_info_pair old_and_new
;
2599 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2601 debug
= bgp_debug_bestpath(dest
);
2604 "%s: bgp delete in progress, ignoring event, p=%pRN",
2608 /* Is it end of initial update? (after startup) */
2610 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2611 sizeof(bgp
->update_delay_zebra_resume_time
));
2613 bgp
->main_zebra_update_hold
= 0;
2614 FOREACH_AFI_SAFI (afi
, safi
) {
2615 if (bgp_fibupd_safi(safi
))
2616 bgp_zebra_announce_table(bgp
, afi
, safi
);
2618 bgp
->main_peers_update_hold
= 0;
2620 bgp_start_routeadv(bgp
);
2624 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2626 debug
= bgp_debug_bestpath(dest
);
2628 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__
, dest
,
2629 afi2str(afi
), safi2str(safi
));
2631 /* The best path calculation for the route is deferred if
2632 * BGP_NODE_SELECT_DEFER is set
2634 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2635 if (BGP_DEBUG(update
, UPDATE_OUT
))
2636 zlog_debug("SELECT_DEFER falg set for route %p", dest
);
2640 /* Best path selection. */
2641 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2643 old_select
= old_and_new
.old
;
2644 new_select
= old_and_new
.new;
2646 /* Do we need to allocate or free labels?
2647 * Right now, since we only deal with per-prefix labels, it is not
2648 * necessary to do this upon changes to best path. Exceptions:
2649 * - label index has changed -> recalculate resulting label
2650 * - path_info sub_type changed -> switch to/from implicit-null
2651 * - no valid label (due to removed static label binding) -> get new one
2653 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2656 || bgp_label_index_differs(new_select
, old_select
)
2657 || new_select
->sub_type
!= old_select
->sub_type
2658 || !bgp_is_valid_label(&dest
->local_label
)) {
2659 /* Enforced penultimate hop popping:
2660 * implicit-null for local routes, aggregate
2661 * and redistributed routes
2663 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2664 || new_select
->sub_type
2665 == BGP_ROUTE_AGGREGATE
2666 || new_select
->sub_type
2667 == BGP_ROUTE_REDISTRIBUTE
) {
2670 BGP_NODE_REGISTERED_FOR_LABEL
))
2671 bgp_unregister_for_label(dest
);
2672 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2673 &dest
->local_label
);
2674 bgp_set_valid_label(&dest
->local_label
);
2676 bgp_register_for_label(dest
,
2679 } else if (CHECK_FLAG(dest
->flags
,
2680 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2681 bgp_unregister_for_label(dest
);
2683 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2684 bgp_unregister_for_label(dest
);
2689 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
2690 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2691 old_select
, new_select
);
2693 /* If best route remains the same and this is not due to user-initiated
2694 * clear, see exactly what needs to be done.
2696 if (old_select
&& old_select
== new_select
2697 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2698 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2699 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2700 if (bgp_zebra_has_route_changed(old_select
)) {
2701 #ifdef ENABLE_BGP_VNC
2702 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2703 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2705 if (bgp_fibupd_safi(safi
)
2706 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2708 if (new_select
->type
== ZEBRA_ROUTE_BGP
2709 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2710 || new_select
->sub_type
2711 == BGP_ROUTE_IMPORTED
))
2713 bgp_zebra_announce(dest
, p
, old_select
,
2718 /* If there is a change of interest to peers, reannounce the
2720 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2721 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2722 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2723 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2725 /* unicast routes must also be annouced to
2726 * labeled-unicast update-groups */
2727 if (safi
== SAFI_UNICAST
)
2728 group_announce_route(bgp
, afi
,
2729 SAFI_LABELED_UNICAST
, dest
,
2732 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2733 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2736 /* advertise/withdraw type-5 routes */
2737 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2738 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2739 bgp_process_evpn_route_injection(
2740 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2742 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2743 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2744 bgp_zebra_clear_route_change_flags(dest
);
2745 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2749 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2751 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2753 /* bestpath has changed; bump version */
2754 if (old_select
|| new_select
) {
2755 bgp_bump_version(dest
);
2757 if (!bgp
->t_rmap_def_originate_eval
) {
2761 update_group_refresh_default_originate_route_map
,
2762 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2763 &bgp
->t_rmap_def_originate_eval
);
2768 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2771 zlog_debug("%s: setting SELECTED flag", __func__
);
2772 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2773 bgp_path_info_unset_flag(dest
, new_select
,
2774 BGP_PATH_ATTR_CHANGED
);
2775 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2776 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2779 #ifdef ENABLE_BGP_VNC
2780 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2781 if (old_select
!= new_select
) {
2783 vnc_import_bgp_exterior_del_route(bgp
, p
,
2785 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2788 vnc_import_bgp_exterior_add_route(bgp
, p
,
2790 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2796 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2798 /* unicast routes must also be annouced to labeled-unicast update-groups
2800 if (safi
== SAFI_UNICAST
)
2801 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2805 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2806 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2807 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2808 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2809 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2810 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2812 /* if this is an evpn imported type-5 prefix,
2813 * we need to withdraw the route first to clear
2814 * the nh neigh and the RMAC entry.
2817 is_route_parent_evpn(old_select
))
2818 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2820 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2822 /* Withdraw the route from the kernel. */
2823 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2824 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2825 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2826 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2828 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2832 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2835 /* Clear any route change flags. */
2836 bgp_zebra_clear_route_change_flags(dest
);
2838 /* Reap old select bgp_path_info, if it has been removed */
2839 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2840 bgp_path_info_reap(dest
, old_select
);
2842 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2846 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2847 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2849 struct bgp_dest
*dest
;
2851 struct afi_safi_info
*thread_info
;
2852 struct listnode
*node
= NULL
, *nnode
= NULL
;
2854 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2855 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2857 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2858 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2859 get_afi_safi_str(afi
, safi
, false),
2860 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2863 /* Process the route list */
2864 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2866 dest
= listgetdata(node
);
2868 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2869 dest
->rt_node
= NULL
;
2871 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2872 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2873 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2875 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2881 /* Send EOR message when all routes are processed */
2882 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2883 bgp_send_delayed_eor(bgp
);
2884 /* Send route processing complete message to RIB */
2885 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2886 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2890 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2892 thread_info
->afi
= afi
;
2893 thread_info
->safi
= safi
;
2894 thread_info
->bgp
= bgp
;
2896 /* If there are more routes to be processed, start the
2899 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2900 BGP_ROUTE_SELECT_DELAY
,
2901 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2905 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2907 struct bgp_process_queue
*pqnode
= data
;
2908 struct bgp
*bgp
= pqnode
->bgp
;
2909 struct bgp_table
*table
;
2910 struct bgp_dest
*dest
;
2913 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2914 bgp_process_main_one(bgp
, NULL
, 0, 0);
2915 /* should always have dedicated wq call */
2916 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2920 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2921 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
2922 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2923 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
2924 table
= bgp_dest_table(dest
);
2925 /* note, new DESTs may be added as part of processing */
2926 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
2928 bgp_dest_unlock_node(dest
);
2929 bgp_table_unlock(table
);
2935 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2937 struct bgp_process_queue
*pqnode
= data
;
2939 bgp_unlock(pqnode
->bgp
);
2941 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2944 void bgp_process_queue_init(void)
2946 if (!bm
->process_main_queue
)
2947 bm
->process_main_queue
=
2948 work_queue_new(bm
->master
, "process_main_queue");
2950 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2951 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2952 bm
->process_main_queue
->spec
.max_retries
= 0;
2953 bm
->process_main_queue
->spec
.hold
= 50;
2954 /* Use a higher yield value of 50ms for main queue processing */
2955 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2958 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2960 struct bgp_process_queue
*pqnode
;
2962 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2963 sizeof(struct bgp_process_queue
));
2965 /* unlocked in bgp_processq_del */
2966 pqnode
->bgp
= bgp_lock(bgp
);
2967 STAILQ_INIT(&pqnode
->pqueue
);
2972 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
2974 #define ARBITRARY_PROCESS_QLEN 10000
2975 struct work_queue
*wq
= bm
->process_main_queue
;
2976 struct bgp_process_queue
*pqnode
;
2977 int pqnode_reuse
= 0;
2979 /* already scheduled for processing? */
2980 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2983 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2986 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2987 if (BGP_DEBUG(update
, UPDATE_OUT
))
2988 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2996 /* Add route nodes to an existing work queue item until reaching the
2997 limit only if is from the same BGP view and it's not an EOIU marker
2999 if (work_queue_item_count(wq
)) {
3000 struct work_queue_item
*item
= work_queue_last_item(wq
);
3001 pqnode
= item
->data
;
3003 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3004 || pqnode
->bgp
!= bgp
3005 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3006 pqnode
= bgp_processq_alloc(bgp
);
3010 pqnode
= bgp_processq_alloc(bgp
);
3011 /* all unlocked in bgp_process_wq */
3012 bgp_table_lock(bgp_dest_table(dest
));
3014 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3015 bgp_dest_lock_node(dest
);
3017 /* can't be enqueued twice */
3018 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3019 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3023 work_queue_add(wq
, pqnode
);
3028 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3030 struct bgp_process_queue
*pqnode
;
3032 if (bm
->process_main_queue
== NULL
)
3035 pqnode
= bgp_processq_alloc(bgp
);
3037 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3038 work_queue_add(bm
->process_main_queue
, pqnode
);
3041 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3045 peer
= THREAD_ARG(thread
);
3046 peer
->t_pmax_restart
= NULL
;
3048 if (bgp_debug_neighbor_events(peer
))
3050 "%s Maximum-prefix restart timer expired, restore peering",
3053 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3054 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3059 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3063 bool filtered
= false;
3064 struct bgp_dest
*dest
;
3065 struct bgp_adj_in
*ain
;
3066 struct attr attr
= {};
3067 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3069 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3070 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3071 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3075 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3079 if (bgp_input_modifier(
3080 peer
, rn_p
, &attr
, afi
, safi
,
3081 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3089 bgp_attr_undup(&attr
, ain
->attr
);
3096 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3100 iana_safi_t pkt_safi
;
3101 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3102 PEER_FLAG_MAX_PREFIX_FORCE
))
3103 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3104 + peer
->pcount
[afi
][safi
]
3105 : peer
->pcount
[afi
][safi
];
3107 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3110 if (pcount
> peer
->pmax
[afi
][safi
]) {
3111 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3112 PEER_STATUS_PREFIX_LIMIT
)
3117 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3118 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3119 peer
->pmax
[afi
][safi
]);
3120 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3122 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3123 PEER_FLAG_MAX_PREFIX_WARNING
))
3126 /* Convert AFI, SAFI to values for packet. */
3127 pkt_afi
= afi_int2iana(afi
);
3128 pkt_safi
= safi_int2iana(safi
);
3132 ndata
[0] = (pkt_afi
>> 8);
3134 ndata
[2] = pkt_safi
;
3135 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3136 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3137 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3138 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3140 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3141 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3142 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3146 /* Dynamic peers will just close their connection. */
3147 if (peer_dynamic_neighbor(peer
))
3150 /* restart timer start */
3151 if (peer
->pmax_restart
[afi
][safi
]) {
3152 peer
->v_pmax_restart
=
3153 peer
->pmax_restart
[afi
][safi
] * 60;
3155 if (bgp_debug_neighbor_events(peer
))
3157 "%s Maximum-prefix restart timer started for %d secs",
3158 peer
->host
, peer
->v_pmax_restart
);
3160 BGP_TIMER_ON(peer
->t_pmax_restart
,
3161 bgp_maximum_prefix_restart_timer
,
3162 peer
->v_pmax_restart
);
3167 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3168 PEER_STATUS_PREFIX_LIMIT
);
3171 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3172 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3173 PEER_STATUS_PREFIX_THRESHOLD
)
3178 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3179 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3180 peer
->pmax
[afi
][safi
]);
3181 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3182 PEER_STATUS_PREFIX_THRESHOLD
);
3184 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3185 PEER_STATUS_PREFIX_THRESHOLD
);
3189 /* Unconditionally remove the route from the RIB, without taking
3190 * damping into consideration (eg, because the session went down)
3192 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3193 struct peer
*peer
, afi_t afi
, safi_t safi
)
3196 struct bgp
*bgp
= NULL
;
3197 bool delete_route
= false;
3199 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3202 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3203 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3205 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3208 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3209 delete_route
= true;
3210 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3211 delete_route
= true;
3213 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3214 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3215 bgp
= pi
->peer
->bgp
;
3217 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3218 list_delete_node(bgp
->gr_info
[afi
][safi
]
3221 dest
->rt_node
= NULL
;
3227 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3228 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3231 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3232 struct peer
*peer
, afi_t afi
, safi_t safi
,
3233 struct prefix_rd
*prd
)
3235 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3237 /* apply dampening, if result is suppressed, we'll be retaining
3238 * the bgp_path_info in the RIB for historical reference.
3240 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3241 && peer
->sort
== BGP_PEER_EBGP
)
3242 if ((bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0))
3243 == BGP_DAMP_SUPPRESSED
) {
3244 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3249 #ifdef ENABLE_BGP_VNC
3250 if (safi
== SAFI_MPLS_VPN
) {
3251 struct bgp_dest
*pdest
= NULL
;
3252 struct bgp_table
*table
= NULL
;
3254 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3255 (struct prefix
*)prd
);
3256 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3257 table
= bgp_dest_get_bgp_table_info(pdest
);
3259 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3260 peer
->bgp
, prd
, table
, p
, pi
);
3262 bgp_dest_unlock_node(pdest
);
3264 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3265 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3267 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3268 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3273 /* If this is an EVPN route, process for un-import. */
3274 if (safi
== SAFI_EVPN
)
3275 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3277 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3280 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3281 struct peer
*peer
, struct attr
*attr
,
3282 struct bgp_dest
*dest
)
3284 struct bgp_path_info
*new;
3286 /* Make new BGP info. */
3287 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3289 new->instance
= instance
;
3290 new->sub_type
= sub_type
;
3293 new->uptime
= bgp_clock();
3298 static void overlay_index_update(struct attr
*attr
,
3299 union gw_addr
*gw_ip
)
3303 if (gw_ip
== NULL
) {
3304 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3306 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3307 sizeof(union gw_addr
));
3311 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3312 union gw_addr
*gw_ip
)
3314 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3320 if (afi
!= AFI_L2VPN
)
3323 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3325 if (gw_ip
== NULL
) {
3326 memset(&temp
, 0, sizeof(temp
));
3327 path_gw_ip_remote
= &temp
.ip
;
3329 path_gw_ip_remote
= gw_ip
;
3331 return !!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3334 /* Check if received nexthop is valid or not. */
3335 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3336 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3337 struct bgp_dest
*dest
)
3340 bool is_bgp_static_route
=
3341 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3345 * Only validated for unicast and multicast currently.
3346 * Also valid for EVPN where the nexthop is an IP address.
3347 * If we are a bgp static route being checked then there is
3348 * no need to check to see if the nexthop is martian as
3349 * that it should be ok.
3351 if (is_bgp_static_route
||
3352 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3355 /* If NEXT_HOP is present, validate it. */
3356 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3357 if (attr
->nexthop
.s_addr
== INADDR_ANY
3358 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3359 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3363 /* If MP_NEXTHOP is present, validate it. */
3364 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3365 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3366 * it is not an IPv6 link-local address.
3368 * If we receive an UPDATE with nexthop length set to 32 bytes
3369 * we shouldn't discard an UPDATE if it's set to (::).
3370 * The link-local (2st) is validated along the code path later.
3372 if (attr
->mp_nexthop_len
) {
3373 switch (attr
->mp_nexthop_len
) {
3374 case BGP_ATTR_NHLEN_IPV4
:
3375 case BGP_ATTR_NHLEN_VPNV4
:
3376 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3378 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3379 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3383 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3384 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3385 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3386 &attr
->mp_nexthop_global
)
3387 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3388 || IN6_IS_ADDR_MULTICAST(
3389 &attr
->mp_nexthop_global
)
3390 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3393 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3394 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3395 || IN6_IS_ADDR_MULTICAST(
3396 &attr
->mp_nexthop_global
)
3397 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3410 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3411 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3412 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3413 uint32_t num_labels
, int soft_reconfig
,
3414 struct bgp_route_evpn
*evpn
)
3417 int aspath_loop_count
= 0;
3418 struct bgp_dest
*dest
;
3420 struct attr new_attr
;
3421 struct attr
*attr_new
;
3422 struct bgp_path_info
*pi
;
3423 struct bgp_path_info
*new;
3424 struct bgp_path_info_extra
*extra
;
3426 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3428 int do_loop_check
= 1;
3429 int has_valid_label
= 0;
3431 uint8_t pi_type
= 0;
3432 uint8_t pi_sub_type
= 0;
3434 #ifdef ENABLE_BGP_VNC
3435 int vnc_implicit_withdraw
= 0;
3439 memset(&new_attr
, 0, sizeof(struct attr
));
3440 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3441 new_attr
.label
= MPLS_INVALID_LABEL
;
3444 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3445 /* TODO: Check to see if we can get rid of "is_valid_label" */
3446 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3447 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3449 has_valid_label
= bgp_is_valid_label(label
);
3451 /* When peer's soft reconfiguration enabled. Record input packet in
3454 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3455 && peer
!= bgp
->peer_self
)
3456 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3458 /* Check previously received route. */
3459 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3460 if (pi
->peer
== peer
&& pi
->type
== type
3461 && pi
->sub_type
== sub_type
3462 && pi
->addpath_rx_id
== addpath_id
)
3465 /* AS path local-as loop check. */
3466 if (peer
->change_local_as
) {
3467 if (peer
->allowas_in
[afi
][safi
])
3468 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3469 else if (!CHECK_FLAG(peer
->flags
,
3470 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3471 aspath_loop_count
= 1;
3473 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3474 > aspath_loop_count
) {
3475 peer
->stat_pfx_aspath_loop
++;
3476 reason
= "as-path contains our own AS A;";
3481 /* If the peer is configured for "allowas-in origin" and the last ASN in
3483 * as-path is our ASN then we do not need to call aspath_loop_check
3485 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3486 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3489 /* AS path loop check. */
3490 if (do_loop_check
) {
3491 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3492 > peer
->allowas_in
[afi
][safi
]
3493 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3494 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3495 > peer
->allowas_in
[afi
][safi
])) {
3496 peer
->stat_pfx_aspath_loop
++;
3497 reason
= "as-path contains our own AS;";
3502 /* Route reflector originator ID check. */
3503 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3504 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3505 peer
->stat_pfx_originator_loop
++;
3506 reason
= "originator is us;";
3510 /* Route reflector cluster ID check. */
3511 if (bgp_cluster_filter(peer
, attr
)) {
3512 peer
->stat_pfx_cluster_loop
++;
3513 reason
= "reflected from the same cluster;";
3517 /* Apply incoming filter. */
3518 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3519 peer
->stat_pfx_filter
++;
3524 /* RFC 8212 to prevent route leaks.
3525 * This specification intends to improve this situation by requiring the
3526 * explicit configuration of both BGP Import and Export Policies for any
3527 * External BGP (EBGP) session such as customers, peers, or
3528 * confederation boundaries for all enabled address families. Through
3529 * codification of the aforementioned requirement, operators will
3530 * benefit from consistent behavior across different BGP
3533 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3534 if (!bgp_inbound_policy_exists(peer
,
3535 &peer
->filter
[afi
][safi
])) {
3536 reason
= "inbound policy missing";
3540 /* draft-ietf-idr-deprecate-as-set-confed-set
3541 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3542 * Eventually, This document (if approved) updates RFC 4271
3543 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3544 * and obsoletes RFC 6472.
3546 if (peer
->bgp
->reject_as_sets
)
3547 if (aspath_check_as_sets(attr
->aspath
)) {
3549 "as-path contains AS_SET or AS_CONFED_SET type;";
3555 /* Apply incoming route-map.
3556 * NB: new_attr may now contain newly allocated values from route-map
3558 * commands, so we need bgp_attr_flush in the error paths, until we
3560 * the attr (which takes over the memory references) */
3561 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3564 peer
->stat_pfx_filter
++;
3565 reason
= "route-map;";
3566 bgp_attr_flush(&new_attr
);
3570 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3571 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3572 /* remove from RIB previous entry */
3573 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3576 if (peer
->sort
== BGP_PEER_EBGP
) {
3578 /* If we receive the graceful-shutdown community from an eBGP
3579 * peer we must lower local-preference */
3580 if (new_attr
.community
3581 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3582 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3583 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3585 /* If graceful-shutdown is configured then add the GSHUT
3586 * community to all paths received from eBGP peers */
3587 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3588 bgp_attr_add_gshut_community(&new_attr
);
3593 pi_sub_type
= pi
->sub_type
;
3596 /* next hop check. */
3597 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3598 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3600 peer
->stat_pfx_nh_invalid
++;
3601 reason
= "martian or self next-hop;";
3602 bgp_attr_flush(&new_attr
);
3606 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3607 peer
->stat_pfx_nh_invalid
++;
3608 reason
= "self mac;";
3612 /* Update Overlay Index */
3613 if (afi
== AFI_L2VPN
) {
3614 overlay_index_update(&new_attr
,
3615 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3618 attr_new
= bgp_attr_intern(&new_attr
);
3620 /* If maximum prefix count is configured and current prefix
3623 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3626 /* If the update is implicit withdraw. */
3628 pi
->uptime
= bgp_clock();
3629 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3631 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3633 /* Same attribute comes in. */
3634 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3635 && attrhash_cmp(pi
->attr
, attr_new
)
3636 && (!has_valid_label
3637 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3638 num_labels
* sizeof(mpls_label_t
))
3640 && (overlay_index_equal(
3642 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3643 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3644 BGP_CONFIG_DAMPENING
)
3645 && peer
->sort
== BGP_PEER_EBGP
3646 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3647 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3648 bgp_debug_rdpfxpath2str(
3649 afi
, safi
, prd
, p
, label
,
3650 num_labels
, addpath_id
? 1 : 0,
3651 addpath_id
, pfx_buf
,
3653 zlog_debug("%s rcvd %s", peer
->host
,
3657 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3658 != BGP_DAMP_SUPPRESSED
) {
3659 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3661 bgp_process(bgp
, dest
, afi
, safi
);
3663 } else /* Duplicate - odd */
3665 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3666 if (!peer
->rcvd_attr_printed
) {
3668 "%s rcvd UPDATE w/ attr: %s",
3670 peer
->rcvd_attr_str
);
3671 peer
->rcvd_attr_printed
= 1;
3674 bgp_debug_rdpfxpath2str(
3675 afi
, safi
, prd
, p
, label
,
3676 num_labels
, addpath_id
? 1 : 0,
3677 addpath_id
, pfx_buf
,
3680 "%s rcvd %s...duplicate ignored",
3681 peer
->host
, pfx_buf
);
3684 /* graceful restart STALE flag unset. */
3685 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3686 bgp_path_info_unset_flag(
3687 dest
, pi
, BGP_PATH_STALE
);
3688 bgp_dest_set_defer_flag(dest
, false);
3689 bgp_process(bgp
, dest
, afi
, safi
);
3693 bgp_dest_unlock_node(dest
);
3694 bgp_attr_unintern(&attr_new
);
3699 /* Withdraw/Announce before we fully processed the withdraw */
3700 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3701 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3702 bgp_debug_rdpfxpath2str(
3703 afi
, safi
, prd
, p
, label
, num_labels
,
3704 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3707 "%s rcvd %s, flapped quicker than processing",
3708 peer
->host
, pfx_buf
);
3711 bgp_path_info_restore(dest
, pi
);
3714 /* Received Logging. */
3715 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3716 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3717 num_labels
, addpath_id
? 1 : 0,
3718 addpath_id
, pfx_buf
,
3720 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3723 /* graceful restart STALE flag unset. */
3724 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3725 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3726 bgp_dest_set_defer_flag(dest
, false);
3729 /* The attribute is changed. */
3730 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3732 /* implicit withdraw, decrement aggregate and pcount here.
3733 * only if update is accepted, they'll increment below.
3735 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3737 /* Update bgp route dampening information. */
3738 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3739 && peer
->sort
== BGP_PEER_EBGP
) {
3740 /* This is implicit withdraw so we should update
3743 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3744 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3746 #ifdef ENABLE_BGP_VNC
3747 if (safi
== SAFI_MPLS_VPN
) {
3748 struct bgp_dest
*pdest
= NULL
;
3749 struct bgp_table
*table
= NULL
;
3751 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3752 (struct prefix
*)prd
);
3753 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3754 table
= bgp_dest_get_bgp_table_info(pdest
);
3756 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3757 bgp
, prd
, table
, p
, pi
);
3759 bgp_dest_unlock_node(pdest
);
3761 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3762 && (safi
== SAFI_UNICAST
)) {
3763 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3765 * Implicit withdraw case.
3767 ++vnc_implicit_withdraw
;
3768 vnc_import_bgp_del_route(bgp
, p
, pi
);
3769 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3774 /* Special handling for EVPN update of an existing route. If the
3775 * extended community attribute has changed, we need to
3777 * the route using its existing extended community. It will be
3778 * subsequently processed for import with the new extended
3781 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3784 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3786 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3789 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3790 attr_new
->ecommunity
);
3792 if (bgp_debug_update(peer
, p
, NULL
, 1))
3794 "Change in EXT-COMM, existing %s new %s",
3796 pi
->attr
->ecommunity
),
3798 attr_new
->ecommunity
));
3799 if (safi
== SAFI_EVPN
)
3800 bgp_evpn_unimport_route(
3801 bgp
, afi
, safi
, p
, pi
);
3802 else /* SAFI_MPLS_VPN */
3803 vpn_leak_to_vrf_withdraw(bgp
,
3809 /* Update to new attribute. */
3810 bgp_attr_unintern(&pi
->attr
);
3811 pi
->attr
= attr_new
;
3813 /* Update MPLS label */
3814 if (has_valid_label
) {
3815 extra
= bgp_path_info_extra_get(pi
);
3816 if (extra
->label
!= label
) {
3817 memcpy(&extra
->label
, label
,
3818 num_labels
* sizeof(mpls_label_t
));
3819 extra
->num_labels
= num_labels
;
3821 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3822 bgp_set_valid_label(&extra
->label
[0]);
3825 /* Update SRv6 SID */
3826 if (attr
->srv6_l3vpn
) {
3827 extra
= bgp_path_info_extra_get(pi
);
3828 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3829 sid_copy(&extra
->sid
[0],
3830 &attr
->srv6_l3vpn
->sid
);
3831 extra
->num_sids
= 1;
3833 } else if (attr
->srv6_vpn
) {
3834 extra
= bgp_path_info_extra_get(pi
);
3835 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3836 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3837 extra
->num_sids
= 1;
3841 #ifdef ENABLE_BGP_VNC
3842 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3843 && (safi
== SAFI_UNICAST
)) {
3844 if (vnc_implicit_withdraw
) {
3846 * Add back the route with its new attributes
3848 * The route is still selected, until the route
3850 * queued by bgp_process actually runs. We have
3852 * update to the VNC side immediately to avoid
3854 * configuration changes (e.g., route-map
3856 * trigger re-importation of the entire RIB.
3858 vnc_import_bgp_add_route(bgp
, p
, pi
);
3859 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3864 /* Update bgp route dampening information. */
3865 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3866 && peer
->sort
== BGP_PEER_EBGP
) {
3867 /* Now we do normal update dampening. */
3868 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
3869 if (ret
== BGP_DAMP_SUPPRESSED
) {
3870 bgp_dest_unlock_node(dest
);
3875 /* Nexthop reachability check - for unicast and
3876 * labeled-unicast.. */
3877 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3878 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3879 || (safi
== SAFI_EVPN
&&
3880 bgp_evpn_is_prefix_nht_supported(p
))) {
3881 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3882 && peer
->ttl
== BGP_DEFAULT_TTL
3883 && !CHECK_FLAG(peer
->flags
,
3884 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3885 && !CHECK_FLAG(bgp
->flags
,
3886 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3891 struct bgp
*bgp_nexthop
= bgp
;
3893 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3894 bgp_nexthop
= pi
->extra
->bgp_orig
;
3896 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3898 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3899 pi
, NULL
, connected
)
3900 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3901 bgp_path_info_set_flag(dest
, pi
,
3904 if (BGP_DEBUG(nht
, NHT
)) {
3905 zlog_debug("%s(%pI4): NH unresolved",
3907 (in_addr_t
*)&attr_new
->nexthop
);
3909 bgp_path_info_unset_flag(dest
, pi
,
3913 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
3915 #ifdef ENABLE_BGP_VNC
3916 if (safi
== SAFI_MPLS_VPN
) {
3917 struct bgp_dest
*pdest
= NULL
;
3918 struct bgp_table
*table
= NULL
;
3920 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3921 (struct prefix
*)prd
);
3922 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3923 table
= bgp_dest_get_bgp_table_info(pdest
);
3925 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3926 bgp
, prd
, table
, p
, pi
);
3928 bgp_dest_unlock_node(pdest
);
3932 /* If this is an EVPN route and some attribute has changed,
3934 * route for import. If the extended community has changed, we
3936 * have done the un-import earlier and the import would result
3938 * route getting injected into appropriate L2 VNIs. If it is
3940 * some other attribute change, the import will result in
3942 * the attributes for the route in the VNI(s).
3944 if (safi
== SAFI_EVPN
&& !same_attr
&&
3945 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3946 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3948 /* Process change. */
3949 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3951 bgp_process(bgp
, dest
, afi
, safi
);
3952 bgp_dest_unlock_node(dest
);
3954 if (SAFI_UNICAST
== safi
3955 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3956 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3958 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3960 if ((SAFI_MPLS_VPN
== safi
)
3961 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3963 vpn_leak_to_vrf_update(bgp
, pi
);
3966 #ifdef ENABLE_BGP_VNC
3967 if (SAFI_MPLS_VPN
== safi
) {
3968 mpls_label_t label_decoded
= decode_label(label
);
3970 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3971 type
, sub_type
, &label_decoded
);
3973 if (SAFI_ENCAP
== safi
) {
3974 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3975 type
, sub_type
, NULL
);
3980 } // End of implicit withdraw
3982 /* Received Logging. */
3983 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3984 if (!peer
->rcvd_attr_printed
) {
3985 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3986 peer
->rcvd_attr_str
);
3987 peer
->rcvd_attr_printed
= 1;
3990 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3991 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3993 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3996 /* Make new BGP info. */
3997 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
3999 /* Update MPLS label */
4000 if (has_valid_label
) {
4001 extra
= bgp_path_info_extra_get(new);
4002 if (extra
->label
!= label
) {
4003 memcpy(&extra
->label
, label
,
4004 num_labels
* sizeof(mpls_label_t
));
4005 extra
->num_labels
= num_labels
;
4007 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4008 bgp_set_valid_label(&extra
->label
[0]);
4011 /* Update SRv6 SID */
4012 if (safi
== SAFI_MPLS_VPN
) {
4013 extra
= bgp_path_info_extra_get(new);
4014 if (attr
->srv6_l3vpn
) {
4015 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4016 extra
->num_sids
= 1;
4017 } else if (attr
->srv6_vpn
) {
4018 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4019 extra
->num_sids
= 1;
4023 /* Update Overlay Index */
4024 if (afi
== AFI_L2VPN
) {
4025 overlay_index_update(new->attr
,
4026 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4028 /* Nexthop reachability check. */
4029 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4030 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4031 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4032 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4033 && peer
->ttl
== BGP_DEFAULT_TTL
4034 && !CHECK_FLAG(peer
->flags
,
4035 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4036 && !CHECK_FLAG(bgp
->flags
,
4037 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4042 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4044 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
4046 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4047 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4049 if (BGP_DEBUG(nht
, NHT
)) {
4050 char buf1
[INET6_ADDRSTRLEN
];
4052 (const void *)&attr_new
->nexthop
,
4053 buf1
, INET6_ADDRSTRLEN
);
4054 zlog_debug("%s(%s): NH unresolved", __func__
,
4057 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4060 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4063 new->addpath_rx_id
= addpath_id
;
4065 /* Increment prefix */
4066 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4068 /* Register new BGP information. */
4069 bgp_path_info_add(dest
, new);
4071 /* route_node_get lock */
4072 bgp_dest_unlock_node(dest
);
4074 #ifdef ENABLE_BGP_VNC
4075 if (safi
== SAFI_MPLS_VPN
) {
4076 struct bgp_dest
*pdest
= NULL
;
4077 struct bgp_table
*table
= NULL
;
4079 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4080 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4081 table
= bgp_dest_get_bgp_table_info(pdest
);
4083 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4084 bgp
, prd
, table
, p
, new);
4086 bgp_dest_unlock_node(pdest
);
4090 /* If this is an EVPN route, process for import. */
4091 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4092 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4094 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4096 /* Process change. */
4097 bgp_process(bgp
, dest
, afi
, safi
);
4099 if (SAFI_UNICAST
== safi
4100 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4101 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4102 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4104 if ((SAFI_MPLS_VPN
== safi
)
4105 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4107 vpn_leak_to_vrf_update(bgp
, new);
4109 #ifdef ENABLE_BGP_VNC
4110 if (SAFI_MPLS_VPN
== safi
) {
4111 mpls_label_t label_decoded
= decode_label(label
);
4113 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4114 sub_type
, &label_decoded
);
4116 if (SAFI_ENCAP
== safi
) {
4117 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4124 /* This BGP update is filtered. Log the reason then update BGP
4127 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4129 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4130 if (!peer
->rcvd_attr_printed
) {
4131 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4132 peer
->rcvd_attr_str
);
4133 peer
->rcvd_attr_printed
= 1;
4136 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4137 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4139 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4140 peer
->host
, pfx_buf
, reason
);
4144 /* If this is an EVPN route, un-import it as it is now filtered.
4146 if (safi
== SAFI_EVPN
)
4147 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4149 if (SAFI_UNICAST
== safi
4150 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4151 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4153 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4155 if ((SAFI_MPLS_VPN
== safi
)
4156 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4158 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4161 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4164 bgp_dest_unlock_node(dest
);
4166 #ifdef ENABLE_BGP_VNC
4168 * Filtered update is treated as an implicit withdrawal (see
4170 * a few lines above)
4172 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4173 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4181 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4182 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4183 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4184 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4187 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4188 struct bgp_dest
*dest
;
4189 struct bgp_path_info
*pi
;
4191 #ifdef ENABLE_BGP_VNC
4192 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4193 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4201 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4203 /* If peer is soft reconfiguration enabled. Record input packet for
4204 * further calculation.
4206 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4207 * routes that are filtered. This tanks out Quagga RS pretty badly due
4209 * the iteration over all RS clients.
4210 * Since we need to remove the entry from adj_in anyway, do that first
4212 * if there was no entry, we don't need to do anything more.
4214 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4215 && peer
!= bgp
->peer_self
)
4216 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4217 peer
->stat_pfx_dup_withdraw
++;
4219 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4220 bgp_debug_rdpfxpath2str(
4221 afi
, safi
, prd
, p
, label
, num_labels
,
4222 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4225 "%s withdrawing route %s not in adj-in",
4226 peer
->host
, pfx_buf
);
4228 bgp_dest_unlock_node(dest
);
4232 /* Lookup withdrawn route. */
4233 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4234 if (pi
->peer
== peer
&& pi
->type
== type
4235 && pi
->sub_type
== sub_type
4236 && pi
->addpath_rx_id
== addpath_id
)
4240 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4241 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4242 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4244 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4248 /* Withdraw specified route from routing table. */
4249 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4250 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4251 if (SAFI_UNICAST
== safi
4252 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4253 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4254 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4256 if ((SAFI_MPLS_VPN
== safi
)
4257 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4259 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4261 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4262 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4263 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4265 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4268 /* Unlock bgp_node_get() lock. */
4269 bgp_dest_unlock_node(dest
);
4274 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4277 struct update_subgroup
*subgrp
;
4278 subgrp
= peer_subgroup(peer
, afi
, safi
);
4279 subgroup_default_originate(subgrp
, withdraw
);
4284 * bgp_stop_announce_route_timer
4286 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4288 if (!paf
->t_announce_route
)
4291 THREAD_TIMER_OFF(paf
->t_announce_route
);
4295 * bgp_announce_route_timer_expired
4297 * Callback that is invoked when the route announcement timer for a
4300 static int bgp_announce_route_timer_expired(struct thread
*t
)
4302 struct peer_af
*paf
;
4305 paf
= THREAD_ARG(t
);
4308 if (peer
->status
!= Established
)
4311 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4314 peer_af_announce_route(paf
, 1);
4319 * bgp_announce_route
4321 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4323 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4325 struct peer_af
*paf
;
4326 struct update_subgroup
*subgrp
;
4328 paf
= peer_af_find(peer
, afi
, safi
);
4331 subgrp
= PAF_SUBGRP(paf
);
4334 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4335 * or a refresh has already been triggered.
4337 if (!subgrp
|| paf
->t_announce_route
)
4341 * Start a timer to stagger/delay the announce. This serves
4342 * two purposes - announcement can potentially be combined for
4343 * multiple peers and the announcement doesn't happen in the
4346 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4347 (subgrp
->peer_count
== 1)
4348 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4349 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4350 &paf
->t_announce_route
);
4354 * Announce routes from all AF tables to a peer.
4356 * This should ONLY be called when there is a need to refresh the
4357 * routes to the peer based on a policy change for this peer alone
4358 * or a route refresh request received from the peer.
4359 * The operation will result in splitting the peer from its existing
4360 * subgroups and putting it in new subgroups.
4362 void bgp_announce_route_all(struct peer
*peer
)
4367 FOREACH_AFI_SAFI (afi
, safi
)
4368 bgp_announce_route(peer
, afi
, safi
);
4371 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4372 struct bgp_table
*table
,
4373 struct prefix_rd
*prd
)
4376 struct bgp_dest
*dest
;
4377 struct bgp_adj_in
*ain
;
4380 table
= peer
->bgp
->rib
[afi
][safi
];
4382 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4383 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4384 if (ain
->peer
!= peer
)
4387 struct bgp_path_info
*pi
;
4388 uint32_t num_labels
= 0;
4389 mpls_label_t
*label_pnt
= NULL
;
4390 struct bgp_route_evpn evpn
;
4392 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4394 if (pi
->peer
== peer
)
4397 if (pi
&& pi
->extra
)
4398 num_labels
= pi
->extra
->num_labels
;
4400 label_pnt
= &pi
->extra
->label
[0];
4402 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4405 memset(&evpn
, 0, sizeof(evpn
));
4407 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4408 ain
->addpath_rx_id
, ain
->attr
, afi
,
4409 safi
, ZEBRA_ROUTE_BGP
,
4410 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4411 num_labels
, 1, &evpn
);
4414 bgp_dest_unlock_node(dest
);
4420 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4422 struct bgp_dest
*dest
;
4423 struct bgp_table
*table
;
4425 if (peer
->status
!= Established
)
4428 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4429 && (safi
!= SAFI_EVPN
))
4430 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4432 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4433 dest
= bgp_route_next(dest
)) {
4434 table
= bgp_dest_get_bgp_table_info(dest
);
4439 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4440 struct prefix_rd prd
;
4442 prd
.family
= AF_UNSPEC
;
4444 memcpy(&prd
.val
, p
->u
.val
, 8);
4446 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4451 struct bgp_clear_node_queue
{
4452 struct bgp_dest
*dest
;
4455 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4457 struct bgp_clear_node_queue
*cnq
= data
;
4458 struct bgp_dest
*dest
= cnq
->dest
;
4459 struct peer
*peer
= wq
->spec
.data
;
4460 struct bgp_path_info
*pi
;
4462 afi_t afi
= bgp_dest_table(dest
)->afi
;
4463 safi_t safi
= bgp_dest_table(dest
)->safi
;
4465 assert(dest
&& peer
);
4468 /* It is possible that we have multiple paths for a prefix from a peer
4469 * if that peer is using AddPath.
4471 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4472 if (pi
->peer
!= peer
)
4475 /* graceful restart STALE flag set. */
4476 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4477 && peer
->nsf
[afi
][safi
]
4478 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4479 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4480 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4482 /* If this is an EVPN route, process for
4484 if (safi
== SAFI_EVPN
)
4485 bgp_evpn_unimport_route(
4487 bgp_dest_get_prefix(dest
), pi
);
4488 /* Handle withdraw for VRF route-leaking and L3VPN */
4489 if (SAFI_UNICAST
== safi
4490 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4491 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4492 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4495 if (SAFI_MPLS_VPN
== safi
&&
4496 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4497 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4500 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4506 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4508 struct bgp_clear_node_queue
*cnq
= data
;
4509 struct bgp_dest
*dest
= cnq
->dest
;
4510 struct bgp_table
*table
= bgp_dest_table(dest
);
4512 bgp_dest_unlock_node(dest
);
4513 bgp_table_unlock(table
);
4514 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4517 static void bgp_clear_node_complete(struct work_queue
*wq
)
4519 struct peer
*peer
= wq
->spec
.data
;
4521 /* Tickle FSM to start moving again */
4522 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4524 peer_unlock(peer
); /* bgp_clear_route */
4527 static void bgp_clear_node_queue_init(struct peer
*peer
)
4529 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4531 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4532 #undef CLEAR_QUEUE_NAME_LEN
4534 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4535 peer
->clear_node_queue
->spec
.hold
= 10;
4536 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4537 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4538 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4539 peer
->clear_node_queue
->spec
.max_retries
= 0;
4541 /* we only 'lock' this peer reference when the queue is actually active
4543 peer
->clear_node_queue
->spec
.data
= peer
;
4546 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4547 struct bgp_table
*table
)
4549 struct bgp_dest
*dest
;
4550 int force
= bm
->process_main_queue
? 0 : 1;
4553 table
= peer
->bgp
->rib
[afi
][safi
];
4555 /* If still no table => afi/safi isn't configured at all or smth. */
4559 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4560 struct bgp_path_info
*pi
, *next
;
4561 struct bgp_adj_in
*ain
;
4562 struct bgp_adj_in
*ain_next
;
4564 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4565 * queued for every clearing peer, regardless of whether it is
4566 * relevant to the peer at hand.
4568 * Overview: There are 3 different indices which need to be
4569 * scrubbed, potentially, when a peer is removed:
4571 * 1 peer's routes visible via the RIB (ie accepted routes)
4572 * 2 peer's routes visible by the (optional) peer's adj-in index
4573 * 3 other routes visible by the peer's adj-out index
4575 * 3 there is no hurry in scrubbing, once the struct peer is
4576 * removed from bgp->peer, we could just GC such deleted peer's
4577 * adj-outs at our leisure.
4579 * 1 and 2 must be 'scrubbed' in some way, at least made
4580 * invisible via RIB index before peer session is allowed to be
4581 * brought back up. So one needs to know when such a 'search' is
4586 * - there'd be a single global queue or a single RIB walker
4587 * - rather than tracking which route_nodes still need to be
4588 * examined on a peer basis, we'd track which peers still
4591 * Given that our per-peer prefix-counts now should be reliable,
4592 * this may actually be achievable. It doesn't seem to be a huge
4593 * problem at this time,
4595 * It is possible that we have multiple paths for a prefix from
4597 * if that peer is using AddPath.
4601 ain_next
= ain
->next
;
4603 if (ain
->peer
== peer
) {
4604 bgp_adj_in_remove(dest
, ain
);
4605 bgp_dest_unlock_node(dest
);
4611 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4613 if (pi
->peer
!= peer
)
4617 bgp_path_info_reap(dest
, pi
);
4619 struct bgp_clear_node_queue
*cnq
;
4621 /* both unlocked in bgp_clear_node_queue_del */
4622 bgp_table_lock(bgp_dest_table(dest
));
4623 bgp_dest_lock_node(dest
);
4625 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4626 sizeof(struct bgp_clear_node_queue
));
4628 work_queue_add(peer
->clear_node_queue
, cnq
);
4636 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4638 struct bgp_dest
*dest
;
4639 struct bgp_table
*table
;
4641 if (peer
->clear_node_queue
== NULL
)
4642 bgp_clear_node_queue_init(peer
);
4644 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4645 * Idle until it receives a Clearing_Completed event. This protects
4646 * against peers which flap faster than we can we clear, which could
4649 * a) race with routes from the new session being installed before
4650 * clear_route_node visits the node (to delete the route of that
4652 * b) resource exhaustion, clear_route_node likely leads to an entry
4653 * on the process_main queue. Fast-flapping could cause that queue
4657 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4658 * the unlock will happen upon work-queue completion; other wise, the
4659 * unlock happens at the end of this function.
4661 if (!peer
->clear_node_queue
->thread
)
4664 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4665 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4667 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4668 dest
= bgp_route_next(dest
)) {
4669 table
= bgp_dest_get_bgp_table_info(dest
);
4673 bgp_clear_route_table(peer
, afi
, safi
, table
);
4676 /* unlock if no nodes got added to the clear-node-queue. */
4677 if (!peer
->clear_node_queue
->thread
)
4681 void bgp_clear_route_all(struct peer
*peer
)
4686 FOREACH_AFI_SAFI (afi
, safi
)
4687 bgp_clear_route(peer
, afi
, safi
);
4689 #ifdef ENABLE_BGP_VNC
4690 rfapiProcessPeerDown(peer
);
4694 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4696 struct bgp_table
*table
;
4697 struct bgp_dest
*dest
;
4698 struct bgp_adj_in
*ain
;
4699 struct bgp_adj_in
*ain_next
;
4701 table
= peer
->bgp
->rib
[afi
][safi
];
4703 /* It is possible that we have multiple paths for a prefix from a peer
4704 * if that peer is using AddPath.
4706 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4710 ain_next
= ain
->next
;
4712 if (ain
->peer
== peer
) {
4713 bgp_adj_in_remove(dest
, ain
);
4714 bgp_dest_unlock_node(dest
);
4722 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4724 struct bgp_dest
*dest
;
4725 struct bgp_path_info
*pi
;
4726 struct bgp_table
*table
;
4728 if (safi
== SAFI_MPLS_VPN
) {
4729 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4730 dest
= bgp_route_next(dest
)) {
4731 struct bgp_dest
*rm
;
4733 /* look for neighbor in tables */
4734 table
= bgp_dest_get_bgp_table_info(dest
);
4738 for (rm
= bgp_table_top(table
); rm
;
4739 rm
= bgp_route_next(rm
))
4740 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4742 if (pi
->peer
!= peer
)
4744 if (!CHECK_FLAG(pi
->flags
,
4748 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4753 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4754 dest
= bgp_route_next(dest
))
4755 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4757 if (pi
->peer
!= peer
)
4759 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4761 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4767 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4769 if (peer
->sort
== BGP_PEER_IBGP
)
4772 if (peer
->sort
== BGP_PEER_EBGP
4773 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4774 || FILTER_LIST_OUT_NAME(filter
)
4775 || DISTRIBUTE_OUT_NAME(filter
)))
4780 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4782 if (peer
->sort
== BGP_PEER_IBGP
)
4785 if (peer
->sort
== BGP_PEER_EBGP
4786 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4787 || FILTER_LIST_IN_NAME(filter
)
4788 || DISTRIBUTE_IN_NAME(filter
)))
4793 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4796 struct bgp_dest
*dest
;
4797 struct bgp_path_info
*pi
;
4798 struct bgp_path_info
*next
;
4800 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4801 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4802 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4806 /* Unimport EVPN routes from VRFs */
4807 if (safi
== SAFI_EVPN
)
4808 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4811 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4812 && pi
->type
== ZEBRA_ROUTE_BGP
4813 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4814 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4815 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4817 if (bgp_fibupd_safi(safi
))
4818 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4821 bgp_path_info_reap(dest
, pi
);
4825 /* Delete all kernel routes. */
4826 void bgp_cleanup_routes(struct bgp
*bgp
)
4829 struct bgp_dest
*dest
;
4830 struct bgp_table
*table
;
4832 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4833 if (afi
== AFI_L2VPN
)
4835 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4838 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4840 if (afi
!= AFI_L2VPN
) {
4842 safi
= SAFI_MPLS_VPN
;
4843 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4844 dest
= bgp_route_next(dest
)) {
4845 table
= bgp_dest_get_bgp_table_info(dest
);
4846 if (table
!= NULL
) {
4847 bgp_cleanup_table(bgp
, table
, safi
);
4848 bgp_table_finish(&table
);
4849 bgp_dest_set_bgp_table_info(dest
, NULL
);
4850 bgp_dest_unlock_node(dest
);
4854 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
4855 dest
= bgp_route_next(dest
)) {
4856 table
= bgp_dest_get_bgp_table_info(dest
);
4857 if (table
!= NULL
) {
4858 bgp_cleanup_table(bgp
, table
, safi
);
4859 bgp_table_finish(&table
);
4860 bgp_dest_set_bgp_table_info(dest
, NULL
);
4861 bgp_dest_unlock_node(dest
);
4866 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
4867 dest
= bgp_route_next(dest
)) {
4868 table
= bgp_dest_get_bgp_table_info(dest
);
4869 if (table
!= NULL
) {
4870 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4871 bgp_table_finish(&table
);
4872 bgp_dest_set_bgp_table_info(dest
, NULL
);
4873 bgp_dest_unlock_node(dest
);
4878 void bgp_reset(void)
4881 bgp_zclient_reset();
4882 access_list_reset();
4883 prefix_list_reset();
4886 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4888 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4889 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4890 PEER_CAP_ADDPATH_AF_TX_RCV
));
4893 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4895 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4896 struct bgp_nlri
*packet
)
4905 int addpath_encoded
;
4906 uint32_t addpath_id
;
4909 lim
= pnt
+ packet
->length
;
4911 safi
= packet
->safi
;
4913 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4915 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4916 syntactic validity. If the field is syntactically incorrect,
4917 then the Error Subcode is set to Invalid Network Field. */
4918 for (; pnt
< lim
; pnt
+= psize
) {
4919 /* Clear prefix structure. */
4920 memset(&p
, 0, sizeof(struct prefix
));
4922 if (addpath_encoded
) {
4924 /* When packet overflow occurs return immediately. */
4925 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4926 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4928 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4929 addpath_id
= ntohl(addpath_id
);
4930 pnt
+= BGP_ADDPATH_ID_LEN
;
4933 /* Fetch prefix length. */
4934 p
.prefixlen
= *pnt
++;
4935 /* afi/safi validity already verified by caller,
4936 * bgp_update_receive */
4937 p
.family
= afi2family(afi
);
4939 /* Prefix length check. */
4940 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4943 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4944 peer
->host
, p
.prefixlen
, packet
->afi
);
4945 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4948 /* Packet size overflow check. */
4949 psize
= PSIZE(p
.prefixlen
);
4951 /* When packet overflow occur return immediately. */
4952 if (pnt
+ psize
> lim
) {
4955 "%s [Error] Update packet error (prefix length %d overflows packet)",
4956 peer
->host
, p
.prefixlen
);
4957 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4960 /* Defensive coding, double-check the psize fits in a struct
4962 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4965 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4966 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4967 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4970 /* Fetch prefix from NLRI packet. */
4971 memcpy(p
.u
.val
, pnt
, psize
);
4973 /* Check address. */
4974 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4975 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4976 /* From RFC4271 Section 6.3:
4978 * If a prefix in the NLRI field is semantically
4980 * (e.g., an unexpected multicast IP address),
4982 * be logged locally, and the prefix SHOULD be
4987 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4988 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4993 /* Check address. */
4994 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4995 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5000 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5002 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5007 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5012 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5014 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5021 /* Normal process. */
5023 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5024 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5025 NULL
, NULL
, 0, 0, NULL
);
5027 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5028 safi
, ZEBRA_ROUTE_BGP
,
5029 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5032 /* Do not send BGP notification twice when maximum-prefix count
5034 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5035 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5037 /* Address family configuration mismatch. */
5039 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5042 /* Packet length consistency check. */
5046 "%s [Error] Update packet error (prefix length mismatch with total length)",
5048 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5051 return BGP_NLRI_PARSE_OK
;
5054 static struct bgp_static
*bgp_static_new(void)
5056 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5059 static void bgp_static_free(struct bgp_static
*bgp_static
)
5061 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5062 route_map_counter_decrement(bgp_static
->rmap
.map
);
5064 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5065 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5068 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5069 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5071 struct bgp_dest
*dest
;
5072 struct bgp_path_info
*pi
;
5073 struct bgp_path_info
*new;
5074 struct bgp_path_info rmap_path
;
5076 struct attr
*attr_new
;
5077 route_map_result_t ret
;
5078 #ifdef ENABLE_BGP_VNC
5079 int vnc_implicit_withdraw
= 0;
5084 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5086 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5088 attr
.nexthop
= bgp_static
->igpnexthop
;
5089 attr
.med
= bgp_static
->igpmetric
;
5090 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5092 if (bgp_static
->atomic
)
5093 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5095 /* Store label index, if required. */
5096 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5097 attr
.label_index
= bgp_static
->label_index
;
5098 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5101 /* Apply route-map. */
5102 if (bgp_static
->rmap
.name
) {
5103 struct attr attr_tmp
= attr
;
5105 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5106 rmap_path
.peer
= bgp
->peer_self
;
5107 rmap_path
.attr
= &attr_tmp
;
5109 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5111 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5114 bgp
->peer_self
->rmap_type
= 0;
5116 if (ret
== RMAP_DENYMATCH
) {
5117 /* Free uninterned attribute. */
5118 bgp_attr_flush(&attr_tmp
);
5120 /* Unintern original. */
5121 aspath_unintern(&attr
.aspath
);
5122 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5126 if (bgp_in_graceful_shutdown(bgp
))
5127 bgp_attr_add_gshut_community(&attr_tmp
);
5129 attr_new
= bgp_attr_intern(&attr_tmp
);
5132 if (bgp_in_graceful_shutdown(bgp
))
5133 bgp_attr_add_gshut_community(&attr
);
5135 attr_new
= bgp_attr_intern(&attr
);
5138 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5139 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5140 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5144 if (attrhash_cmp(pi
->attr
, attr_new
)
5145 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5146 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5147 bgp_dest_unlock_node(dest
);
5148 bgp_attr_unintern(&attr_new
);
5149 aspath_unintern(&attr
.aspath
);
5152 /* The attribute is changed. */
5153 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5155 /* Rewrite BGP route information. */
5156 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5157 bgp_path_info_restore(dest
, pi
);
5159 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5160 #ifdef ENABLE_BGP_VNC
5161 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5162 && (safi
== SAFI_UNICAST
)) {
5163 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5165 * Implicit withdraw case.
5166 * We have to do this before pi is
5169 ++vnc_implicit_withdraw
;
5170 vnc_import_bgp_del_route(bgp
, p
, pi
);
5171 vnc_import_bgp_exterior_del_route(
5176 bgp_attr_unintern(&pi
->attr
);
5177 pi
->attr
= attr_new
;
5178 pi
->uptime
= bgp_clock();
5179 #ifdef ENABLE_BGP_VNC
5180 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5181 && (safi
== SAFI_UNICAST
)) {
5182 if (vnc_implicit_withdraw
) {
5183 vnc_import_bgp_add_route(bgp
, p
, pi
);
5184 vnc_import_bgp_exterior_add_route(
5190 /* Nexthop reachability check. */
5191 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5192 && (safi
== SAFI_UNICAST
5193 || safi
== SAFI_LABELED_UNICAST
)) {
5195 struct bgp
*bgp_nexthop
= bgp
;
5197 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5198 bgp_nexthop
= pi
->extra
->bgp_orig
;
5200 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5202 bgp_path_info_set_flag(dest
, pi
,
5205 if (BGP_DEBUG(nht
, NHT
)) {
5206 char buf1
[INET6_ADDRSTRLEN
];
5207 inet_ntop(p
->family
,
5211 "%s(%s): Route not in table, not advertising",
5214 bgp_path_info_unset_flag(
5215 dest
, pi
, BGP_PATH_VALID
);
5218 /* Delete the NHT structure if any, if we're
5220 * enabling/disabling import check. We
5221 * deregister the route
5222 * from NHT to avoid overloading NHT and the
5223 * process interaction
5225 bgp_unlink_nexthop(pi
);
5226 bgp_path_info_set_flag(dest
, pi
,
5229 /* Process change. */
5230 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5231 bgp_process(bgp
, dest
, afi
, safi
);
5233 if (SAFI_UNICAST
== safi
5234 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5236 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5237 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5241 bgp_dest_unlock_node(dest
);
5242 aspath_unintern(&attr
.aspath
);
5247 /* Make new BGP info. */
5248 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5250 /* Nexthop reachability check. */
5251 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5252 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5253 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5254 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5256 if (BGP_DEBUG(nht
, NHT
)) {
5257 char buf1
[INET6_ADDRSTRLEN
];
5258 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5261 "%s(%s): Route not in table, not advertising",
5264 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5267 /* Delete the NHT structure if any, if we're toggling between
5268 * enabling/disabling import check. We deregister the route
5269 * from NHT to avoid overloading NHT and the process interaction
5271 bgp_unlink_nexthop(new);
5273 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5276 /* Aggregate address increment. */
5277 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5279 /* Register new BGP information. */
5280 bgp_path_info_add(dest
, new);
5282 /* route_node_get lock */
5283 bgp_dest_unlock_node(dest
);
5285 /* Process change. */
5286 bgp_process(bgp
, dest
, afi
, safi
);
5288 if (SAFI_UNICAST
== safi
5289 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5290 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5291 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5294 /* Unintern original. */
5295 aspath_unintern(&attr
.aspath
);
5298 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5301 struct bgp_dest
*dest
;
5302 struct bgp_path_info
*pi
;
5304 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5306 /* Check selected route and self inserted route. */
5307 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5308 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5309 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5312 /* Withdraw static BGP route from routing table. */
5314 if (SAFI_UNICAST
== safi
5315 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5316 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5317 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5319 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5320 bgp_unlink_nexthop(pi
);
5321 bgp_path_info_delete(dest
, pi
);
5322 bgp_process(bgp
, dest
, afi
, safi
);
5325 /* Unlock bgp_node_lookup. */
5326 bgp_dest_unlock_node(dest
);
5330 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5332 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5333 afi_t afi
, safi_t safi
,
5334 struct prefix_rd
*prd
)
5336 struct bgp_dest
*dest
;
5337 struct bgp_path_info
*pi
;
5339 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5341 /* Check selected route and self inserted route. */
5342 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5343 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5344 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5347 /* Withdraw static BGP route from routing table. */
5349 #ifdef ENABLE_BGP_VNC
5350 rfapiProcessWithdraw(
5351 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5352 1); /* Kill, since it is an administrative change */
5354 if (SAFI_MPLS_VPN
== safi
5355 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5356 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5358 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5359 bgp_path_info_delete(dest
, pi
);
5360 bgp_process(bgp
, dest
, afi
, safi
);
5363 /* Unlock bgp_node_lookup. */
5364 bgp_dest_unlock_node(dest
);
5367 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5368 struct bgp_static
*bgp_static
, afi_t afi
,
5371 struct bgp_dest
*dest
;
5372 struct bgp_path_info
*new;
5373 struct attr
*attr_new
;
5374 struct attr attr
= {0};
5375 struct bgp_path_info
*pi
;
5376 #ifdef ENABLE_BGP_VNC
5377 mpls_label_t label
= 0;
5379 uint32_t num_labels
= 0;
5384 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5386 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5389 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5391 attr
.nexthop
= bgp_static
->igpnexthop
;
5392 attr
.med
= bgp_static
->igpmetric
;
5393 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5395 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5396 || (safi
== SAFI_ENCAP
)) {
5397 if (afi
== AFI_IP
) {
5398 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5399 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5402 if (afi
== AFI_L2VPN
) {
5403 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5405 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5406 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5407 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5408 sizeof(struct in6_addr
));
5409 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5410 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5411 struct bgp_encap_type_vxlan bet
;
5412 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5413 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5414 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5416 if (bgp_static
->router_mac
) {
5417 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5420 /* Apply route-map. */
5421 if (bgp_static
->rmap
.name
) {
5422 struct attr attr_tmp
= attr
;
5423 struct bgp_path_info rmap_path
;
5424 route_map_result_t ret
;
5426 rmap_path
.peer
= bgp
->peer_self
;
5427 rmap_path
.attr
= &attr_tmp
;
5429 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5431 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5434 bgp
->peer_self
->rmap_type
= 0;
5436 if (ret
== RMAP_DENYMATCH
) {
5437 /* Free uninterned attribute. */
5438 bgp_attr_flush(&attr_tmp
);
5440 /* Unintern original. */
5441 aspath_unintern(&attr
.aspath
);
5442 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5447 attr_new
= bgp_attr_intern(&attr_tmp
);
5449 attr_new
= bgp_attr_intern(&attr
);
5452 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5453 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5454 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5458 memset(&add
, 0, sizeof(union gw_addr
));
5459 if (attrhash_cmp(pi
->attr
, attr_new
)
5460 && overlay_index_equal(afi
, pi
, &add
)
5461 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5462 bgp_dest_unlock_node(dest
);
5463 bgp_attr_unintern(&attr_new
);
5464 aspath_unintern(&attr
.aspath
);
5467 /* The attribute is changed. */
5468 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5470 /* Rewrite BGP route information. */
5471 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5472 bgp_path_info_restore(dest
, pi
);
5474 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5475 bgp_attr_unintern(&pi
->attr
);
5476 pi
->attr
= attr_new
;
5477 pi
->uptime
= bgp_clock();
5478 #ifdef ENABLE_BGP_VNC
5480 label
= decode_label(&pi
->extra
->label
[0]);
5483 /* Process change. */
5484 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5485 bgp_process(bgp
, dest
, afi
, safi
);
5487 if (SAFI_MPLS_VPN
== safi
5488 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5489 vpn_leak_to_vrf_update(bgp
, pi
);
5491 #ifdef ENABLE_BGP_VNC
5492 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5493 pi
->attr
, afi
, safi
, pi
->type
,
5494 pi
->sub_type
, &label
);
5496 bgp_dest_unlock_node(dest
);
5497 aspath_unintern(&attr
.aspath
);
5503 /* Make new BGP info. */
5504 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5506 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5507 new->extra
= bgp_path_info_extra_new();
5509 new->extra
->label
[0] = bgp_static
->label
;
5510 new->extra
->num_labels
= num_labels
;
5512 #ifdef ENABLE_BGP_VNC
5513 label
= decode_label(&bgp_static
->label
);
5516 /* Aggregate address increment. */
5517 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5519 /* Register new BGP information. */
5520 bgp_path_info_add(dest
, new);
5521 /* route_node_get lock */
5522 bgp_dest_unlock_node(dest
);
5524 /* Process change. */
5525 bgp_process(bgp
, dest
, afi
, safi
);
5527 if (SAFI_MPLS_VPN
== safi
5528 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5529 vpn_leak_to_vrf_update(bgp
, new);
5531 #ifdef ENABLE_BGP_VNC
5532 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5533 safi
, new->type
, new->sub_type
, &label
);
5536 /* Unintern original. */
5537 aspath_unintern(&attr
.aspath
);
5540 /* Configure static BGP network. When user don't run zebra, static
5541 route should be installed as valid. */
5542 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5543 const char *ip_str
, afi_t afi
, safi_t safi
,
5544 const char *rmap
, int backdoor
, uint32_t label_index
)
5546 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5549 struct bgp_static
*bgp_static
;
5550 struct bgp_dest
*dest
;
5551 uint8_t need_update
= 0;
5553 /* Convert IP prefix string to struct prefix. */
5554 ret
= str2prefix(ip_str
, &p
);
5556 vty_out(vty
, "%% Malformed prefix\n");
5557 return CMD_WARNING_CONFIG_FAILED
;
5559 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5560 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5561 return CMD_WARNING_CONFIG_FAILED
;
5568 /* Set BGP static route configuration. */
5569 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5572 vty_out(vty
, "%% Can't find static route specified\n");
5573 return CMD_WARNING_CONFIG_FAILED
;
5576 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5578 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5579 && (label_index
!= bgp_static
->label_index
)) {
5581 "%% label-index doesn't match static route\n");
5582 return CMD_WARNING_CONFIG_FAILED
;
5585 if ((rmap
&& bgp_static
->rmap
.name
)
5586 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5588 "%% route-map name doesn't match static route\n");
5589 return CMD_WARNING_CONFIG_FAILED
;
5592 /* Update BGP RIB. */
5593 if (!bgp_static
->backdoor
)
5594 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5596 /* Clear configuration. */
5597 bgp_static_free(bgp_static
);
5598 bgp_dest_set_bgp_static_info(dest
, NULL
);
5599 bgp_dest_unlock_node(dest
);
5600 bgp_dest_unlock_node(dest
);
5603 /* Set BGP static route configuration. */
5604 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5605 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5607 /* Configuration change. */
5608 /* Label index cannot be changed. */
5609 if (bgp_static
->label_index
!= label_index
) {
5610 vty_out(vty
, "%% cannot change label-index\n");
5611 return CMD_WARNING_CONFIG_FAILED
;
5614 /* Check previous routes are installed into BGP. */
5615 if (bgp_static
->valid
5616 && bgp_static
->backdoor
!= backdoor
)
5619 bgp_static
->backdoor
= backdoor
;
5622 XFREE(MTYPE_ROUTE_MAP_NAME
,
5623 bgp_static
->rmap
.name
);
5624 route_map_counter_decrement(
5625 bgp_static
->rmap
.map
);
5626 bgp_static
->rmap
.name
=
5627 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5628 bgp_static
->rmap
.map
=
5629 route_map_lookup_by_name(rmap
);
5630 route_map_counter_increment(
5631 bgp_static
->rmap
.map
);
5633 XFREE(MTYPE_ROUTE_MAP_NAME
,
5634 bgp_static
->rmap
.name
);
5635 route_map_counter_decrement(
5636 bgp_static
->rmap
.map
);
5637 bgp_static
->rmap
.map
= NULL
;
5638 bgp_static
->valid
= 0;
5640 bgp_dest_unlock_node(dest
);
5642 /* New configuration. */
5643 bgp_static
= bgp_static_new();
5644 bgp_static
->backdoor
= backdoor
;
5645 bgp_static
->valid
= 0;
5646 bgp_static
->igpmetric
= 0;
5647 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5648 bgp_static
->label_index
= label_index
;
5651 XFREE(MTYPE_ROUTE_MAP_NAME
,
5652 bgp_static
->rmap
.name
);
5653 route_map_counter_decrement(
5654 bgp_static
->rmap
.map
);
5655 bgp_static
->rmap
.name
=
5656 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5657 bgp_static
->rmap
.map
=
5658 route_map_lookup_by_name(rmap
);
5659 route_map_counter_increment(
5660 bgp_static
->rmap
.map
);
5662 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5665 bgp_static
->valid
= 1;
5667 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5669 if (!bgp_static
->backdoor
)
5670 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5676 void bgp_static_add(struct bgp
*bgp
)
5680 struct bgp_dest
*dest
;
5681 struct bgp_dest
*rm
;
5682 struct bgp_table
*table
;
5683 struct bgp_static
*bgp_static
;
5685 FOREACH_AFI_SAFI (afi
, safi
)
5686 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5687 dest
= bgp_route_next(dest
)) {
5688 if (!bgp_dest_has_bgp_path_info_data(dest
))
5691 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5692 || (safi
== SAFI_EVPN
)) {
5693 table
= bgp_dest_get_bgp_table_info(dest
);
5695 for (rm
= bgp_table_top(table
); rm
;
5696 rm
= bgp_route_next(rm
)) {
5698 bgp_dest_get_bgp_static_info(
5700 bgp_static_update_safi(
5701 bgp
, bgp_dest_get_prefix(rm
),
5702 bgp_static
, afi
, safi
);
5706 bgp
, bgp_dest_get_prefix(dest
),
5707 bgp_dest_get_bgp_static_info(dest
), afi
,
5713 /* Called from bgp_delete(). Delete all static routes from the BGP
5715 void bgp_static_delete(struct bgp
*bgp
)
5719 struct bgp_dest
*dest
;
5720 struct bgp_dest
*rm
;
5721 struct bgp_table
*table
;
5722 struct bgp_static
*bgp_static
;
5724 FOREACH_AFI_SAFI (afi
, safi
)
5725 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5726 dest
= bgp_route_next(dest
)) {
5727 if (!bgp_dest_has_bgp_path_info_data(dest
))
5730 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5731 || (safi
== SAFI_EVPN
)) {
5732 table
= bgp_dest_get_bgp_table_info(dest
);
5734 for (rm
= bgp_table_top(table
); rm
;
5735 rm
= bgp_route_next(rm
)) {
5737 bgp_dest_get_bgp_static_info(
5742 bgp_static_withdraw_safi(
5743 bgp
, bgp_dest_get_prefix(rm
),
5745 (struct prefix_rd
*)
5746 bgp_dest_get_prefix(
5748 bgp_static_free(bgp_static
);
5749 bgp_dest_set_bgp_static_info(dest
,
5751 bgp_dest_unlock_node(dest
);
5754 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5755 bgp_static_withdraw(bgp
,
5756 bgp_dest_get_prefix(dest
),
5758 bgp_static_free(bgp_static
);
5759 bgp_dest_set_bgp_static_info(dest
, NULL
);
5760 bgp_dest_unlock_node(dest
);
5765 void bgp_static_redo_import_check(struct bgp
*bgp
)
5769 struct bgp_dest
*dest
;
5770 struct bgp_dest
*rm
;
5771 struct bgp_table
*table
;
5772 struct bgp_static
*bgp_static
;
5774 /* Use this flag to force reprocessing of the route */
5775 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5776 FOREACH_AFI_SAFI (afi
, safi
) {
5777 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5778 dest
= bgp_route_next(dest
)) {
5779 if (!bgp_dest_has_bgp_path_info_data(dest
))
5782 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5783 || (safi
== SAFI_EVPN
)) {
5784 table
= bgp_dest_get_bgp_table_info(dest
);
5786 for (rm
= bgp_table_top(table
); rm
;
5787 rm
= bgp_route_next(rm
)) {
5789 bgp_dest_get_bgp_static_info(
5791 bgp_static_update_safi(
5792 bgp
, bgp_dest_get_prefix(rm
),
5793 bgp_static
, afi
, safi
);
5796 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5797 bgp_static_update(bgp
,
5798 bgp_dest_get_prefix(dest
),
5799 bgp_static
, afi
, safi
);
5803 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5806 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5809 struct bgp_table
*table
;
5810 struct bgp_dest
*dest
;
5811 struct bgp_path_info
*pi
;
5813 /* Do not install the aggregate route if BGP is in the
5814 * process of termination.
5816 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
5817 || (bgp
->peer_self
== NULL
))
5820 table
= bgp
->rib
[afi
][safi
];
5821 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
5822 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
5823 if (pi
->peer
== bgp
->peer_self
5824 && ((pi
->type
== ZEBRA_ROUTE_BGP
5825 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5826 || (pi
->type
!= ZEBRA_ROUTE_BGP
5828 == BGP_ROUTE_REDISTRIBUTE
))) {
5829 bgp_aggregate_decrement(
5830 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
5832 bgp_unlink_nexthop(pi
);
5833 bgp_path_info_delete(dest
, pi
);
5834 bgp_process(bgp
, dest
, afi
, safi
);
5841 * Purge all networks and redistributed routes from routing table.
5842 * Invoked upon the instance going down.
5844 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5849 FOREACH_AFI_SAFI (afi
, safi
)
5850 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5855 * Currently this is used to set static routes for VPN and ENCAP.
5856 * I think it can probably be factored with bgp_static_set.
5858 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5859 const char *ip_str
, const char *rd_str
,
5860 const char *label_str
, const char *rmap_str
,
5861 int evpn_type
, const char *esi
, const char *gwip
,
5862 const char *ethtag
, const char *routermac
)
5864 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5867 struct prefix_rd prd
;
5868 struct bgp_dest
*pdest
;
5869 struct bgp_dest
*dest
;
5870 struct bgp_table
*table
;
5871 struct bgp_static
*bgp_static
;
5872 mpls_label_t label
= MPLS_INVALID_LABEL
;
5873 struct prefix gw_ip
;
5875 /* validate ip prefix */
5876 ret
= str2prefix(ip_str
, &p
);
5878 vty_out(vty
, "%% Malformed prefix\n");
5879 return CMD_WARNING_CONFIG_FAILED
;
5882 if ((afi
== AFI_L2VPN
)
5883 && (bgp_build_evpn_prefix(evpn_type
,
5884 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5885 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5886 return CMD_WARNING_CONFIG_FAILED
;
5889 ret
= str2prefix_rd(rd_str
, &prd
);
5891 vty_out(vty
, "%% Malformed rd\n");
5892 return CMD_WARNING_CONFIG_FAILED
;
5896 unsigned long label_val
;
5897 label_val
= strtoul(label_str
, NULL
, 10);
5898 encode_label(label_val
, &label
);
5901 if (safi
== SAFI_EVPN
) {
5902 if (esi
&& str2esi(esi
, NULL
) == 0) {
5903 vty_out(vty
, "%% Malformed ESI\n");
5904 return CMD_WARNING_CONFIG_FAILED
;
5906 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5907 vty_out(vty
, "%% Malformed Router MAC\n");
5908 return CMD_WARNING_CONFIG_FAILED
;
5911 memset(&gw_ip
, 0, sizeof(struct prefix
));
5912 ret
= str2prefix(gwip
, &gw_ip
);
5914 vty_out(vty
, "%% Malformed GatewayIp\n");
5915 return CMD_WARNING_CONFIG_FAILED
;
5917 if ((gw_ip
.family
== AF_INET
5918 && is_evpn_prefix_ipaddr_v6(
5919 (struct prefix_evpn
*)&p
))
5920 || (gw_ip
.family
== AF_INET6
5921 && is_evpn_prefix_ipaddr_v4(
5922 (struct prefix_evpn
*)&p
))) {
5924 "%% GatewayIp family differs with IP prefix\n");
5925 return CMD_WARNING_CONFIG_FAILED
;
5929 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5930 if (!bgp_dest_has_bgp_path_info_data(pdest
))
5931 bgp_dest_set_bgp_table_info(pdest
,
5932 bgp_table_init(bgp
, afi
, safi
));
5933 table
= bgp_dest_get_bgp_table_info(pdest
);
5935 dest
= bgp_node_get(table
, &p
);
5937 if (bgp_dest_has_bgp_path_info_data(dest
)) {
5938 vty_out(vty
, "%% Same network configuration exists\n");
5939 bgp_dest_unlock_node(dest
);
5941 /* New configuration. */
5942 bgp_static
= bgp_static_new();
5943 bgp_static
->backdoor
= 0;
5944 bgp_static
->valid
= 0;
5945 bgp_static
->igpmetric
= 0;
5946 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5947 bgp_static
->label
= label
;
5948 bgp_static
->prd
= prd
;
5951 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5952 route_map_counter_decrement(bgp_static
->rmap
.map
);
5953 bgp_static
->rmap
.name
=
5954 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5955 bgp_static
->rmap
.map
=
5956 route_map_lookup_by_name(rmap_str
);
5957 route_map_counter_increment(bgp_static
->rmap
.map
);
5960 if (safi
== SAFI_EVPN
) {
5962 bgp_static
->eth_s_id
=
5965 str2esi(esi
, bgp_static
->eth_s_id
);
5968 bgp_static
->router_mac
=
5969 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5970 (void)prefix_str2mac(routermac
,
5971 bgp_static
->router_mac
);
5974 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5976 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5978 bgp_static
->valid
= 1;
5979 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5985 /* Configure static BGP network. */
5986 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5987 const char *ip_str
, const char *rd_str
,
5988 const char *label_str
, int evpn_type
, const char *esi
,
5989 const char *gwip
, const char *ethtag
)
5991 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5994 struct prefix_rd prd
;
5995 struct bgp_dest
*pdest
;
5996 struct bgp_dest
*dest
;
5997 struct bgp_table
*table
;
5998 struct bgp_static
*bgp_static
;
5999 mpls_label_t label
= MPLS_INVALID_LABEL
;
6001 /* Convert IP prefix string to struct prefix. */
6002 ret
= str2prefix(ip_str
, &p
);
6004 vty_out(vty
, "%% Malformed prefix\n");
6005 return CMD_WARNING_CONFIG_FAILED
;
6008 if ((afi
== AFI_L2VPN
)
6009 && (bgp_build_evpn_prefix(evpn_type
,
6010 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6011 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6012 return CMD_WARNING_CONFIG_FAILED
;
6014 ret
= str2prefix_rd(rd_str
, &prd
);
6016 vty_out(vty
, "%% Malformed rd\n");
6017 return CMD_WARNING_CONFIG_FAILED
;
6021 unsigned long label_val
;
6022 label_val
= strtoul(label_str
, NULL
, 10);
6023 encode_label(label_val
, &label
);
6026 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6027 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6028 bgp_dest_set_bgp_table_info(pdest
,
6029 bgp_table_init(bgp
, afi
, safi
));
6031 bgp_dest_unlock_node(pdest
);
6032 table
= bgp_dest_get_bgp_table_info(pdest
);
6034 dest
= bgp_node_lookup(table
, &p
);
6037 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6039 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6040 bgp_static_free(bgp_static
);
6041 bgp_dest_set_bgp_static_info(dest
, NULL
);
6042 bgp_dest_unlock_node(dest
);
6043 bgp_dest_unlock_node(dest
);
6045 vty_out(vty
, "%% Can't find the route\n");
6050 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6051 const char *rmap_name
)
6053 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6054 struct bgp_rmap
*rmap
;
6056 rmap
= &bgp
->table_map
[afi
][safi
];
6058 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6059 route_map_counter_decrement(rmap
->map
);
6060 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6061 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6062 route_map_counter_increment(rmap
->map
);
6064 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6065 route_map_counter_decrement(rmap
->map
);
6069 if (bgp_fibupd_safi(safi
))
6070 bgp_zebra_announce_table(bgp
, afi
, safi
);
6075 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6076 const char *rmap_name
)
6078 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6079 struct bgp_rmap
*rmap
;
6081 rmap
= &bgp
->table_map
[afi
][safi
];
6082 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6083 route_map_counter_decrement(rmap
->map
);
6086 if (bgp_fibupd_safi(safi
))
6087 bgp_zebra_announce_table(bgp
, afi
, safi
);
6092 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6095 if (bgp
->table_map
[afi
][safi
].name
) {
6096 vty_out(vty
, " table-map %s\n",
6097 bgp
->table_map
[afi
][safi
].name
);
6101 DEFUN (bgp_table_map
,
6104 "BGP table to RIB route download filter\n"
6105 "Name of the route map\n")
6108 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6109 argv
[idx_word
]->arg
);
6111 DEFUN (no_bgp_table_map
,
6112 no_bgp_table_map_cmd
,
6113 "no table-map WORD",
6115 "BGP table to RIB route download filter\n"
6116 "Name of the route map\n")
6119 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6120 argv
[idx_word
]->arg
);
6126 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6127 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6128 backdoor$backdoor}]",
6130 "Specify a network to announce via BGP\n"
6135 "Route-map to modify the attributes\n"
6136 "Name of the route map\n"
6137 "Label index to associate with the prefix\n"
6138 "Label index value\n"
6139 "Specify a BGP backdoor route\n")
6141 char addr_prefix_str
[BUFSIZ
];
6146 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6149 vty_out(vty
, "%% Inconsistent address and mask\n");
6150 return CMD_WARNING_CONFIG_FAILED
;
6154 return bgp_static_set(
6155 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6156 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6157 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6160 DEFPY(ipv6_bgp_network
,
6161 ipv6_bgp_network_cmd
,
6162 "[no] network X:X::X:X/M$prefix \
6163 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6165 "Specify a network to announce via BGP\n"
6167 "Route-map to modify the attributes\n"
6168 "Name of the route map\n"
6169 "Label index to associate with the prefix\n"
6170 "Label index value\n")
6172 return bgp_static_set(
6173 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6174 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6177 static struct bgp_aggregate
*bgp_aggregate_new(void)
6179 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6182 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6184 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6185 route_map_counter_decrement(aggregate
->rmap
.map
);
6186 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6189 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6190 struct aspath
*aspath
,
6191 struct community
*comm
,
6192 struct ecommunity
*ecomm
,
6193 struct lcommunity
*lcomm
)
6195 static struct aspath
*ae
= NULL
;
6198 ae
= aspath_empty();
6203 if (origin
!= pi
->attr
->origin
)
6206 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6209 if (!community_cmp(pi
->attr
->community
, comm
))
6212 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6215 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6218 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6224 static void bgp_aggregate_install(
6225 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6226 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6227 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6228 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6230 struct bgp_dest
*dest
;
6231 struct bgp_table
*table
;
6232 struct bgp_path_info
*pi
, *orig
, *new;
6235 table
= bgp
->rib
[afi
][safi
];
6237 dest
= bgp_node_get(table
, p
);
6239 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6240 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6241 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6245 * If we have paths with different MEDs, then don't install
6246 * (or uninstall) the aggregate route.
6248 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6249 goto uninstall_aggregate_route
;
6251 if (aggregate
->count
> 0) {
6253 * If the aggregate information has not changed
6254 * no need to re-install it again.
6256 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6257 ecommunity
, lcommunity
)) {
6258 bgp_dest_unlock_node(dest
);
6261 aspath_free(aspath
);
6263 community_free(&community
);
6265 ecommunity_free(&ecommunity
);
6267 lcommunity_free(&lcommunity
);
6273 * Mark the old as unusable
6276 bgp_path_info_delete(dest
, pi
);
6278 attr
= bgp_attr_aggregate_intern(
6279 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6280 aggregate
, atomic_aggregate
, p
);
6283 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6287 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6288 bgp
->peer_self
, attr
, dest
);
6290 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6292 bgp_path_info_add(dest
, new);
6293 bgp_process(bgp
, dest
, afi
, safi
);
6295 uninstall_aggregate_route
:
6296 for (pi
= orig
; pi
; pi
= pi
->next
)
6297 if (pi
->peer
== bgp
->peer_self
6298 && pi
->type
== ZEBRA_ROUTE_BGP
6299 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6302 /* Withdraw static BGP route from routing table. */
6304 bgp_path_info_delete(dest
, pi
);
6305 bgp_process(bgp
, dest
, afi
, safi
);
6309 bgp_dest_unlock_node(dest
);
6313 * Check if the current path has different MED than other known paths.
6315 * \returns `true` if the MED matched the others else `false`.
6317 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6318 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6320 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6322 /* This is the first route being analyzed. */
6323 if (!aggregate
->med_initialized
) {
6324 aggregate
->med_initialized
= true;
6325 aggregate
->med_mismatched
= false;
6326 aggregate
->med_matched_value
= cur_med
;
6328 /* Check if routes with different MED showed up. */
6329 if (cur_med
!= aggregate
->med_matched_value
)
6330 aggregate
->med_mismatched
= true;
6333 return !aggregate
->med_mismatched
;
6337 * Initializes and tests all routes in the aggregate address path for MED
6340 * \returns `true` if all MEDs are the same otherwise `false`.
6342 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6343 struct bgp
*bgp
, const struct prefix
*p
,
6344 afi_t afi
, safi_t safi
)
6346 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6347 const struct prefix
*dest_p
;
6348 struct bgp_dest
*dest
, *top
;
6349 struct bgp_path_info
*pi
;
6350 bool med_matched
= true;
6352 aggregate
->med_initialized
= false;
6354 top
= bgp_node_get(table
, p
);
6355 for (dest
= bgp_node_get(table
, p
); dest
;
6356 dest
= bgp_route_next_until(dest
, top
)) {
6357 dest_p
= bgp_dest_get_prefix(dest
);
6358 if (dest_p
->prefixlen
<= p
->prefixlen
)
6361 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6362 if (BGP_PATH_HOLDDOWN(pi
))
6364 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6366 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6367 med_matched
= false;
6374 bgp_dest_unlock_node(top
);
6380 * Toggles the route suppression status for this aggregate address
6383 static void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6385 const struct prefix
*p
, afi_t afi
,
6386 safi_t safi
, bool suppress
)
6388 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6389 struct bgp_path_info_extra
*pie
;
6390 const struct prefix
*dest_p
;
6391 struct bgp_dest
*dest
, *top
;
6392 struct bgp_path_info
*pi
;
6393 bool toggle_suppression
;
6395 /* We've found a different MED we must revert any suppressed routes. */
6396 top
= bgp_node_get(table
, p
);
6397 for (dest
= bgp_node_get(table
, p
); dest
;
6398 dest
= bgp_route_next_until(dest
, top
)) {
6399 dest_p
= bgp_dest_get_prefix(dest
);
6400 if (dest_p
->prefixlen
<= p
->prefixlen
)
6403 toggle_suppression
= false;
6404 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6405 if (BGP_PATH_HOLDDOWN(pi
))
6407 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6411 * On installation it is possible that pi->extra is
6412 * set to NULL, otherwise it must exists.
6414 assert(!suppress
&& pi
->extra
!= NULL
);
6416 /* We are toggling suppression back. */
6418 pie
= bgp_path_info_extra_get(pi
);
6419 /* Suppress route if not suppressed already. */
6421 bgp_path_info_set_flag(dest
, pi
,
6422 BGP_PATH_ATTR_CHANGED
);
6423 toggle_suppression
= true;
6428 assert(pie
->suppress
> 0);
6430 /* Install route if there is no more suppression. */
6431 if (pie
->suppress
== 0) {
6432 bgp_path_info_set_flag(dest
, pi
,
6433 BGP_PATH_ATTR_CHANGED
);
6434 toggle_suppression
= true;
6438 if (toggle_suppression
)
6439 bgp_process(bgp
, dest
, afi
, safi
);
6441 bgp_dest_unlock_node(top
);
6445 * Aggregate address MED matching incremental test: this function is called
6446 * when the initial aggregation occurred and we are only testing a single
6449 * In addition to testing and setting the MED validity it also installs back
6450 * suppressed routes (if summary is configured).
6452 * Must not be called in `bgp_aggregate_route`.
6454 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6455 struct bgp
*bgp
, const struct prefix
*p
,
6456 afi_t afi
, safi_t safi
,
6457 struct bgp_path_info
*pi
, bool is_adding
)
6459 /* MED matching disabled. */
6460 if (!aggregate
->match_med
)
6463 /* Aggregation with different MED, nothing to do. */
6464 if (aggregate
->med_mismatched
)
6468 * Test the current entry:
6470 * is_adding == true: if the new entry doesn't match then we must
6471 * install all suppressed routes.
6473 * is_adding == false: if the entry being removed was the last
6474 * unmatching entry then we can suppress all routes.
6477 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6478 && aggregate
->summary_only
)
6479 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6482 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6484 /* No mismatches, just quit. */
6485 if (!aggregate
->med_mismatched
)
6488 /* Route summarization is disabled. */
6489 if (!aggregate
->summary_only
)
6492 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6495 /* Update an aggregate as routes are added/removed from the BGP table */
6496 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6497 safi_t safi
, struct bgp_aggregate
*aggregate
)
6499 struct bgp_table
*table
;
6500 struct bgp_dest
*top
;
6501 struct bgp_dest
*dest
;
6503 struct aspath
*aspath
= NULL
;
6504 struct community
*community
= NULL
;
6505 struct ecommunity
*ecommunity
= NULL
;
6506 struct lcommunity
*lcommunity
= NULL
;
6507 struct bgp_path_info
*pi
;
6508 unsigned long match
= 0;
6509 uint8_t atomic_aggregate
= 0;
6511 /* If the bgp instance is being deleted or self peer is deleted
6512 * then do not create aggregate route
6514 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6515 || (bgp
->peer_self
== NULL
))
6518 /* Initialize and test routes for MED difference. */
6519 if (aggregate
->match_med
)
6520 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6522 /* ORIGIN attribute: If at least one route among routes that are
6523 aggregated has ORIGIN with the value INCOMPLETE, then the
6524 aggregated route must have the ORIGIN attribute with the value
6525 INCOMPLETE. Otherwise, if at least one route among routes that
6526 are aggregated has ORIGIN with the value EGP, then the aggregated
6527 route must have the origin attribute with the value EGP. In all
6528 other case the value of the ORIGIN attribute of the aggregated
6529 route is INTERNAL. */
6530 origin
= BGP_ORIGIN_IGP
;
6532 table
= bgp
->rib
[afi
][safi
];
6534 top
= bgp_node_get(table
, p
);
6535 for (dest
= bgp_node_get(table
, p
); dest
;
6536 dest
= bgp_route_next_until(dest
, top
)) {
6537 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6539 if (dest_p
->prefixlen
<= p
->prefixlen
)
6544 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6545 if (BGP_PATH_HOLDDOWN(pi
))
6549 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6550 atomic_aggregate
= 1;
6552 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6556 * summary-only aggregate route suppress
6557 * aggregated route announcements.
6560 * Don't create summaries if MED didn't match
6561 * otherwise neither the specific routes and the
6562 * aggregation will be announced.
6564 if (aggregate
->summary_only
6565 && AGGREGATE_MED_VALID(aggregate
)) {
6566 (bgp_path_info_extra_get(pi
))->suppress
++;
6567 bgp_path_info_set_flag(dest
, pi
,
6568 BGP_PATH_ATTR_CHANGED
);
6575 * If at least one route among routes that are
6576 * aggregated has ORIGIN with the value INCOMPLETE,
6577 * then the aggregated route MUST have the ORIGIN
6578 * attribute with the value INCOMPLETE. Otherwise, if
6579 * at least one route among routes that are aggregated
6580 * has ORIGIN with the value EGP, then the aggregated
6581 * route MUST have the ORIGIN attribute with the value
6584 switch (pi
->attr
->origin
) {
6585 case BGP_ORIGIN_INCOMPLETE
:
6586 aggregate
->incomplete_origin_count
++;
6588 case BGP_ORIGIN_EGP
:
6589 aggregate
->egp_origin_count
++;
6597 if (!aggregate
->as_set
)
6601 * as-set aggregate route generate origin, as path,
6602 * and community aggregation.
6604 /* Compute aggregate route's as-path.
6606 bgp_compute_aggregate_aspath_hash(aggregate
,
6609 /* Compute aggregate route's community.
6611 if (pi
->attr
->community
)
6612 bgp_compute_aggregate_community_hash(
6614 pi
->attr
->community
);
6616 /* Compute aggregate route's extended community.
6618 if (pi
->attr
->ecommunity
)
6619 bgp_compute_aggregate_ecommunity_hash(
6621 pi
->attr
->ecommunity
);
6623 /* Compute aggregate route's large community.
6625 if (pi
->attr
->lcommunity
)
6626 bgp_compute_aggregate_lcommunity_hash(
6628 pi
->attr
->lcommunity
);
6631 bgp_process(bgp
, dest
, afi
, safi
);
6633 if (aggregate
->as_set
) {
6634 bgp_compute_aggregate_aspath_val(aggregate
);
6635 bgp_compute_aggregate_community_val(aggregate
);
6636 bgp_compute_aggregate_ecommunity_val(aggregate
);
6637 bgp_compute_aggregate_lcommunity_val(aggregate
);
6641 bgp_dest_unlock_node(top
);
6644 if (aggregate
->incomplete_origin_count
> 0)
6645 origin
= BGP_ORIGIN_INCOMPLETE
;
6646 else if (aggregate
->egp_origin_count
> 0)
6647 origin
= BGP_ORIGIN_EGP
;
6649 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6650 origin
= aggregate
->origin
;
6652 if (aggregate
->as_set
) {
6653 if (aggregate
->aspath
)
6654 /* Retrieve aggregate route's as-path.
6656 aspath
= aspath_dup(aggregate
->aspath
);
6658 if (aggregate
->community
)
6659 /* Retrieve aggregate route's community.
6661 community
= community_dup(aggregate
->community
);
6663 if (aggregate
->ecommunity
)
6664 /* Retrieve aggregate route's ecommunity.
6666 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6668 if (aggregate
->lcommunity
)
6669 /* Retrieve aggregate route's lcommunity.
6671 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6674 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6675 ecommunity
, lcommunity
, atomic_aggregate
,
6679 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6680 safi_t safi
, struct bgp_aggregate
*aggregate
)
6682 struct bgp_table
*table
;
6683 struct bgp_dest
*top
;
6684 struct bgp_dest
*dest
;
6685 struct bgp_path_info
*pi
;
6686 unsigned long match
;
6688 table
= bgp
->rib
[afi
][safi
];
6690 /* If routes exists below this node, generate aggregate routes. */
6691 top
= bgp_node_get(table
, p
);
6692 for (dest
= bgp_node_get(table
, p
); dest
;
6693 dest
= bgp_route_next_until(dest
, top
)) {
6694 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6696 if (dest_p
->prefixlen
<= p
->prefixlen
)
6700 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6701 if (BGP_PATH_HOLDDOWN(pi
))
6704 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6707 if (aggregate
->summary_only
&& pi
->extra
6708 && AGGREGATE_MED_VALID(aggregate
)) {
6709 pi
->extra
->suppress
--;
6711 if (pi
->extra
->suppress
== 0) {
6712 bgp_path_info_set_flag(
6714 BGP_PATH_ATTR_CHANGED
);
6720 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6721 aggregate
->incomplete_origin_count
--;
6722 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6723 aggregate
->egp_origin_count
--;
6725 if (aggregate
->as_set
) {
6726 /* Remove as-path from aggregate.
6728 bgp_remove_aspath_from_aggregate_hash(
6732 if (pi
->attr
->community
)
6733 /* Remove community from aggregate.
6735 bgp_remove_comm_from_aggregate_hash(
6737 pi
->attr
->community
);
6739 if (pi
->attr
->ecommunity
)
6740 /* Remove ecommunity from aggregate.
6742 bgp_remove_ecomm_from_aggregate_hash(
6744 pi
->attr
->ecommunity
);
6746 if (pi
->attr
->lcommunity
)
6747 /* Remove lcommunity from aggregate.
6749 bgp_remove_lcomm_from_aggregate_hash(
6751 pi
->attr
->lcommunity
);
6755 /* If this node was suppressed, process the change. */
6757 bgp_process(bgp
, dest
, afi
, safi
);
6759 if (aggregate
->as_set
) {
6760 aspath_free(aggregate
->aspath
);
6761 aggregate
->aspath
= NULL
;
6762 if (aggregate
->community
)
6763 community_free(&aggregate
->community
);
6764 if (aggregate
->ecommunity
)
6765 ecommunity_free(&aggregate
->ecommunity
);
6766 if (aggregate
->lcommunity
)
6767 lcommunity_free(&aggregate
->lcommunity
);
6770 bgp_dest_unlock_node(top
);
6773 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
6774 const struct prefix
*aggr_p
,
6775 struct bgp_path_info
*pinew
, afi_t afi
,
6777 struct bgp_aggregate
*aggregate
)
6780 struct aspath
*aspath
= NULL
;
6781 uint8_t atomic_aggregate
= 0;
6782 struct community
*community
= NULL
;
6783 struct ecommunity
*ecommunity
= NULL
;
6784 struct lcommunity
*lcommunity
= NULL
;
6786 /* ORIGIN attribute: If at least one route among routes that are
6787 * aggregated has ORIGIN with the value INCOMPLETE, then the
6788 * aggregated route must have the ORIGIN attribute with the value
6789 * INCOMPLETE. Otherwise, if at least one route among routes that
6790 * are aggregated has ORIGIN with the value EGP, then the aggregated
6791 * route must have the origin attribute with the value EGP. In all
6792 * other case the value of the ORIGIN attribute of the aggregated
6793 * route is INTERNAL.
6795 origin
= BGP_ORIGIN_IGP
;
6800 * This must be called before `summary` check to avoid
6801 * "suppressing" twice.
6803 if (aggregate
->match_med
)
6804 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
6807 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
6808 (bgp_path_info_extra_get(pinew
))->suppress
++;
6810 switch (pinew
->attr
->origin
) {
6811 case BGP_ORIGIN_INCOMPLETE
:
6812 aggregate
->incomplete_origin_count
++;
6814 case BGP_ORIGIN_EGP
:
6815 aggregate
->egp_origin_count
++;
6823 if (aggregate
->incomplete_origin_count
> 0)
6824 origin
= BGP_ORIGIN_INCOMPLETE
;
6825 else if (aggregate
->egp_origin_count
> 0)
6826 origin
= BGP_ORIGIN_EGP
;
6828 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6829 origin
= aggregate
->origin
;
6831 if (aggregate
->as_set
) {
6832 /* Compute aggregate route's as-path.
6834 bgp_compute_aggregate_aspath(aggregate
,
6835 pinew
->attr
->aspath
);
6837 /* Compute aggregate route's community.
6839 if (pinew
->attr
->community
)
6840 bgp_compute_aggregate_community(
6842 pinew
->attr
->community
);
6844 /* Compute aggregate route's extended community.
6846 if (pinew
->attr
->ecommunity
)
6847 bgp_compute_aggregate_ecommunity(
6849 pinew
->attr
->ecommunity
);
6851 /* Compute aggregate route's large community.
6853 if (pinew
->attr
->lcommunity
)
6854 bgp_compute_aggregate_lcommunity(
6856 pinew
->attr
->lcommunity
);
6858 /* Retrieve aggregate route's as-path.
6860 if (aggregate
->aspath
)
6861 aspath
= aspath_dup(aggregate
->aspath
);
6863 /* Retrieve aggregate route's community.
6865 if (aggregate
->community
)
6866 community
= community_dup(aggregate
->community
);
6868 /* Retrieve aggregate route's ecommunity.
6870 if (aggregate
->ecommunity
)
6871 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6873 /* Retrieve aggregate route's lcommunity.
6875 if (aggregate
->lcommunity
)
6876 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6879 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6880 aspath
, community
, ecommunity
,
6881 lcommunity
, atomic_aggregate
, aggregate
);
6884 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6886 struct bgp_path_info
*pi
,
6887 struct bgp_aggregate
*aggregate
,
6888 const struct prefix
*aggr_p
)
6891 struct aspath
*aspath
= NULL
;
6892 uint8_t atomic_aggregate
= 0;
6893 struct community
*community
= NULL
;
6894 struct ecommunity
*ecommunity
= NULL
;
6895 struct lcommunity
*lcommunity
= NULL
;
6896 unsigned long match
= 0;
6898 if (BGP_PATH_HOLDDOWN(pi
))
6901 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6904 if (aggregate
->summary_only
&& pi
->extra
&& pi
->extra
->suppress
> 0
6905 && AGGREGATE_MED_VALID(aggregate
)) {
6906 pi
->extra
->suppress
--;
6908 if (pi
->extra
->suppress
== 0) {
6909 bgp_path_info_set_flag(pi
->net
, pi
,
6910 BGP_PATH_ATTR_CHANGED
);
6916 * This must be called after `summary` check to avoid
6917 * "unsuppressing" twice.
6919 if (aggregate
->match_med
)
6920 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
6923 if (aggregate
->count
> 0)
6926 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6927 aggregate
->incomplete_origin_count
--;
6928 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6929 aggregate
->egp_origin_count
--;
6931 if (aggregate
->as_set
) {
6932 /* Remove as-path from aggregate.
6934 bgp_remove_aspath_from_aggregate(aggregate
,
6937 if (pi
->attr
->community
)
6938 /* Remove community from aggregate.
6940 bgp_remove_community_from_aggregate(
6942 pi
->attr
->community
);
6944 if (pi
->attr
->ecommunity
)
6945 /* Remove ecommunity from aggregate.
6947 bgp_remove_ecommunity_from_aggregate(
6949 pi
->attr
->ecommunity
);
6951 if (pi
->attr
->lcommunity
)
6952 /* Remove lcommunity from aggregate.
6954 bgp_remove_lcommunity_from_aggregate(
6956 pi
->attr
->lcommunity
);
6959 /* If this node was suppressed, process the change. */
6961 bgp_process(bgp
, pi
->net
, afi
, safi
);
6963 origin
= BGP_ORIGIN_IGP
;
6964 if (aggregate
->incomplete_origin_count
> 0)
6965 origin
= BGP_ORIGIN_INCOMPLETE
;
6966 else if (aggregate
->egp_origin_count
> 0)
6967 origin
= BGP_ORIGIN_EGP
;
6969 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6970 origin
= aggregate
->origin
;
6972 if (aggregate
->as_set
) {
6973 /* Retrieve aggregate route's as-path.
6975 if (aggregate
->aspath
)
6976 aspath
= aspath_dup(aggregate
->aspath
);
6978 /* Retrieve aggregate route's community.
6980 if (aggregate
->community
)
6981 community
= community_dup(aggregate
->community
);
6983 /* Retrieve aggregate route's ecommunity.
6985 if (aggregate
->ecommunity
)
6986 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6988 /* Retrieve aggregate route's lcommunity.
6990 if (aggregate
->lcommunity
)
6991 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6994 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6995 aspath
, community
, ecommunity
,
6996 lcommunity
, atomic_aggregate
, aggregate
);
6999 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7000 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7002 struct bgp_dest
*child
;
7003 struct bgp_dest
*dest
;
7004 struct bgp_aggregate
*aggregate
;
7005 struct bgp_table
*table
;
7007 table
= bgp
->aggregate
[afi
][safi
];
7009 /* No aggregates configured. */
7010 if (bgp_table_top_nolock(table
) == NULL
)
7013 if (p
->prefixlen
== 0)
7016 if (BGP_PATH_HOLDDOWN(pi
))
7019 child
= bgp_node_get(table
, p
);
7021 /* Aggregate address configuration check. */
7022 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7023 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7025 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7026 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7027 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7031 bgp_dest_unlock_node(child
);
7034 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7035 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7037 struct bgp_dest
*child
;
7038 struct bgp_dest
*dest
;
7039 struct bgp_aggregate
*aggregate
;
7040 struct bgp_table
*table
;
7042 table
= bgp
->aggregate
[afi
][safi
];
7044 /* No aggregates configured. */
7045 if (bgp_table_top_nolock(table
) == NULL
)
7048 if (p
->prefixlen
== 0)
7051 child
= bgp_node_get(table
, p
);
7053 /* Aggregate address configuration check. */
7054 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7055 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7057 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7058 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7059 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7063 bgp_dest_unlock_node(child
);
7066 /* Aggregate route attribute. */
7067 #define AGGREGATE_SUMMARY_ONLY 1
7068 #define AGGREGATE_AS_SET 1
7069 #define AGGREGATE_AS_UNSET 0
7071 static const char *bgp_origin2str(uint8_t origin
)
7074 case BGP_ORIGIN_IGP
:
7076 case BGP_ORIGIN_EGP
:
7078 case BGP_ORIGIN_INCOMPLETE
:
7079 return "incomplete";
7084 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
7085 afi_t afi
, safi_t safi
)
7087 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7090 struct bgp_dest
*dest
;
7091 struct bgp_aggregate
*aggregate
;
7093 /* Convert string to prefix structure. */
7094 ret
= str2prefix(prefix_str
, &p
);
7096 vty_out(vty
, "Malformed prefix\n");
7097 return CMD_WARNING_CONFIG_FAILED
;
7101 /* Old configuration check. */
7102 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
7105 "%% There is no aggregate-address configuration.\n");
7106 return CMD_WARNING_CONFIG_FAILED
;
7109 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7110 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
7111 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
7112 NULL
, NULL
, 0, aggregate
);
7114 /* Unlock aggregate address configuration. */
7115 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7117 if (aggregate
->community
)
7118 community_free(&aggregate
->community
);
7120 if (aggregate
->community_hash
) {
7121 /* Delete all communities in the hash.
7123 hash_clean(aggregate
->community_hash
,
7124 bgp_aggr_community_remove
);
7125 /* Free up the community_hash.
7127 hash_free(aggregate
->community_hash
);
7130 if (aggregate
->ecommunity
)
7131 ecommunity_free(&aggregate
->ecommunity
);
7133 if (aggregate
->ecommunity_hash
) {
7134 /* Delete all ecommunities in the hash.
7136 hash_clean(aggregate
->ecommunity_hash
,
7137 bgp_aggr_ecommunity_remove
);
7138 /* Free up the ecommunity_hash.
7140 hash_free(aggregate
->ecommunity_hash
);
7143 if (aggregate
->lcommunity
)
7144 lcommunity_free(&aggregate
->lcommunity
);
7146 if (aggregate
->lcommunity_hash
) {
7147 /* Delete all lcommunities in the hash.
7149 hash_clean(aggregate
->lcommunity_hash
,
7150 bgp_aggr_lcommunity_remove
);
7151 /* Free up the lcommunity_hash.
7153 hash_free(aggregate
->lcommunity_hash
);
7156 if (aggregate
->aspath
)
7157 aspath_free(aggregate
->aspath
);
7159 if (aggregate
->aspath_hash
) {
7160 /* Delete all as-paths in the hash.
7162 hash_clean(aggregate
->aspath_hash
,
7163 bgp_aggr_aspath_remove
);
7164 /* Free up the aspath_hash.
7166 hash_free(aggregate
->aspath_hash
);
7169 bgp_aggregate_free(aggregate
);
7170 bgp_dest_unlock_node(dest
);
7171 bgp_dest_unlock_node(dest
);
7176 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
7177 safi_t safi
, const char *rmap
,
7178 uint8_t summary_only
, uint8_t as_set
,
7179 uint8_t origin
, bool match_med
)
7181 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
7184 struct bgp_dest
*dest
;
7185 struct bgp_aggregate
*aggregate
;
7186 uint8_t as_set_new
= as_set
;
7188 /* Convert string to prefix structure. */
7189 ret
= str2prefix(prefix_str
, &p
);
7191 vty_out(vty
, "Malformed prefix\n");
7192 return CMD_WARNING_CONFIG_FAILED
;
7196 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
7197 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
7198 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7200 return CMD_WARNING_CONFIG_FAILED
;
7203 /* Old configuration check. */
7204 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
7205 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7208 vty_out(vty
, "There is already same aggregate network.\n");
7209 /* try to remove the old entry */
7210 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
7212 vty_out(vty
, "Error deleting aggregate.\n");
7213 bgp_dest_unlock_node(dest
);
7214 return CMD_WARNING_CONFIG_FAILED
;
7218 /* Make aggregate address structure. */
7219 aggregate
= bgp_aggregate_new();
7220 aggregate
->summary_only
= summary_only
;
7221 aggregate
->match_med
= match_med
;
7223 /* Network operators MUST NOT locally generate any new
7224 * announcements containing AS_SET or AS_CONFED_SET. If they have
7225 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7226 * SHOULD withdraw those routes and re-announce routes for the
7227 * aggregate or component prefixes (i.e., the more-specific routes
7228 * subsumed by the previously aggregated route) without AS_SET
7229 * or AS_CONFED_SET in the updates.
7231 if (bgp
->reject_as_sets
) {
7232 if (as_set
== AGGREGATE_AS_SET
) {
7233 as_set_new
= AGGREGATE_AS_UNSET
;
7235 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7238 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7242 aggregate
->as_set
= as_set_new
;
7243 aggregate
->safi
= safi
;
7244 /* Override ORIGIN attribute if defined.
7245 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7246 * to IGP which is not what rfc4271 says.
7247 * This enables the same behavior, optionally.
7249 aggregate
->origin
= origin
;
7252 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7253 route_map_counter_decrement(aggregate
->rmap
.map
);
7254 aggregate
->rmap
.name
=
7255 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7256 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7257 route_map_counter_increment(aggregate
->rmap
.map
);
7259 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7261 /* Aggregate address insert into BGP routing table. */
7262 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
7267 DEFPY(aggregate_addressv4
, aggregate_addressv4_cmd
,
7268 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7270 "|summary-only$summary_only"
7271 "|route-map WORD$rmap_name"
7272 "|origin <egp|igp|incomplete>$origin_s"
7273 "|matching-MED-only$match_med"
7276 "Configure BGP aggregate entries\n"
7277 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
7278 "Generate AS set path information\n"
7279 "Filter more specific routes from updates\n"
7280 "Apply route map to aggregate network\n"
7285 "Unknown heritage\n"
7286 "Only aggregate routes with matching MED\n")
7288 const char *prefix_s
= NULL
;
7289 safi_t safi
= bgp_node_safi(vty
);
7290 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7291 int as_set
= AGGREGATE_AS_UNSET
;
7292 char prefix_buf
[PREFIX2STR_BUFFER
];
7295 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
)
7297 vty_out(vty
, "%% Inconsistent address and mask\n");
7298 return CMD_WARNING_CONFIG_FAILED
;
7300 prefix_s
= prefix_buf
;
7302 prefix_s
= prefix_str
;
7305 if (strcmp(origin_s
, "egp") == 0)
7306 origin
= BGP_ORIGIN_EGP
;
7307 else if (strcmp(origin_s
, "igp") == 0)
7308 origin
= BGP_ORIGIN_IGP
;
7309 else if (strcmp(origin_s
, "incomplete") == 0)
7310 origin
= BGP_ORIGIN_INCOMPLETE
;
7314 as_set
= AGGREGATE_AS_SET
;
7316 /* Handle configuration removal, otherwise installation. */
7318 return bgp_aggregate_unset(vty
, prefix_s
, AFI_IP
, safi
);
7320 return bgp_aggregate_set(vty
, prefix_s
, AFI_IP
, safi
, rmap_name
,
7321 summary_only
!= NULL
, as_set
, origin
,
7325 DEFPY(aggregate_addressv6
, aggregate_addressv6_cmd
,
7326 "[no] aggregate-address X:X::X:X/M$prefix {"
7328 "|summary-only$summary_only"
7329 "|route-map WORD$rmap_name"
7330 "|origin <egp|igp|incomplete>$origin_s"
7331 "|matching-MED-only$match_med"
7334 "Configure BGP aggregate entries\n"
7335 "Aggregate prefix\n"
7336 "Generate AS set path information\n"
7337 "Filter more specific routes from updates\n"
7338 "Apply route map to aggregate network\n"
7343 "Unknown heritage\n"
7344 "Only aggregate routes with matching MED\n")
7346 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7347 int as_set
= AGGREGATE_AS_UNSET
;
7350 if (strcmp(origin_s
, "egp") == 0)
7351 origin
= BGP_ORIGIN_EGP
;
7352 else if (strcmp(origin_s
, "igp") == 0)
7353 origin
= BGP_ORIGIN_IGP
;
7354 else if (strcmp(origin_s
, "incomplete") == 0)
7355 origin
= BGP_ORIGIN_INCOMPLETE
;
7359 as_set
= AGGREGATE_AS_SET
;
7361 /* Handle configuration removal, otherwise installation. */
7363 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP6
,
7366 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP6
, SAFI_UNICAST
,
7367 rmap_name
, summary_only
!= NULL
, as_set
,
7368 origin
, match_med
!= NULL
);
7371 /* Redistribute route treatment. */
7372 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7373 const union g_addr
*nexthop
, ifindex_t ifindex
,
7374 enum nexthop_types_t nhtype
, uint32_t metric
,
7375 uint8_t type
, unsigned short instance
,
7378 struct bgp_path_info
*new;
7379 struct bgp_path_info
*bpi
;
7380 struct bgp_path_info rmap_path
;
7381 struct bgp_dest
*bn
;
7383 struct attr
*new_attr
;
7385 route_map_result_t ret
;
7386 struct bgp_redist
*red
;
7388 /* Make default attribute. */
7389 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7391 * This must not be NULL to satisfy Coverity SA
7393 assert(attr
.aspath
);
7396 case NEXTHOP_TYPE_IFINDEX
:
7398 case NEXTHOP_TYPE_IPV4
:
7399 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7400 attr
.nexthop
= nexthop
->ipv4
;
7402 case NEXTHOP_TYPE_IPV6
:
7403 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7404 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7405 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7407 case NEXTHOP_TYPE_BLACKHOLE
:
7408 switch (p
->family
) {
7410 attr
.nexthop
.s_addr
= INADDR_ANY
;
7413 memset(&attr
.mp_nexthop_global
, 0,
7414 sizeof(attr
.mp_nexthop_global
));
7415 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7420 attr
.nh_ifindex
= ifindex
;
7423 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7426 afi
= family2afi(p
->family
);
7428 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7430 struct attr attr_new
;
7432 /* Copy attribute for modification. */
7435 if (red
->redist_metric_flag
)
7436 attr_new
.med
= red
->redist_metric
;
7438 /* Apply route-map. */
7439 if (red
->rmap
.name
) {
7440 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7441 rmap_path
.peer
= bgp
->peer_self
;
7442 rmap_path
.attr
= &attr_new
;
7444 SET_FLAG(bgp
->peer_self
->rmap_type
,
7445 PEER_RMAP_TYPE_REDISTRIBUTE
);
7447 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7450 bgp
->peer_self
->rmap_type
= 0;
7452 if (ret
== RMAP_DENYMATCH
) {
7453 /* Free uninterned attribute. */
7454 bgp_attr_flush(&attr_new
);
7456 /* Unintern original. */
7457 aspath_unintern(&attr
.aspath
);
7458 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7463 if (bgp_in_graceful_shutdown(bgp
))
7464 bgp_attr_add_gshut_community(&attr_new
);
7466 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7467 SAFI_UNICAST
, p
, NULL
);
7469 new_attr
= bgp_attr_intern(&attr_new
);
7471 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
7472 if (bpi
->peer
== bgp
->peer_self
7473 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7477 /* Ensure the (source route) type is updated. */
7479 if (attrhash_cmp(bpi
->attr
, new_attr
)
7480 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7481 bgp_attr_unintern(&new_attr
);
7482 aspath_unintern(&attr
.aspath
);
7483 bgp_dest_unlock_node(bn
);
7486 /* The attribute is changed. */
7487 bgp_path_info_set_flag(bn
, bpi
,
7488 BGP_PATH_ATTR_CHANGED
);
7490 /* Rewrite BGP route information. */
7491 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7492 bgp_path_info_restore(bn
, bpi
);
7494 bgp_aggregate_decrement(
7495 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7496 bgp_attr_unintern(&bpi
->attr
);
7497 bpi
->attr
= new_attr
;
7498 bpi
->uptime
= bgp_clock();
7500 /* Process change. */
7501 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7503 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7504 bgp_dest_unlock_node(bn
);
7505 aspath_unintern(&attr
.aspath
);
7507 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7509 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7511 vpn_leak_from_vrf_update(
7512 bgp_get_default(), bgp
, bpi
);
7518 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7519 bgp
->peer_self
, new_attr
, bn
);
7520 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7522 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7523 bgp_path_info_add(bn
, new);
7524 bgp_dest_unlock_node(bn
);
7525 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7527 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7528 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7530 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7534 /* Unintern original. */
7535 aspath_unintern(&attr
.aspath
);
7538 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7539 unsigned short instance
)
7542 struct bgp_dest
*dest
;
7543 struct bgp_path_info
*pi
;
7544 struct bgp_redist
*red
;
7546 afi
= family2afi(p
->family
);
7548 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7550 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7551 SAFI_UNICAST
, p
, NULL
);
7553 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7554 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7558 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7559 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7561 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7564 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7565 bgp_path_info_delete(dest
, pi
);
7566 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7568 bgp_dest_unlock_node(dest
);
7572 /* Withdraw specified route type's route. */
7573 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7574 unsigned short instance
)
7576 struct bgp_dest
*dest
;
7577 struct bgp_path_info
*pi
;
7578 struct bgp_table
*table
;
7580 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7582 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
7583 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
7584 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7585 && pi
->instance
== instance
)
7589 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7590 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7592 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7595 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
7596 pi
, afi
, SAFI_UNICAST
);
7597 bgp_path_info_delete(dest
, pi
);
7598 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
7603 /* Static function to display route. */
7604 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
7605 json_object
*json
, bool wide
)
7611 if (p
->family
== AF_INET
) {
7615 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7618 json_object_string_add(json
, "prefix",
7619 inet_ntop(p
->family
,
7622 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7623 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7624 json_object_string_add(json
, "network", buf2
);
7626 } else if (p
->family
== AF_ETHERNET
) {
7627 prefix2str(p
, buf
, PREFIX_STRLEN
);
7628 len
= vty_out(vty
, "%s", buf
);
7629 } else if (p
->family
== AF_EVPN
) {
7633 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7636 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7637 } else if (p
->family
== AF_FLOWSPEC
) {
7638 route_vty_out_flowspec(vty
, p
, NULL
,
7640 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7641 NLRI_STRING_FORMAT_MIN
, json
);
7646 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7649 json_object_string_add(json
, "prefix",
7650 inet_ntop(p
->family
,
7653 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7654 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7655 json_object_string_add(json
, "network", buf2
);
7660 len
= wide
? (45 - len
) : (17 - len
);
7662 vty_out(vty
, "\n%*s", 20, " ");
7664 vty_out(vty
, "%*s", len
, " ");
7668 enum bgp_display_type
{
7672 /* Print the short form route status for a bgp_path_info */
7673 static void route_vty_short_status_out(struct vty
*vty
,
7674 struct bgp_path_info
*path
,
7675 json_object
*json_path
)
7679 /* Route status display. */
7680 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7681 json_object_boolean_true_add(json_path
, "removed");
7683 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7684 json_object_boolean_true_add(json_path
, "stale");
7686 if (path
->extra
&& path
->extra
->suppress
)
7687 json_object_boolean_true_add(json_path
, "suppressed");
7689 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7690 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7691 json_object_boolean_true_add(json_path
, "valid");
7694 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7695 json_object_boolean_true_add(json_path
, "history");
7697 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7698 json_object_boolean_true_add(json_path
, "damped");
7700 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7701 json_object_boolean_true_add(json_path
, "bestpath");
7703 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7704 json_object_boolean_true_add(json_path
, "multipath");
7706 /* Internal route. */
7707 if ((path
->peer
->as
)
7708 && (path
->peer
->as
== path
->peer
->local_as
))
7709 json_object_string_add(json_path
, "pathFrom",
7712 json_object_string_add(json_path
, "pathFrom",
7718 /* Route status display. */
7719 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7721 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7723 else if (path
->extra
&& path
->extra
->suppress
)
7725 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7726 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7732 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7734 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7736 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7738 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7743 /* Internal route. */
7744 if (path
->peer
&& (path
->peer
->as
)
7745 && (path
->peer
->as
== path
->peer
->local_as
))
7751 static char *bgp_nexthop_hostname(struct peer
*peer
,
7752 struct bgp_nexthop_cache
*bnc
)
7755 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
7756 return peer
->hostname
;
7760 /* called from terminal list command */
7761 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
7762 struct bgp_path_info
*path
, int display
, safi_t safi
,
7763 json_object
*json_paths
, bool wide
)
7766 struct attr
*attr
= path
->attr
;
7767 json_object
*json_path
= NULL
;
7768 json_object
*json_nexthops
= NULL
;
7769 json_object
*json_nexthop_global
= NULL
;
7770 json_object
*json_nexthop_ll
= NULL
;
7771 json_object
*json_ext_community
= NULL
;
7772 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7774 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7775 bool nexthop_othervrf
= false;
7776 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7777 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7778 char *nexthop_hostname
=
7779 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
7780 char esi_buf
[ESI_STR_LEN
];
7783 json_path
= json_object_new_object();
7785 /* short status lead text */
7786 route_vty_short_status_out(vty
, path
, json_path
);
7789 /* print prefix and mask */
7791 route_vty_out_route(p
, vty
, json_path
, wide
);
7793 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
7795 route_vty_out_route(p
, vty
, json_path
, wide
);
7799 * If vrf id of nexthop is different from that of prefix,
7800 * set up printable string to append
7802 if (path
->extra
&& path
->extra
->bgp_orig
) {
7803 const char *self
= "";
7808 nexthop_othervrf
= true;
7809 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7811 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7812 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7813 "@%s%s", VRFID_NONE_STR
, self
);
7815 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7816 path
->extra
->bgp_orig
->vrf_id
, self
);
7818 if (path
->extra
->bgp_orig
->inst_type
7819 != BGP_INSTANCE_TYPE_DEFAULT
)
7821 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7823 const char *self
= "";
7828 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7832 * For ENCAP and EVPN routes, nexthop address family is not
7833 * neccessarily the same as the prefix address family.
7834 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7835 * EVPN routes are also exchanged with a MP nexthop. Currently,
7837 * is only IPv4, the value will be present in either
7839 * attr->mp_nexthop_global_in
7841 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7844 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7848 snprintf(nexthop
, sizeof(nexthop
), "%s",
7849 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7853 snprintf(nexthop
, sizeof(nexthop
), "%s",
7854 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7858 snprintf(nexthop
, sizeof(nexthop
), "?");
7863 json_nexthop_global
= json_object_new_object();
7865 json_object_string_add(json_nexthop_global
, "ip",
7868 if (path
->peer
->hostname
)
7869 json_object_string_add(json_nexthop_global
,
7871 path
->peer
->hostname
);
7873 json_object_string_add(json_nexthop_global
, "afi",
7874 (af
== AF_INET
) ? "ipv4"
7876 json_object_boolean_true_add(json_nexthop_global
,
7879 if (nexthop_hostname
)
7880 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
7881 nexthop_hostname
, vrf_id_str
);
7883 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
7885 len
= wide
? (41 - len
) : (16 - len
);
7887 vty_out(vty
, "\n%*s", 36, " ");
7889 vty_out(vty
, "%*s", len
, " ");
7891 } else if (safi
== SAFI_EVPN
) {
7893 json_nexthop_global
= json_object_new_object();
7895 json_object_string_add(json_nexthop_global
, "ip",
7896 inet_ntoa(attr
->nexthop
));
7898 if (path
->peer
->hostname
)
7899 json_object_string_add(json_nexthop_global
,
7901 path
->peer
->hostname
);
7903 json_object_string_add(json_nexthop_global
, "afi",
7905 json_object_boolean_true_add(json_nexthop_global
,
7908 if (nexthop_hostname
)
7909 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7910 nexthop_hostname
, vrf_id_str
);
7912 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7915 len
= wide
? (41 - len
) : (16 - len
);
7917 vty_out(vty
, "\n%*s", 36, " ");
7919 vty_out(vty
, "%*s", len
, " ");
7921 } else if (safi
== SAFI_FLOWSPEC
) {
7922 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
7924 json_nexthop_global
= json_object_new_object();
7926 json_object_string_add(json_nexthop_global
,
7928 json_object_string_add(
7929 json_nexthop_global
, "ip",
7930 inet_ntoa(attr
->nexthop
));
7932 if (path
->peer
->hostname
)
7933 json_object_string_add(
7934 json_nexthop_global
, "hostname",
7935 path
->peer
->hostname
);
7937 json_object_boolean_true_add(
7938 json_nexthop_global
,
7941 if (nexthop_hostname
)
7942 len
= vty_out(vty
, "%pI4(%s)%s",
7947 len
= vty_out(vty
, "%pI4%s",
7951 len
= wide
? (41 - len
) : (16 - len
);
7953 vty_out(vty
, "\n%*s", 36, " ");
7955 vty_out(vty
, "%*s", len
, " ");
7958 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7960 json_nexthop_global
= json_object_new_object();
7962 json_object_string_add(json_nexthop_global
, "ip",
7963 inet_ntoa(attr
->nexthop
));
7965 if (path
->peer
->hostname
)
7966 json_object_string_add(json_nexthop_global
,
7968 path
->peer
->hostname
);
7970 json_object_string_add(json_nexthop_global
, "afi",
7972 json_object_boolean_true_add(json_nexthop_global
,
7975 if (nexthop_hostname
)
7976 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
7977 nexthop_hostname
, vrf_id_str
);
7979 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
7982 len
= wide
? (41 - len
) : (16 - len
);
7984 vty_out(vty
, "\n%*s", 36, " ");
7986 vty_out(vty
, "%*s", len
, " ");
7991 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7995 json_nexthop_global
= json_object_new_object();
7996 json_object_string_add(
7997 json_nexthop_global
, "ip",
7998 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8001 if (path
->peer
->hostname
)
8002 json_object_string_add(json_nexthop_global
,
8004 path
->peer
->hostname
);
8006 json_object_string_add(json_nexthop_global
, "afi",
8008 json_object_string_add(json_nexthop_global
, "scope",
8011 /* We display both LL & GL if both have been
8013 if ((attr
->mp_nexthop_len
8014 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8015 || (path
->peer
->conf_if
)) {
8016 json_nexthop_ll
= json_object_new_object();
8017 json_object_string_add(
8018 json_nexthop_ll
, "ip",
8020 &attr
->mp_nexthop_local
, buf
,
8023 if (path
->peer
->hostname
)
8024 json_object_string_add(
8025 json_nexthop_ll
, "hostname",
8026 path
->peer
->hostname
);
8028 json_object_string_add(json_nexthop_ll
, "afi",
8030 json_object_string_add(json_nexthop_ll
, "scope",
8033 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8034 &attr
->mp_nexthop_local
)
8036 && !attr
->mp_nexthop_prefer_global
)
8037 json_object_boolean_true_add(
8038 json_nexthop_ll
, "used");
8040 json_object_boolean_true_add(
8041 json_nexthop_global
, "used");
8043 json_object_boolean_true_add(
8044 json_nexthop_global
, "used");
8046 /* Display LL if LL/Global both in table unless
8047 * prefer-global is set */
8048 if (((attr
->mp_nexthop_len
8049 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8050 && !attr
->mp_nexthop_prefer_global
)
8051 || (path
->peer
->conf_if
)) {
8052 if (path
->peer
->conf_if
) {
8053 len
= vty_out(vty
, "%s",
8054 path
->peer
->conf_if
);
8055 /* len of IPv6 addr + max len of def
8057 len
= wide
? (41 - len
) : (16 - len
);
8060 vty_out(vty
, "\n%*s", 36, " ");
8062 vty_out(vty
, "%*s", len
, " ");
8064 if (nexthop_hostname
)
8067 &attr
->mp_nexthop_local
,
8073 &attr
->mp_nexthop_local
,
8076 len
= wide
? (41 - len
) : (16 - len
);
8079 vty_out(vty
, "\n%*s", 36, " ");
8081 vty_out(vty
, "%*s", len
, " ");
8084 if (nexthop_hostname
)
8085 len
= vty_out(vty
, "%pI6(%s)%s",
8086 &attr
->mp_nexthop_global
,
8090 len
= vty_out(vty
, "%pI6%s",
8091 &attr
->mp_nexthop_global
,
8094 len
= wide
? (41 - len
) : (16 - len
);
8097 vty_out(vty
, "\n%*s", 36, " ");
8099 vty_out(vty
, "%*s", len
, " ");
8105 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8107 json_object_int_add(json_path
, "metric", attr
->med
);
8109 vty_out(vty
, "%7u", attr
->med
);
8111 vty_out(vty
, "%10u", attr
->med
);
8112 else if (!json_paths
) {
8114 vty_out(vty
, "%*s", 7, " ");
8116 vty_out(vty
, "%*s", 10, " ");
8120 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8122 json_object_int_add(json_path
, "locPrf",
8125 vty_out(vty
, "%7u", attr
->local_pref
);
8126 else if (!json_paths
)
8130 json_object_int_add(json_path
, "weight", attr
->weight
);
8132 vty_out(vty
, "%7u ", attr
->weight
);
8136 json_object_string_add(
8137 json_path
, "peerId",
8138 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8144 json_object_string_add(json_path
, "path",
8147 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8152 json_object_string_add(json_path
, "origin",
8153 bgp_origin_long_str
[attr
->origin
]);
8155 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8158 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8159 json_object_string_add(json_path
, "esi",
8160 esi_to_str(&attr
->esi
,
8161 esi_buf
, sizeof(esi_buf
)));
8163 if (safi
== SAFI_EVPN
&&
8164 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8165 json_ext_community
= json_object_new_object();
8166 json_object_string_add(json_ext_community
,
8168 attr
->ecommunity
->str
);
8169 json_object_object_add(json_path
,
8170 "extendedCommunity",
8171 json_ext_community
);
8175 json_object_boolean_true_add(json_path
,
8176 "announceNexthopSelf");
8177 if (nexthop_othervrf
) {
8178 json_object_string_add(json_path
, "nhVrfName",
8181 json_object_int_add(json_path
, "nhVrfId",
8182 ((nexthop_vrfid
== VRF_UNKNOWN
)
8184 : (int)nexthop_vrfid
));
8189 if (json_nexthop_global
|| json_nexthop_ll
) {
8190 json_nexthops
= json_object_new_array();
8192 if (json_nexthop_global
)
8193 json_object_array_add(json_nexthops
,
8194 json_nexthop_global
);
8196 if (json_nexthop_ll
)
8197 json_object_array_add(json_nexthops
,
8200 json_object_object_add(json_path
, "nexthops",
8204 json_object_array_add(json_paths
, json_path
);
8208 if (safi
== SAFI_EVPN
) {
8209 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8210 vty_out(vty
, "%*s", 20, " ");
8211 vty_out(vty
, "ESI:%s\n",
8212 esi_to_str(&attr
->esi
,
8213 esi_buf
, sizeof(esi_buf
)));
8216 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8217 vty_out(vty
, "%*s", 20, " ");
8218 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8222 #ifdef ENABLE_BGP_VNC
8223 /* prints an additional line, indented, with VNC info, if
8225 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8226 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8231 /* called from terminal list command */
8232 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8233 struct attr
*attr
, safi_t safi
, bool use_json
,
8234 json_object
*json_ar
, bool wide
)
8236 json_object
*json_status
= NULL
;
8237 json_object
*json_net
= NULL
;
8241 /* Route status display. */
8243 json_status
= json_object_new_object();
8244 json_net
= json_object_new_object();
8251 /* print prefix and mask */
8253 if (safi
== SAFI_EVPN
)
8254 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8255 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8256 json_object_string_add(
8257 json_net
, "addrPrefix",
8258 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8260 json_object_int_add(json_net
, "prefixLen",
8262 prefix2str(p
, buff
, PREFIX_STRLEN
);
8263 json_object_string_add(json_net
, "network", buff
);
8266 route_vty_out_route(p
, vty
, NULL
, wide
);
8268 /* Print attribute */
8271 if (p
->family
== AF_INET
8272 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8273 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8274 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8275 json_object_string_add(
8276 json_net
, "nextHop",
8278 attr
->mp_nexthop_global_in
));
8280 json_object_string_add(
8281 json_net
, "nextHop",
8282 inet_ntoa(attr
->nexthop
));
8283 } else if (p
->family
== AF_INET6
8284 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8287 json_object_string_add(
8288 json_net
, "nextHopGlobal",
8290 &attr
->mp_nexthop_global
, buf
,
8292 } else if (p
->family
== AF_EVPN
&&
8293 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8294 json_object_string_add(json_net
,
8295 "nextHop", inet_ntoa(
8296 attr
->mp_nexthop_global_in
));
8299 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8300 json_object_int_add(json_net
, "metric",
8303 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8304 json_object_int_add(json_net
, "locPrf",
8307 json_object_int_add(json_net
, "weight", attr
->weight
);
8311 json_object_string_add(json_net
, "path",
8315 json_object_string_add(json_net
, "bgpOriginCode",
8316 bgp_origin_str
[attr
->origin
]);
8318 if (p
->family
== AF_INET
8319 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8320 || safi
== SAFI_EVPN
8321 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8322 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8323 || safi
== SAFI_EVPN
)
8324 vty_out(vty
, "%-16s",
8326 attr
->mp_nexthop_global_in
));
8328 vty_out(vty
, "%-41s",
8329 inet_ntoa(attr
->nexthop
));
8331 vty_out(vty
, "%-16s",
8332 inet_ntoa(attr
->nexthop
));
8333 } else if (p
->family
== AF_INET6
8334 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8340 &attr
->mp_nexthop_global
, buf
,
8342 len
= wide
? (41 - len
) : (16 - len
);
8344 vty_out(vty
, "\n%*s", 36, " ");
8346 vty_out(vty
, "%*s", len
, " ");
8349 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8351 vty_out(vty
, "%7u", attr
->med
);
8353 vty_out(vty
, "%10u", attr
->med
);
8359 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8360 vty_out(vty
, "%7u", attr
->local_pref
);
8364 vty_out(vty
, "%7u ", attr
->weight
);
8368 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8371 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8375 json_object_boolean_true_add(json_status
, "*");
8376 json_object_boolean_true_add(json_status
, ">");
8377 json_object_object_add(json_net
, "appliedStatusSymbols",
8380 prefix2str(p
, buff
, PREFIX_STRLEN
);
8381 json_object_object_add(json_ar
, buff
, json_net
);
8386 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
8387 struct bgp_path_info
*path
, int display
, safi_t safi
,
8390 json_object
*json_out
= NULL
;
8392 mpls_label_t label
= MPLS_INVALID_LABEL
;
8398 json_out
= json_object_new_object();
8400 /* short status lead text */
8401 route_vty_short_status_out(vty
, path
, json_out
);
8403 /* print prefix and mask */
8406 route_vty_out_route(p
, vty
, NULL
, false);
8408 vty_out(vty
, "%*s", 17, " ");
8411 /* Print attribute */
8413 if (((p
->family
== AF_INET
)
8414 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8415 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8416 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8417 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8418 || safi
== SAFI_EVPN
) {
8420 json_object_string_add(
8421 json_out
, "mpNexthopGlobalIn",
8422 inet_ntoa(attr
->mp_nexthop_global_in
));
8424 vty_out(vty
, "%-16s",
8425 inet_ntoa(attr
->mp_nexthop_global_in
));
8428 json_object_string_add(
8429 json_out
, "nexthop",
8430 inet_ntoa(attr
->nexthop
));
8432 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8434 } else if (((p
->family
== AF_INET6
)
8435 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8436 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8437 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8440 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8442 json_object_string_add(
8443 json_out
, "mpNexthopGlobalIn",
8445 &attr
->mp_nexthop_global
,
8446 buf_a
, sizeof(buf_a
)));
8450 &attr
->mp_nexthop_global
,
8451 buf_a
, sizeof(buf_a
)));
8452 } else if (attr
->mp_nexthop_len
8453 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8454 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8455 &attr
->mp_nexthop_global
,
8456 &attr
->mp_nexthop_local
);
8458 json_object_string_add(json_out
,
8459 "mpNexthopGlobalLocal",
8462 vty_out(vty
, "%s", buf_a
);
8466 label
= decode_label(&path
->extra
->label
[0]);
8468 if (bgp_is_valid_label(&label
)) {
8470 json_object_int_add(json_out
, "notag", label
);
8471 json_object_array_add(json
, json_out
);
8473 vty_out(vty
, "notag/%d", label
);
8479 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
8480 struct bgp_path_info
*path
, int display
,
8481 json_object
*json_paths
)
8484 char buf
[BUFSIZ
] = {0};
8485 json_object
*json_path
= NULL
;
8486 json_object
*json_nexthop
= NULL
;
8487 json_object
*json_overlay
= NULL
;
8493 json_path
= json_object_new_object();
8494 json_overlay
= json_object_new_object();
8495 json_nexthop
= json_object_new_object();
8498 /* short status lead text */
8499 route_vty_short_status_out(vty
, path
, json_path
);
8501 /* print prefix and mask */
8503 route_vty_out_route(p
, vty
, json_path
, false);
8505 vty_out(vty
, "%*s", 17, " ");
8507 /* Print attribute */
8510 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8514 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8516 vty_out(vty
, "%-16s", buf
);
8518 json_object_string_add(json_nexthop
, "ip", buf
);
8520 json_object_string_add(json_nexthop
, "afi", "ipv4");
8522 json_object_object_add(json_path
, "nexthop",
8527 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8528 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8530 vty_out(vty
, "%s(%s)", buf
, buf1
);
8532 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8534 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8537 json_object_string_add(json_nexthop
, "afi", "ipv6");
8539 json_object_object_add(json_path
, "nexthop",
8547 json_object_string_add(json_nexthop
, "Error",
8548 "Unsupported address-family");
8552 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8553 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8555 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8556 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8561 vty_out(vty
, "/%s", buf
);
8563 json_object_string_add(json_overlay
, "gw", buf
);
8565 if (attr
->ecommunity
) {
8567 struct ecommunity_val
*routermac
= ecommunity_lookup(
8568 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8569 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8572 mac
= ecom_mac2str((char *)routermac
->val
);
8575 vty_out(vty
, "/%s", mac
);
8577 json_object_string_add(json_overlay
, "rmac",
8580 XFREE(MTYPE_TMP
, mac
);
8587 json_object_object_add(json_path
, "overlay", json_overlay
);
8589 json_object_array_add(json_paths
, json_path
);
8593 /* dampening route */
8594 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8595 struct bgp_path_info
*path
, int display
,
8596 afi_t afi
, safi_t safi
, bool use_json
,
8601 char timebuf
[BGP_UPTIME_LEN
];
8603 /* short status lead text */
8604 route_vty_short_status_out(vty
, path
, json
);
8606 /* print prefix and mask */
8609 route_vty_out_route(p
, vty
, NULL
, false);
8611 vty_out(vty
, "%*s", 17, " ");
8614 len
= vty_out(vty
, "%s", path
->peer
->host
);
8618 vty_out(vty
, "\n%*s", 34, " ");
8621 json_object_int_add(json
, "peerHost", len
);
8623 vty_out(vty
, "%*s", len
, " ");
8627 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8628 safi
, use_json
, json
);
8631 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8632 BGP_UPTIME_LEN
, afi
, safi
,
8635 /* Print attribute */
8641 json_object_string_add(json
, "asPath",
8644 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8649 json_object_string_add(json
, "origin",
8650 bgp_origin_str
[attr
->origin
]);
8652 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8659 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8660 struct bgp_path_info
*path
, int display
,
8661 afi_t afi
, safi_t safi
, bool use_json
,
8665 struct bgp_damp_info
*bdi
;
8666 char timebuf
[BGP_UPTIME_LEN
];
8672 bdi
= path
->extra
->damp_info
;
8674 /* short status lead text */
8675 route_vty_short_status_out(vty
, path
, json
);
8677 /* print prefix and mask */
8680 route_vty_out_route(p
, vty
, NULL
, false);
8682 vty_out(vty
, "%*s", 17, " ");
8685 len
= vty_out(vty
, "%s", path
->peer
->host
);
8689 vty_out(vty
, "\n%*s", 33, " ");
8692 json_object_int_add(json
, "peerHost", len
);
8694 vty_out(vty
, "%*s", len
, " ");
8697 len
= vty_out(vty
, "%d", bdi
->flap
);
8704 json_object_int_add(json
, "bdiFlap", len
);
8706 vty_out(vty
, "%*s", len
, " ");
8710 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8713 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8714 BGP_UPTIME_LEN
, 0, NULL
));
8716 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8717 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8719 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8720 BGP_UPTIME_LEN
, afi
, safi
,
8724 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8725 BGP_UPTIME_LEN
, afi
,
8726 safi
, use_json
, json
));
8729 vty_out(vty
, "%*s ", 8, " ");
8732 /* Print attribute */
8738 json_object_string_add(json
, "asPath",
8741 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8746 json_object_string_add(json
, "origin",
8747 bgp_origin_str
[attr
->origin
]);
8749 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8755 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8756 int *first
, const char *header
,
8757 json_object
*json_adv_to
)
8759 char buf1
[INET6_ADDRSTRLEN
];
8760 json_object
*json_peer
= NULL
;
8763 /* 'advertised-to' is a dictionary of peers we have advertised
8765 * prefix too. The key is the peer's IP or swpX, the value is
8767 * hostname if we know it and "" if not.
8769 json_peer
= json_object_new_object();
8772 json_object_string_add(json_peer
, "hostname",
8776 json_object_object_add(json_adv_to
, peer
->conf_if
,
8779 json_object_object_add(
8781 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8785 vty_out(vty
, "%s", header
);
8790 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
8792 vty_out(vty
, " %s(%s)", peer
->hostname
,
8795 vty_out(vty
, " %s(%s)", peer
->hostname
,
8796 sockunion2str(&peer
->su
, buf1
,
8800 vty_out(vty
, " %s", peer
->conf_if
);
8803 sockunion2str(&peer
->su
, buf1
,
8809 static void route_vty_out_tx_ids(struct vty
*vty
,
8810 struct bgp_addpath_info_data
*d
)
8814 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8815 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8816 d
->addpath_tx_id
[i
],
8817 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8821 static const char *bgp_path_selection_reason2str(
8822 enum bgp_path_selection_reason reason
)
8825 case bgp_path_selection_none
:
8826 return "Nothing to Select";
8827 case bgp_path_selection_first
:
8828 return "First path received";
8829 case bgp_path_selection_evpn_sticky_mac
:
8830 return "EVPN Sticky Mac";
8831 case bgp_path_selection_evpn_seq
:
8832 return "EVPN sequence number";
8833 case bgp_path_selection_evpn_lower_ip
:
8834 return "EVPN lower IP";
8835 case bgp_path_selection_evpn_local_path
:
8836 return "EVPN local ES path";
8837 case bgp_path_selection_evpn_non_proxy
:
8838 return "EVPN non proxy";
8839 case bgp_path_selection_weight
:
8841 case bgp_path_selection_local_pref
:
8842 return "Local Pref";
8843 case bgp_path_selection_local_route
:
8844 return "Local Route";
8845 case bgp_path_selection_confed_as_path
:
8846 return "Confederation based AS Path";
8847 case bgp_path_selection_as_path
:
8849 case bgp_path_selection_origin
:
8851 case bgp_path_selection_med
:
8853 case bgp_path_selection_peer
:
8855 case bgp_path_selection_confed
:
8856 return "Confed Peer Type";
8857 case bgp_path_selection_igp_metric
:
8858 return "IGP Metric";
8859 case bgp_path_selection_older
:
8860 return "Older Path";
8861 case bgp_path_selection_router_id
:
8863 case bgp_path_selection_cluster_length
:
8864 return "Cluser length";
8865 case bgp_path_selection_stale
:
8866 return "Path Staleness";
8867 case bgp_path_selection_local_configured
:
8868 return "Locally configured route";
8869 case bgp_path_selection_neighbor_ip
:
8870 return "Neighbor IP";
8871 case bgp_path_selection_default
:
8872 return "Nothing left to compare";
8874 return "Invalid (internal error)";
8877 static void route_vty_out_detail_es_info(struct vty
*vty
,
8878 struct attr
*attr
, json_object
*json_path
)
8880 char esi_buf
[ESI_STR_LEN
];
8881 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
8882 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
8883 ATTR_ES_PEER_ROUTER
);
8884 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
8885 ATTR_ES_PEER_ACTIVE
);
8886 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
8887 ATTR_ES_PEER_PROXY
);
8889 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
8891 json_object
*json_es_info
= NULL
;
8893 json_object_string_add(
8896 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
8897 json_es_info
= json_object_new_object();
8899 json_object_boolean_true_add(
8900 json_es_info
, "localEs");
8902 json_object_boolean_true_add(
8903 json_es_info
, "peerActive");
8905 json_object_boolean_true_add(
8906 json_es_info
, "peerProxy");
8908 json_object_boolean_true_add(
8909 json_es_info
, "peerRouter");
8910 if (attr
->mm_sync_seqnum
)
8911 json_object_int_add(
8912 json_es_info
, "peerSeq",
8913 attr
->mm_sync_seqnum
);
8914 json_object_object_add(
8915 json_path
, "es_info",
8919 if (bgp_evpn_attr_is_sync(attr
))
8921 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
8923 es_local
? "local-es":"",
8924 peer_proxy
? "proxy " : "",
8925 peer_active
? "active ":"",
8926 peer_router
? "router ":"",
8927 attr
->mm_sync_seqnum
);
8929 vty_out(vty
, " ESI %s %s\n",
8931 es_local
? "local-es":"");
8935 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8936 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
8937 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8939 char buf
[INET6_ADDRSTRLEN
];
8941 char buf2
[EVPN_ROUTE_STRLEN
];
8942 struct attr
*attr
= path
->attr
;
8943 int sockunion_vty_out(struct vty
*, union sockunion
*);
8945 json_object
*json_bestpath
= NULL
;
8946 json_object
*json_cluster_list
= NULL
;
8947 json_object
*json_cluster_list_list
= NULL
;
8948 json_object
*json_ext_community
= NULL
;
8949 json_object
*json_last_update
= NULL
;
8950 json_object
*json_pmsi
= NULL
;
8951 json_object
*json_nexthop_global
= NULL
;
8952 json_object
*json_nexthop_ll
= NULL
;
8953 json_object
*json_nexthops
= NULL
;
8954 json_object
*json_path
= NULL
;
8955 json_object
*json_peer
= NULL
;
8956 json_object
*json_string
= NULL
;
8957 json_object
*json_adv_to
= NULL
;
8959 struct listnode
*node
, *nnode
;
8961 int addpath_capable
;
8963 unsigned int first_as
;
8965 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8967 char *nexthop_hostname
=
8968 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8971 json_path
= json_object_new_object();
8972 json_peer
= json_object_new_object();
8973 json_nexthop_global
= json_object_new_object();
8981 if (path
->extra
&& path
->extra
->num_labels
) {
8982 bgp_evpn_label2str(path
->extra
->label
,
8983 path
->extra
->num_labels
, tag_buf
,
8986 if (safi
== SAFI_EVPN
) {
8989 (struct prefix_evpn
*)
8990 bgp_dest_get_prefix(bn
),
8991 buf2
, sizeof(buf2
));
8992 vty_out(vty
, " Route %s", buf2
);
8993 if (tag_buf
[0] != '\0')
8994 vty_out(vty
, " VNI %s", tag_buf
);
8998 json_object_string_add(json_path
, "VNI",
9003 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9004 struct bgp_path_info
*parent_ri
;
9005 struct bgp_dest
*dest
, *pdest
;
9007 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9008 dest
= parent_ri
->net
;
9009 if (dest
&& dest
->pdest
) {
9010 pdest
= dest
->pdest
;
9012 (struct prefix_rd
*)bgp_dest_get_prefix(
9014 buf1
, sizeof(buf1
));
9015 if (is_pi_family_evpn(parent_ri
)) {
9017 (struct prefix_evpn
*)
9018 bgp_dest_get_prefix(
9020 buf2
, sizeof(buf2
));
9021 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
9023 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
9028 /* Line1 display AS-path, Aggregator */
9031 if (!attr
->aspath
->json
)
9032 aspath_str_update(attr
->aspath
, true);
9033 json_object_lock(attr
->aspath
->json
);
9034 json_object_object_add(json_path
, "aspath",
9035 attr
->aspath
->json
);
9037 if (attr
->aspath
->segments
)
9038 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9040 vty_out(vty
, " Local");
9044 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9046 json_object_boolean_true_add(json_path
, "removed");
9048 vty_out(vty
, ", (removed)");
9051 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9053 json_object_boolean_true_add(json_path
, "stale");
9055 vty_out(vty
, ", (stale)");
9058 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9060 json_object_int_add(json_path
, "aggregatorAs",
9061 attr
->aggregator_as
);
9062 json_object_string_add(
9063 json_path
, "aggregatorId",
9064 inet_ntoa(attr
->aggregator_addr
));
9065 if (attr
->aggregator_as
== BGP_AS_ZERO
)
9066 json_object_boolean_true_add(
9067 json_path
, "aggregatorAsMalformed");
9069 json_object_boolean_false_add(
9070 json_path
, "aggregatorAsMalformed");
9072 if (attr
->aggregator_as
== BGP_AS_ZERO
)
9074 ", (aggregated by %u(malformed) %s)",
9075 attr
->aggregator_as
,
9076 inet_ntoa(attr
->aggregator_addr
));
9078 vty_out(vty
, ", (aggregated by %u %s)",
9079 attr
->aggregator_as
,
9080 inet_ntoa(attr
->aggregator_addr
));
9084 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9085 PEER_FLAG_REFLECTOR_CLIENT
)) {
9087 json_object_boolean_true_add(json_path
,
9088 "rxedFromRrClient");
9090 vty_out(vty
, ", (Received from a RR-client)");
9093 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9094 PEER_FLAG_RSERVER_CLIENT
)) {
9096 json_object_boolean_true_add(json_path
,
9097 "rxedFromRsClient");
9099 vty_out(vty
, ", (Received from a RS-client)");
9102 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9104 json_object_boolean_true_add(json_path
,
9105 "dampeningHistoryEntry");
9107 vty_out(vty
, ", (history entry)");
9108 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9110 json_object_boolean_true_add(json_path
,
9111 "dampeningSuppressed");
9113 vty_out(vty
, ", (suppressed due to dampening)");
9119 /* Line2 display Next-hop, Neighbor, Router-id */
9120 /* Display the nexthop */
9121 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9123 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9124 || bn_p
->family
== AF_EVPN
)
9125 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9126 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9127 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9128 || safi
== SAFI_EVPN
) {
9130 json_object_string_add(
9131 json_nexthop_global
, "ip",
9132 inet_ntoa(attr
->mp_nexthop_global_in
));
9134 if (path
->peer
->hostname
)
9135 json_object_string_add(
9136 json_nexthop_global
, "hostname",
9137 path
->peer
->hostname
);
9139 if (nexthop_hostname
)
9140 vty_out(vty
, " %pI4(%s)",
9141 &attr
->mp_nexthop_global_in
,
9144 vty_out(vty
, " %pI4",
9145 &attr
->mp_nexthop_global_in
);
9149 json_object_string_add(
9150 json_nexthop_global
, "ip",
9151 inet_ntoa(attr
->nexthop
));
9153 if (path
->peer
->hostname
)
9154 json_object_string_add(
9155 json_nexthop_global
, "hostname",
9156 path
->peer
->hostname
);
9158 if (nexthop_hostname
)
9159 vty_out(vty
, " %pI4(%s)",
9163 vty_out(vty
, " %pI4",
9169 json_object_string_add(json_nexthop_global
, "afi",
9173 json_object_string_add(
9174 json_nexthop_global
, "ip",
9175 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9176 buf
, INET6_ADDRSTRLEN
));
9178 if (path
->peer
->hostname
)
9179 json_object_string_add(json_nexthop_global
,
9181 path
->peer
->hostname
);
9183 json_object_string_add(json_nexthop_global
, "afi",
9185 json_object_string_add(json_nexthop_global
, "scope",
9188 if (nexthop_hostname
)
9189 vty_out(vty
, " %pI6(%s)",
9190 &attr
->mp_nexthop_global
,
9193 vty_out(vty
, " %pI6",
9194 &attr
->mp_nexthop_global
);
9198 /* Display the IGP cost or 'inaccessible' */
9199 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9201 json_object_boolean_false_add(json_nexthop_global
,
9204 vty_out(vty
, " (inaccessible)");
9206 if (path
->extra
&& path
->extra
->igpmetric
) {
9208 json_object_int_add(json_nexthop_global
,
9210 path
->extra
->igpmetric
);
9212 vty_out(vty
, " (metric %u)",
9213 path
->extra
->igpmetric
);
9216 /* IGP cost is 0, display this only for json */
9219 json_object_int_add(json_nexthop_global
,
9224 json_object_boolean_true_add(json_nexthop_global
,
9228 /* Display peer "from" output */
9229 /* This path was originated locally */
9230 if (path
->peer
== bgp
->peer_self
) {
9232 if (safi
== SAFI_EVPN
9233 || (bn_p
->family
== AF_INET
9234 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9236 json_object_string_add(json_peer
, "peerId",
9239 vty_out(vty
, " from 0.0.0.0 ");
9242 json_object_string_add(json_peer
, "peerId",
9245 vty_out(vty
, " from :: ");
9249 json_object_string_add(json_peer
, "routerId",
9250 inet_ntoa(bgp
->router_id
));
9252 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
9255 /* We RXed this path from one of our peers */
9259 json_object_string_add(json_peer
, "peerId",
9260 sockunion2str(&path
->peer
->su
,
9263 json_object_string_add(json_peer
, "routerId",
9265 &path
->peer
->remote_id
,
9266 buf1
, sizeof(buf1
)));
9268 if (path
->peer
->hostname
)
9269 json_object_string_add(json_peer
, "hostname",
9270 path
->peer
->hostname
);
9272 if (path
->peer
->domainname
)
9273 json_object_string_add(json_peer
, "domainname",
9274 path
->peer
->domainname
);
9276 if (path
->peer
->conf_if
)
9277 json_object_string_add(json_peer
, "interface",
9278 path
->peer
->conf_if
);
9280 if (path
->peer
->conf_if
) {
9281 if (path
->peer
->hostname
9282 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9283 BGP_FLAG_SHOW_HOSTNAME
))
9284 vty_out(vty
, " from %s(%s)",
9285 path
->peer
->hostname
,
9286 path
->peer
->conf_if
);
9288 vty_out(vty
, " from %s",
9289 path
->peer
->conf_if
);
9291 if (path
->peer
->hostname
9292 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9293 BGP_FLAG_SHOW_HOSTNAME
))
9294 vty_out(vty
, " from %s(%s)",
9295 path
->peer
->hostname
,
9298 vty_out(vty
, " from %s",
9299 sockunion2str(&path
->peer
->su
,
9304 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9305 vty_out(vty
, " (%s)",
9306 inet_ntoa(attr
->originator_id
));
9308 vty_out(vty
, " (%s)",
9310 &path
->peer
->remote_id
, buf1
,
9316 * Note when vrfid of nexthop is different from that of prefix
9318 if (path
->extra
&& path
->extra
->bgp_orig
) {
9319 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9324 if (path
->extra
->bgp_orig
->inst_type
9325 == BGP_INSTANCE_TYPE_DEFAULT
)
9326 vn
= VRF_DEFAULT_NAME
;
9328 vn
= path
->extra
->bgp_orig
->name
;
9330 json_object_string_add(json_path
, "nhVrfName", vn
);
9332 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9333 json_object_int_add(json_path
, "nhVrfId", -1);
9335 json_object_int_add(json_path
, "nhVrfId",
9336 (int)nexthop_vrfid
);
9339 if (nexthop_vrfid
== VRF_UNKNOWN
)
9340 vty_out(vty
, " vrf ?");
9344 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9345 vty_out(vty
, " vrf %s(%u)",
9346 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9353 json_object_boolean_true_add(json_path
,
9354 "announceNexthopSelf");
9356 vty_out(vty
, " announce-nh-self");
9363 /* display the link-local nexthop */
9364 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9366 json_nexthop_ll
= json_object_new_object();
9367 json_object_string_add(
9368 json_nexthop_ll
, "ip",
9369 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9370 buf
, INET6_ADDRSTRLEN
));
9372 if (path
->peer
->hostname
)
9373 json_object_string_add(json_nexthop_ll
,
9375 path
->peer
->hostname
);
9377 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9378 json_object_string_add(json_nexthop_ll
, "scope",
9381 json_object_boolean_true_add(json_nexthop_ll
,
9384 if (!attr
->mp_nexthop_prefer_global
)
9385 json_object_boolean_true_add(json_nexthop_ll
,
9388 json_object_boolean_true_add(
9389 json_nexthop_global
, "used");
9391 vty_out(vty
, " (%s) %s\n",
9392 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9393 buf
, INET6_ADDRSTRLEN
),
9394 attr
->mp_nexthop_prefer_global
9399 /* If we do not have a link-local nexthop then we must flag the
9403 json_object_boolean_true_add(json_nexthop_global
,
9407 if (safi
== SAFI_EVPN
&&
9408 bgp_evpn_is_esi_valid(&attr
->esi
)) {
9409 route_vty_out_detail_es_info(vty
, attr
, json_path
);
9412 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9413 * Int/Ext/Local, Atomic, best */
9415 json_object_string_add(json_path
, "origin",
9416 bgp_origin_long_str
[attr
->origin
]);
9418 vty_out(vty
, " Origin %s",
9419 bgp_origin_long_str
[attr
->origin
]);
9421 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
9423 json_object_int_add(json_path
, "metric", attr
->med
);
9425 vty_out(vty
, ", metric %u", attr
->med
);
9428 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
9430 json_object_int_add(json_path
, "locPrf",
9433 vty_out(vty
, ", localpref %u", attr
->local_pref
);
9436 if (attr
->weight
!= 0) {
9438 json_object_int_add(json_path
, "weight", attr
->weight
);
9440 vty_out(vty
, ", weight %u", attr
->weight
);
9443 if (attr
->tag
!= 0) {
9445 json_object_int_add(json_path
, "tag", attr
->tag
);
9447 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9450 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9452 json_object_boolean_false_add(json_path
, "valid");
9454 vty_out(vty
, ", invalid");
9455 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9457 json_object_boolean_true_add(json_path
, "valid");
9459 vty_out(vty
, ", valid");
9462 if (path
->peer
!= bgp
->peer_self
) {
9463 if (path
->peer
->as
== path
->peer
->local_as
) {
9464 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9466 json_object_string_add(
9470 vty_out(vty
, ", confed-internal");
9473 json_object_string_add(
9474 json_peer
, "type", "internal");
9476 vty_out(vty
, ", internal");
9479 if (bgp_confederation_peers_check(bgp
,
9482 json_object_string_add(
9486 vty_out(vty
, ", confed-external");
9489 json_object_string_add(
9490 json_peer
, "type", "external");
9492 vty_out(vty
, ", external");
9495 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9497 json_object_boolean_true_add(json_path
, "aggregated");
9498 json_object_boolean_true_add(json_path
, "local");
9500 vty_out(vty
, ", aggregated, local");
9502 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9504 json_object_boolean_true_add(json_path
, "sourced");
9506 vty_out(vty
, ", sourced");
9509 json_object_boolean_true_add(json_path
, "sourced");
9510 json_object_boolean_true_add(json_path
, "local");
9512 vty_out(vty
, ", sourced, local");
9516 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9518 json_object_boolean_true_add(json_path
,
9521 vty_out(vty
, ", atomic-aggregate");
9524 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9525 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9526 && bgp_path_info_mpath_count(path
))) {
9528 json_object_boolean_true_add(json_path
, "multipath");
9530 vty_out(vty
, ", multipath");
9533 // Mark the bestpath(s)
9534 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9535 first_as
= aspath_get_first_as(attr
->aspath
);
9539 json_bestpath
= json_object_new_object();
9540 json_object_int_add(json_bestpath
, "bestpathFromAs",
9544 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9546 vty_out(vty
, ", bestpath-from-AS Local");
9550 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9553 json_bestpath
= json_object_new_object();
9554 json_object_boolean_true_add(json_bestpath
, "overall");
9555 json_object_string_add(
9556 json_bestpath
, "selectionReason",
9557 bgp_path_selection_reason2str(bn
->reason
));
9559 vty_out(vty
, ", best");
9560 vty_out(vty
, " (%s)",
9561 bgp_path_selection_reason2str(bn
->reason
));
9566 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9571 /* Line 4 display Community */
9572 if (attr
->community
) {
9574 if (!attr
->community
->json
)
9575 community_str(attr
->community
, true);
9576 json_object_lock(attr
->community
->json
);
9577 json_object_object_add(json_path
, "community",
9578 attr
->community
->json
);
9580 vty_out(vty
, " Community: %s\n",
9581 attr
->community
->str
);
9585 /* Line 5 display Extended-community */
9586 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9588 json_ext_community
= json_object_new_object();
9589 json_object_string_add(json_ext_community
, "string",
9590 attr
->ecommunity
->str
);
9591 json_object_object_add(json_path
, "extendedCommunity",
9592 json_ext_community
);
9594 vty_out(vty
, " Extended Community: %s\n",
9595 attr
->ecommunity
->str
);
9599 /* Line 6 display Large community */
9600 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9602 if (!attr
->lcommunity
->json
)
9603 lcommunity_str(attr
->lcommunity
, true);
9604 json_object_lock(attr
->lcommunity
->json
);
9605 json_object_object_add(json_path
, "largeCommunity",
9606 attr
->lcommunity
->json
);
9608 vty_out(vty
, " Large Community: %s\n",
9609 attr
->lcommunity
->str
);
9613 /* Line 7 display Originator, Cluster-id */
9614 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9615 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9616 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9618 json_object_string_add(
9619 json_path
, "originatorId",
9620 inet_ntoa(attr
->originator_id
));
9622 vty_out(vty
, " Originator: %s",
9623 inet_ntoa(attr
->originator_id
));
9626 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9630 json_cluster_list
= json_object_new_object();
9631 json_cluster_list_list
=
9632 json_object_new_array();
9634 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9636 json_string
= json_object_new_string(
9637 inet_ntoa(attr
->cluster
9639 json_object_array_add(
9640 json_cluster_list_list
,
9645 * struct cluster_list does not have
9646 * "str" variable like aspath and community
9647 * do. Add this someday if someone asks
9649 * json_object_string_add(json_cluster_list,
9650 * "string", attr->cluster->str);
9652 json_object_object_add(json_cluster_list
,
9654 json_cluster_list_list
);
9655 json_object_object_add(json_path
, "clusterList",
9658 vty_out(vty
, ", Cluster list: ");
9660 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9663 inet_ntoa(attr
->cluster
9673 if (path
->extra
&& path
->extra
->damp_info
)
9674 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9677 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9678 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9679 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9682 json_object_int_add(json_path
, "remoteLabel", label
);
9684 vty_out(vty
, " Remote label: %d\n", label
);
9688 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9689 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9691 json_object_string_add(json_path
, "remoteSid", buf
);
9693 vty_out(vty
, " Remote SID: %s\n", buf
);
9697 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9699 json_object_int_add(json_path
, "labelIndex",
9702 vty_out(vty
, " Label Index: %d\n",
9706 /* Line 8 display Addpath IDs */
9707 if (path
->addpath_rx_id
9708 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9710 json_object_int_add(json_path
, "addpathRxId",
9711 path
->addpath_rx_id
);
9713 /* Keep backwards compatibility with the old API
9714 * by putting TX All's ID in the old field
9716 json_object_int_add(
9717 json_path
, "addpathTxId",
9719 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9721 /* ... but create a specific field for each
9724 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9725 json_object_int_add(
9727 bgp_addpath_names(i
)->id_json_name
,
9728 path
->tx_addpath
.addpath_tx_id
[i
]);
9731 vty_out(vty
, " AddPath ID: RX %u, ",
9732 path
->addpath_rx_id
);
9734 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9738 /* If we used addpath to TX a non-bestpath we need to display
9739 * "Advertised to" on a path-by-path basis
9741 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9744 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9746 bgp_addpath_encode_tx(peer
, afi
, safi
);
9747 has_adj
= bgp_adj_out_lookup(
9749 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9750 &path
->tx_addpath
));
9752 if ((addpath_capable
&& has_adj
)
9753 || (!addpath_capable
&& has_adj
9754 && CHECK_FLAG(path
->flags
,
9755 BGP_PATH_SELECTED
))) {
9756 if (json_path
&& !json_adv_to
)
9757 json_adv_to
= json_object_new_object();
9759 route_vty_out_advertised_to(
9761 " Advertised to:", json_adv_to
);
9767 json_object_object_add(
9768 json_path
, "advertisedTo", json_adv_to
);
9777 /* Line 9 display Uptime */
9778 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9780 json_last_update
= json_object_new_object();
9781 json_object_int_add(json_last_update
, "epoch", tbuf
);
9782 json_object_string_add(json_last_update
, "string",
9784 json_object_object_add(json_path
, "lastUpdate",
9787 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9789 /* Line 10 display PMSI tunnel attribute, if present */
9790 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9792 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9793 PMSI_TNLTYPE_STR_DEFAULT
);
9796 json_pmsi
= json_object_new_object();
9797 json_object_string_add(json_pmsi
, "tunnelType", str
);
9798 json_object_int_add(json_pmsi
, "label",
9799 label2vni(&attr
->label
));
9800 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9802 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9803 str
, label2vni(&attr
->label
));
9806 /* We've constructed the json object for this path, add it to the json
9810 if (json_nexthop_global
|| json_nexthop_ll
) {
9811 json_nexthops
= json_object_new_array();
9813 if (json_nexthop_global
)
9814 json_object_array_add(json_nexthops
,
9815 json_nexthop_global
);
9817 if (json_nexthop_ll
)
9818 json_object_array_add(json_nexthops
,
9821 json_object_object_add(json_path
, "nexthops",
9825 json_object_object_add(json_path
, "peer", json_peer
);
9826 json_object_array_add(json_paths
, json_path
);
9830 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9831 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9832 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9834 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9835 const char *prefix_list_str
, afi_t afi
,
9836 safi_t safi
, enum bgp_show_type type
);
9837 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9838 const char *filter
, afi_t afi
, safi_t safi
,
9839 enum bgp_show_type type
);
9840 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9841 const char *rmap_str
, afi_t afi
, safi_t safi
,
9842 enum bgp_show_type type
);
9843 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9844 const char *com
, int exact
, afi_t afi
,
9846 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9847 const char *prefix
, afi_t afi
, safi_t safi
,
9848 enum bgp_show_type type
);
9849 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9850 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9852 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9853 const char *comstr
, int exact
, afi_t afi
,
9854 safi_t safi
, uint8_t show_flags
);
9857 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9858 struct bgp_table
*table
, enum bgp_show_type type
,
9859 void *output_arg
, char *rd
, int is_last
,
9860 unsigned long *output_cum
, unsigned long *total_cum
,
9861 unsigned long *json_header_depth
, uint8_t show_flags
)
9863 struct bgp_path_info
*pi
;
9864 struct bgp_dest
*dest
;
9867 unsigned long output_count
= 0;
9868 unsigned long total_count
= 0;
9870 json_object
*json_paths
= NULL
;
9872 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
9873 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
9874 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
9876 if (output_cum
&& *output_cum
!= 0)
9879 if (use_json
&& !*json_header_depth
) {
9881 *json_header_depth
= 1;
9883 vty_out(vty
, "{\n");
9884 *json_header_depth
= 2;
9888 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9889 " \"localAS\": %u,\n \"routes\": { ",
9890 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9891 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9894 table
->version
, inet_ntoa(bgp
->router_id
),
9895 bgp
->default_local_pref
, bgp
->as
);
9897 vty_out(vty
, " \"routeDistinguishers\" : {");
9898 ++*json_header_depth
;
9902 if (use_json
&& rd
) {
9903 vty_out(vty
, " \"%s\" : { ", rd
);
9906 /* Start processing of routes. */
9907 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
9908 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
9910 pi
= bgp_dest_get_bgp_path_info(dest
);
9916 json_paths
= json_object_new_array();
9920 for (; pi
; pi
= pi
->next
) {
9922 if (type
== bgp_show_type_flap_statistics
9923 || type
== bgp_show_type_flap_neighbor
9924 || type
== bgp_show_type_dampend_paths
9925 || type
== bgp_show_type_damp_neighbor
) {
9926 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9929 if (type
== bgp_show_type_regexp
) {
9930 regex_t
*regex
= output_arg
;
9932 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9936 if (type
== bgp_show_type_prefix_list
) {
9937 struct prefix_list
*plist
= output_arg
;
9939 if (prefix_list_apply(plist
, dest_p
)
9943 if (type
== bgp_show_type_filter_list
) {
9944 struct as_list
*as_list
= output_arg
;
9946 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9947 != AS_FILTER_PERMIT
)
9950 if (type
== bgp_show_type_route_map
) {
9951 struct route_map
*rmap
= output_arg
;
9952 struct bgp_path_info path
;
9953 struct attr dummy_attr
;
9954 route_map_result_t ret
;
9956 dummy_attr
= *pi
->attr
;
9958 path
.peer
= pi
->peer
;
9959 path
.attr
= &dummy_attr
;
9961 ret
= route_map_apply(rmap
, dest_p
, RMAP_BGP
,
9963 if (ret
== RMAP_DENYMATCH
)
9966 if (type
== bgp_show_type_neighbor
9967 || type
== bgp_show_type_flap_neighbor
9968 || type
== bgp_show_type_damp_neighbor
) {
9969 union sockunion
*su
= output_arg
;
9971 if (pi
->peer
== NULL
9972 || pi
->peer
->su_remote
== NULL
9973 || !sockunion_same(pi
->peer
->su_remote
, su
))
9976 if (type
== bgp_show_type_cidr_only
) {
9977 uint32_t destination
;
9979 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
9980 if (IN_CLASSC(destination
)
9981 && dest_p
->prefixlen
== 24)
9983 if (IN_CLASSB(destination
)
9984 && dest_p
->prefixlen
== 16)
9986 if (IN_CLASSA(destination
)
9987 && dest_p
->prefixlen
== 8)
9990 if (type
== bgp_show_type_prefix_longer
) {
9992 if (!prefix_match(p
, dest_p
))
9995 if (type
== bgp_show_type_community_all
) {
9996 if (!pi
->attr
->community
)
9999 if (type
== bgp_show_type_community
) {
10000 struct community
*com
= output_arg
;
10002 if (!pi
->attr
->community
10003 || !community_match(pi
->attr
->community
,
10007 if (type
== bgp_show_type_community_exact
) {
10008 struct community
*com
= output_arg
;
10010 if (!pi
->attr
->community
10011 || !community_cmp(pi
->attr
->community
, com
))
10014 if (type
== bgp_show_type_community_list
) {
10015 struct community_list
*list
= output_arg
;
10017 if (!community_list_match(pi
->attr
->community
,
10021 if (type
== bgp_show_type_community_list_exact
) {
10022 struct community_list
*list
= output_arg
;
10024 if (!community_list_exact_match(
10025 pi
->attr
->community
, list
))
10028 if (type
== bgp_show_type_lcommunity
) {
10029 struct lcommunity
*lcom
= output_arg
;
10031 if (!pi
->attr
->lcommunity
10032 || !lcommunity_match(pi
->attr
->lcommunity
,
10037 if (type
== bgp_show_type_lcommunity_exact
) {
10038 struct lcommunity
*lcom
= output_arg
;
10040 if (!pi
->attr
->lcommunity
10041 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10045 if (type
== bgp_show_type_lcommunity_list
) {
10046 struct community_list
*list
= output_arg
;
10048 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10053 == bgp_show_type_lcommunity_list_exact
) {
10054 struct community_list
*list
= output_arg
;
10056 if (!lcommunity_list_exact_match(
10057 pi
->attr
->lcommunity
, list
))
10060 if (type
== bgp_show_type_lcommunity_all
) {
10061 if (!pi
->attr
->lcommunity
)
10064 if (type
== bgp_show_type_dampend_paths
10065 || type
== bgp_show_type_damp_neighbor
) {
10066 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10067 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10071 if (!use_json
&& header
) {
10072 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
10074 inet_ntoa(bgp
->router_id
));
10075 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10076 vty_out(vty
, "%s", VRFID_NONE_STR
);
10078 vty_out(vty
, "%u", bgp
->vrf_id
);
10079 vty_out(vty
, "\n");
10080 vty_out(vty
, "Default local pref %u, ",
10081 bgp
->default_local_pref
);
10082 vty_out(vty
, "local AS %u\n", bgp
->as
);
10083 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10084 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10085 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10086 if (type
== bgp_show_type_dampend_paths
10087 || type
== bgp_show_type_damp_neighbor
)
10088 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10089 else if (type
== bgp_show_type_flap_statistics
10090 || type
== bgp_show_type_flap_neighbor
)
10091 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10093 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10094 : BGP_SHOW_HEADER
));
10097 if (rd
!= NULL
&& !display
&& !output_count
) {
10100 "Route Distinguisher: %s\n",
10103 if (type
== bgp_show_type_dampend_paths
10104 || type
== bgp_show_type_damp_neighbor
)
10105 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10106 AFI_IP
, safi
, use_json
,
10108 else if (type
== bgp_show_type_flap_statistics
10109 || type
== bgp_show_type_flap_neighbor
)
10110 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10111 AFI_IP
, safi
, use_json
,
10114 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10124 /* encode prefix */
10125 if (dest_p
->family
== AF_FLOWSPEC
) {
10126 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10129 bgp_fs_nlri_get_string(
10131 dest_p
->u
.prefix_flowspec
.ptr
,
10132 dest_p
->u
.prefix_flowspec
.prefixlen
,
10133 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10134 family2afi(dest_p
->u
10135 .prefix_flowspec
.family
));
10137 vty_out(vty
, "\"%s/%d\": ", retstr
,
10138 dest_p
->u
.prefix_flowspec
10141 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10142 dest_p
->u
.prefix_flowspec
10146 vty_out(vty
, "\"%pFX\": ", dest_p
);
10148 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10151 json_object_to_json_string_ext(
10152 json_paths
, JSON_C_TO_STRING_PRETTY
));
10153 json_object_free(json_paths
);
10157 json_object_free(json_paths
);
10161 output_count
+= *output_cum
;
10162 *output_cum
= output_count
;
10165 total_count
+= *total_cum
;
10166 *total_cum
= total_count
;
10170 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10174 for (i
= 0; i
< *json_header_depth
; ++i
)
10175 vty_out(vty
, " } ");
10177 vty_out(vty
, "\n");
10181 /* No route is displayed */
10182 if (output_count
== 0) {
10183 if (type
== bgp_show_type_normal
)
10185 "No BGP prefixes displayed, %ld exist\n",
10189 "\nDisplayed %ld routes and %ld total paths\n",
10190 output_count
, total_count
);
10194 return CMD_SUCCESS
;
10197 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10198 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10199 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10201 struct bgp_dest
*dest
, *next
;
10202 unsigned long output_cum
= 0;
10203 unsigned long total_cum
= 0;
10204 unsigned long json_header_depth
= 0;
10205 struct bgp_table
*itable
;
10207 uint8_t show_flags
= 0;
10209 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10212 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10214 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10215 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10217 next
= bgp_route_next(dest
);
10218 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10221 itable
= bgp_dest_get_bgp_table_info(dest
);
10222 if (itable
!= NULL
) {
10223 struct prefix_rd prd
;
10224 char rd
[RD_ADDRSTRLEN
];
10226 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10227 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10228 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10229 rd
, next
== NULL
, &output_cum
,
10230 &total_cum
, &json_header_depth
,
10237 if (output_cum
== 0)
10238 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10242 "\nDisplayed %ld routes and %ld total paths\n",
10243 output_cum
, total_cum
);
10245 return CMD_SUCCESS
;
10247 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10248 enum bgp_show_type type
, void *output_arg
,
10249 uint8_t show_flags
)
10251 struct bgp_table
*table
;
10252 unsigned long json_header_depth
= 0;
10253 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10256 bgp
= bgp_get_default();
10261 vty_out(vty
, "No BGP process is configured\n");
10263 vty_out(vty
, "{}\n");
10264 return CMD_WARNING
;
10267 table
= bgp
->rib
[afi
][safi
];
10268 /* use MPLS and ENCAP specific shows until they are merged */
10269 if (safi
== SAFI_MPLS_VPN
) {
10270 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10271 output_arg
, use_json
);
10274 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10275 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10276 output_arg
, use_json
,
10279 /* labeled-unicast routes live in the unicast table */
10280 else if (safi
== SAFI_LABELED_UNICAST
)
10281 safi
= SAFI_UNICAST
;
10283 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10284 NULL
, NULL
, &json_header_depth
, show_flags
);
10287 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10288 safi_t safi
, uint8_t show_flags
)
10290 struct listnode
*node
, *nnode
;
10293 bool route_output
= false;
10294 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10297 vty_out(vty
, "{\n");
10299 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10300 route_output
= true;
10303 vty_out(vty
, ",\n");
10307 vty_out(vty
, "\"%s\":",
10308 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10312 vty_out(vty
, "\nInstance %s:\n",
10313 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10317 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10322 vty_out(vty
, "}\n");
10323 else if (!route_output
)
10324 vty_out(vty
, "%% BGP instance not found\n");
10327 /* Header of detailed BGP route information */
10328 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10329 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10330 afi_t afi
, safi_t safi
, json_object
*json
)
10332 struct bgp_path_info
*pi
;
10333 const struct prefix
*p
;
10335 struct listnode
*node
, *nnode
;
10336 char buf1
[RD_ADDRSTRLEN
];
10337 char buf2
[INET6_ADDRSTRLEN
];
10338 char buf3
[EVPN_ROUTE_STRLEN
];
10339 char prefix_str
[BUFSIZ
];
10343 int accept_own
= 0;
10344 int route_filter_translated_v4
= 0;
10345 int route_filter_v4
= 0;
10346 int route_filter_translated_v6
= 0;
10347 int route_filter_v6
= 0;
10348 int llgr_stale
= 0;
10350 int accept_own_nexthop
= 0;
10353 int no_advertise
= 0;
10357 int has_valid_label
= 0;
10358 mpls_label_t label
= 0;
10359 json_object
*json_adv_to
= NULL
;
10361 p
= bgp_dest_get_prefix(dest
);
10362 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10364 if (has_valid_label
)
10365 label
= label_pton(&dest
->local_label
);
10367 if (safi
== SAFI_EVPN
) {
10370 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
10371 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10372 : "", prd
? ":" : "",
10373 bgp_evpn_route2str((struct prefix_evpn
*)p
,
10374 buf3
, sizeof(buf3
)));
10376 json_object_string_add(json
, "rd",
10377 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
10379 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
10383 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
10384 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
10385 ? prefix_rd2str(prd
, buf1
,
10388 safi
== SAFI_MPLS_VPN
? ":" : "",
10389 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
10394 json_object_string_add(json
, "prefix",
10395 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
10398 if (has_valid_label
) {
10400 json_object_int_add(json
, "localLabel", label
);
10402 vty_out(vty
, "Local label: %d\n", label
);
10406 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
10407 vty_out(vty
, "not allocated\n");
10409 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
10411 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
10413 if (pi
->extra
&& pi
->extra
->suppress
)
10416 if (pi
->attr
->community
== NULL
)
10419 no_advertise
+= community_include(
10420 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
10421 no_export
+= community_include(pi
->attr
->community
,
10422 COMMUNITY_NO_EXPORT
);
10423 local_as
+= community_include(pi
->attr
->community
,
10424 COMMUNITY_LOCAL_AS
);
10425 accept_own
+= community_include(pi
->attr
->community
,
10426 COMMUNITY_ACCEPT_OWN
);
10427 route_filter_translated_v4
+= community_include(
10428 pi
->attr
->community
,
10429 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
10430 route_filter_translated_v6
+= community_include(
10431 pi
->attr
->community
,
10432 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
10433 route_filter_v4
+= community_include(
10434 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
10435 route_filter_v6
+= community_include(
10436 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
10437 llgr_stale
+= community_include(pi
->attr
->community
,
10438 COMMUNITY_LLGR_STALE
);
10439 no_llgr
+= community_include(pi
->attr
->community
,
10440 COMMUNITY_NO_LLGR
);
10441 accept_own_nexthop
+=
10442 community_include(pi
->attr
->community
,
10443 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
10444 blackhole
+= community_include(pi
->attr
->community
,
10445 COMMUNITY_BLACKHOLE
);
10446 no_peer
+= community_include(pi
->attr
->community
,
10447 COMMUNITY_NO_PEER
);
10452 vty_out(vty
, "Paths: (%d available", count
);
10454 vty_out(vty
, ", best #%d", best
);
10455 if (safi
== SAFI_UNICAST
) {
10456 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10457 vty_out(vty
, ", table %s",
10460 vty_out(vty
, ", vrf %s",
10464 vty_out(vty
, ", no best path");
10468 ", accept own local route exported and imported in different VRF");
10469 else if (route_filter_translated_v4
)
10471 ", mark translated RTs for VPNv4 route filtering");
10472 else if (route_filter_v4
)
10474 ", attach RT as-is for VPNv4 route filtering");
10475 else if (route_filter_translated_v6
)
10477 ", mark translated RTs for VPNv6 route filtering");
10478 else if (route_filter_v6
)
10480 ", attach RT as-is for VPNv6 route filtering");
10481 else if (llgr_stale
)
10483 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10486 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10487 else if (accept_own_nexthop
)
10489 ", accept local nexthop");
10490 else if (blackhole
)
10491 vty_out(vty
, ", inform peer to blackhole prefix");
10492 else if (no_export
)
10493 vty_out(vty
, ", not advertised to EBGP peer");
10494 else if (no_advertise
)
10495 vty_out(vty
, ", not advertised to any peer");
10497 vty_out(vty
, ", not advertised outside local AS");
10500 ", inform EBGP peer not to advertise to their EBGP peers");
10504 ", Advertisements suppressed by an aggregate.");
10505 vty_out(vty
, ")\n");
10508 /* If we are not using addpath then we can display Advertised to and
10510 * show what peers we advertised the bestpath to. If we are using
10512 * though then we must display Advertised to on a path-by-path basis. */
10513 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10514 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10515 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
10516 if (json
&& !json_adv_to
)
10517 json_adv_to
= json_object_new_object();
10519 route_vty_out_advertised_to(
10521 " Advertised to non peer-group peers:\n ",
10528 json_object_object_add(json
, "advertisedTo",
10533 vty_out(vty
, " Not advertised to any peer");
10534 vty_out(vty
, "\n");
10539 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10540 struct bgp_dest
*bgp_node
, struct vty
*vty
,
10541 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10542 json_object
*json
, enum bgp_path_type pathtype
,
10545 struct bgp_path_info
*pi
;
10547 char rdbuf
[RD_ADDRSTRLEN
];
10548 json_object
*json_header
= NULL
;
10549 json_object
*json_paths
= NULL
;
10551 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
10553 if (json
&& !json_paths
) {
10554 /* Instantiate json_paths only if path is valid */
10555 json_paths
= json_object_new_array();
10557 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10558 json_header
= json_object_new_object();
10560 json_header
= json
;
10564 route_vty_out_detail_header(
10565 vty
, bgp
, bgp_node
, pfx_rd
,
10566 AFI_IP
, safi
, json_header
);
10571 if (pathtype
== BGP_PATH_SHOW_ALL
10572 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10573 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10574 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10575 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10576 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10577 route_vty_out_detail(vty
, bgp
, bgp_node
,
10582 if (json
&& json_paths
) {
10583 json_object_object_add(json_header
, "paths", json_paths
);
10586 json_object_object_add(json
, rdbuf
, json_header
);
10590 /* Display specified route of BGP table. */
10591 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10592 struct bgp_table
*rib
, const char *ip_str
,
10593 afi_t afi
, safi_t safi
,
10594 struct prefix_rd
*prd
, int prefix_check
,
10595 enum bgp_path_type pathtype
, bool use_json
)
10599 struct prefix match
;
10600 struct bgp_dest
*dest
;
10601 struct bgp_dest
*rm
;
10602 struct bgp_table
*table
;
10603 json_object
*json
= NULL
;
10604 json_object
*json_paths
= NULL
;
10606 /* Check IP address argument. */
10607 ret
= str2prefix(ip_str
, &match
);
10609 vty_out(vty
, "address is malformed\n");
10610 return CMD_WARNING
;
10613 match
.family
= afi2family(afi
);
10616 json
= json_object_new_object();
10618 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10619 for (dest
= bgp_table_top(rib
); dest
;
10620 dest
= bgp_route_next(dest
)) {
10621 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10623 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
10625 table
= bgp_dest_get_bgp_table_info(dest
);
10629 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10632 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
10634 && rm_p
->prefixlen
!= match
.prefixlen
) {
10635 bgp_dest_unlock_node(rm
);
10639 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10640 bgp
, afi
, safi
, json
, pathtype
,
10643 bgp_dest_unlock_node(rm
);
10645 } else if (safi
== SAFI_EVPN
) {
10646 struct bgp_dest
*longest_pfx
;
10647 bool is_exact_pfxlen_match
= false;
10649 for (dest
= bgp_table_top(rib
); dest
;
10650 dest
= bgp_route_next(dest
)) {
10651 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10653 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
10655 table
= bgp_dest_get_bgp_table_info(dest
);
10659 longest_pfx
= NULL
;
10660 is_exact_pfxlen_match
= false;
10662 * Search through all the prefixes for a match. The
10663 * pfx's are enumerated in ascending order of pfxlens.
10664 * So, the last pfx match is the longest match. Set
10665 * is_exact_pfxlen_match when we get exact pfxlen match
10667 for (rm
= bgp_table_top(table
); rm
;
10668 rm
= bgp_route_next(rm
)) {
10669 const struct prefix
*rm_p
=
10670 bgp_dest_get_prefix(rm
);
10672 * Get prefixlen of the ip-prefix within type5
10675 if (evpn_type5_prefix_match(rm_p
, &match
)
10679 bgp_evpn_get_type5_prefixlen(
10681 if (type5_pfxlen
== match
.prefixlen
) {
10682 is_exact_pfxlen_match
= true;
10683 bgp_dest_unlock_node(rm
);
10692 if (prefix_check
&& !is_exact_pfxlen_match
)
10696 bgp_dest_lock_node(rm
);
10698 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
10699 bgp
, afi
, safi
, json
, pathtype
,
10702 bgp_dest_unlock_node(rm
);
10704 } else if (safi
== SAFI_FLOWSPEC
) {
10706 json_paths
= json_object_new_array();
10708 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10709 &match
, prefix_check
,
10713 if (use_json
&& display
)
10714 json_object_object_add(json
, "paths", json_paths
);
10716 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
10717 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10719 || dest_p
->prefixlen
== match
.prefixlen
) {
10720 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
10721 safi
, json
, pathtype
,
10725 bgp_dest_unlock_node(dest
);
10730 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10731 json
, JSON_C_TO_STRING_PRETTY
|
10732 JSON_C_TO_STRING_NOSLASHESCAPE
));
10733 json_object_free(json
);
10736 vty_out(vty
, "%% Network not in table\n");
10737 return CMD_WARNING
;
10741 return CMD_SUCCESS
;
10744 /* Display specified route of Main RIB */
10745 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10746 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10747 int prefix_check
, enum bgp_path_type pathtype
,
10751 bgp
= bgp_get_default();
10754 vty_out(vty
, "No BGP process is configured\n");
10756 vty_out(vty
, "{}\n");
10757 return CMD_WARNING
;
10761 /* labeled-unicast routes live in the unicast table */
10762 if (safi
== SAFI_LABELED_UNICAST
)
10763 safi
= SAFI_UNICAST
;
10765 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10766 afi
, safi
, prd
, prefix_check
, pathtype
,
10770 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10771 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10772 safi_t safi
, bool uj
)
10774 struct lcommunity
*lcom
;
10779 uint8_t show_flags
= 0;
10782 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10784 b
= buffer_new(1024);
10785 for (i
= 0; i
< argc
; i
++) {
10787 buffer_putc(b
, ' ');
10789 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10791 buffer_putstr(b
, argv
[i
]->arg
);
10795 buffer_putc(b
, '\0');
10797 str
= buffer_getstr(b
);
10800 lcom
= lcommunity_str2com(str
);
10801 XFREE(MTYPE_TMP
, str
);
10803 vty_out(vty
, "%% Large-community malformed\n");
10804 return CMD_WARNING
;
10807 return bgp_show(vty
, bgp
, afi
, safi
,
10808 (exact
? bgp_show_type_lcommunity_exact
10809 : bgp_show_type_lcommunity
),
10813 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10814 const char *lcom
, bool exact
, afi_t afi
,
10815 safi_t safi
, bool uj
)
10817 struct community_list
*list
;
10818 uint8_t show_flags
= 0;
10821 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10824 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10825 LARGE_COMMUNITY_LIST_MASTER
);
10826 if (list
== NULL
) {
10827 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10829 return CMD_WARNING
;
10832 return bgp_show(vty
, bgp
, afi
, safi
,
10833 (exact
? bgp_show_type_lcommunity_list_exact
10834 : bgp_show_type_lcommunity_list
),
10838 DEFUN (show_ip_bgp_large_community_list
,
10839 show_ip_bgp_large_community_list_cmd
,
10840 "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]",
10844 BGP_INSTANCE_HELP_STR
10846 BGP_SAFI_WITH_LABEL_HELP_STR
10847 "Display routes matching the large-community-list\n"
10848 "large-community-list number\n"
10849 "large-community-list name\n"
10850 "Exact match of the large-communities\n"
10853 afi_t afi
= AFI_IP6
;
10854 safi_t safi
= SAFI_UNICAST
;
10856 bool exact_match
= 0;
10857 struct bgp
*bgp
= NULL
;
10858 bool uj
= use_json(argc
, argv
);
10863 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10866 return CMD_WARNING
;
10868 argv_find(argv
, argc
, "large-community-list", &idx
);
10870 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10872 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10875 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10876 exact_match
, afi
, safi
, uj
);
10878 DEFUN (show_ip_bgp_large_community
,
10879 show_ip_bgp_large_community_cmd
,
10880 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10884 BGP_INSTANCE_HELP_STR
10886 BGP_SAFI_WITH_LABEL_HELP_STR
10887 "Display routes matching the large-communities\n"
10888 "List of large-community numbers\n"
10889 "Exact match of the large-communities\n"
10892 afi_t afi
= AFI_IP6
;
10893 safi_t safi
= SAFI_UNICAST
;
10895 bool exact_match
= 0;
10896 struct bgp
*bgp
= NULL
;
10897 bool uj
= use_json(argc
, argv
);
10898 uint8_t show_flags
= 0;
10902 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10905 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10908 return CMD_WARNING
;
10910 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10911 if (argv_find(argv
, argc
, "exact-match", &idx
))
10913 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10914 exact_match
, afi
, safi
, uj
);
10916 return bgp_show(vty
, bgp
, afi
, safi
,
10917 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
10920 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10921 safi_t safi
, struct json_object
*json_array
);
10922 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10923 safi_t safi
, struct json_object
*json
);
10926 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
10927 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10928 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10929 "Display number of prefixes for all afi/safi\n" JSON_STR
)
10931 bool uj
= use_json(argc
, argv
);
10932 struct bgp
*bgp
= NULL
;
10933 safi_t safi
= SAFI_UNICAST
;
10934 afi_t afi
= AFI_IP6
;
10936 struct json_object
*json_all
= NULL
;
10937 struct json_object
*json_afi_safi
= NULL
;
10939 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10942 return CMD_WARNING
;
10945 json_all
= json_object_new_object();
10947 FOREACH_AFI_SAFI (afi
, safi
) {
10949 * So limit output to those afi/safi pairs that
10950 * actually have something interesting in them
10952 if (strmatch(get_afi_safi_str(afi
, safi
, true),
10957 json_afi_safi
= json_object_new_array();
10958 json_object_object_add(
10960 get_afi_safi_str(afi
, safi
, true),
10963 json_afi_safi
= NULL
;
10966 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10971 json_object_to_json_string_ext(
10972 json_all
, JSON_C_TO_STRING_PRETTY
));
10973 json_object_free(json_all
);
10976 return CMD_SUCCESS
;
10979 /* BGP route print out function without JSON */
10980 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
10981 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
10982 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
10986 BGP_INSTANCE_HELP_STR
10989 "BGP RIB advertisement statistics\n"
10992 afi_t afi
= AFI_IP6
;
10993 safi_t safi
= SAFI_UNICAST
;
10994 struct bgp
*bgp
= NULL
;
10996 bool uj
= use_json(argc
, argv
);
10997 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10999 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11002 return CMD_WARNING
;
11005 json_afi_safi
= json_object_new_array();
11007 json_afi_safi
= NULL
;
11009 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11012 json
= json_object_new_object();
11013 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11015 vty_out(vty
, "%s", json_object_to_json_string_ext(
11016 json
, JSON_C_TO_STRING_PRETTY
));
11017 json_object_free(json
);
11022 /* BGP route print out function without JSON */
11023 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11025 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11027 statistics [json]",
11028 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11029 BGP_SAFI_WITH_LABEL_HELP_STR
11030 "BGP RIB advertisement statistics\n" JSON_STR
)
11032 afi_t afi
= AFI_IP6
;
11033 safi_t safi
= SAFI_UNICAST
;
11034 struct bgp
*bgp
= NULL
;
11036 bool uj
= use_json(argc
, argv
);
11037 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11039 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11042 return CMD_WARNING
;
11045 json_afi_safi
= json_object_new_array();
11047 json_afi_safi
= NULL
;
11049 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11052 json
= json_object_new_object();
11053 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11056 json_object_to_json_string_ext(
11057 json
, JSON_C_TO_STRING_PRETTY
));
11058 json_object_free(json
);
11063 /* BGP route print out function without JSON */
11064 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11065 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11066 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11068 <[all$all] dampening <parameters>\
11072 |community-list <(1-500)|WORD> [exact-match]\
11073 |A.B.C.D/M longer-prefixes\
11074 |X:X::X:X/M longer-prefixes\
11076 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11077 BGP_SAFI_WITH_LABEL_HELP_STR
11078 "Display the entries for all address families\n"
11079 "Display detailed information about dampening\n"
11080 "Display detail of configured dampening parameters\n"
11081 "Display routes matching the route-map\n"
11082 "A route-map to match on\n"
11083 "Display routes conforming to the prefix-list\n"
11084 "Prefix-list name\n"
11085 "Display routes conforming to the filter-list\n"
11086 "Regular expression access list name\n"
11087 "Display routes matching the community-list\n"
11088 "community-list number\n"
11089 "community-list name\n"
11090 "Exact match of the communities\n"
11092 "Display route and more specific routes\n"
11094 "Display route and more specific routes\n")
11096 afi_t afi
= AFI_IP6
;
11097 safi_t safi
= SAFI_UNICAST
;
11098 int exact_match
= 0;
11099 struct bgp
*bgp
= NULL
;
11101 uint8_t show_flags
= 0;
11103 /* [<ipv4|ipv6> [all]] */
11105 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11106 if (argv_find(argv
, argc
, "ipv4", &idx
))
11107 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11109 if (argv_find(argv
, argc
, "ipv6", &idx
))
11110 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11113 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11116 return CMD_WARNING
;
11118 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11119 if (argv_find(argv
, argc
, "parameters", &idx
))
11120 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11124 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11125 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11126 safi
, bgp_show_type_prefix_list
);
11128 if (argv_find(argv
, argc
, "filter-list", &idx
))
11129 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11130 safi
, bgp_show_type_filter_list
);
11132 if (argv_find(argv
, argc
, "route-map", &idx
))
11133 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11134 safi
, bgp_show_type_route_map
);
11136 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11137 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11138 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11140 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11141 exact_match
, afi
, safi
);
11143 /* prefix-longer */
11144 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11145 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11146 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11148 bgp_show_type_prefix_longer
);
11150 return CMD_WARNING
;
11153 /* BGP route print out function with JSON */
11154 DEFPY (show_ip_bgp_json
,
11155 show_ip_bgp_json_cmd
,
11156 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11159 |dampening <flap-statistics|dampened-paths>\
11160 |community [AA:NN|local-AS|no-advertise|no-export\
11161 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11162 |accept-own|accept-own-nexthop|route-filter-v6\
11163 |route-filter-v4|route-filter-translated-v6\
11164 |route-filter-translated-v4] [exact-match]\
11165 ] [json$uj | wide$wide]",
11169 BGP_INSTANCE_HELP_STR
11171 BGP_SAFI_WITH_LABEL_HELP_STR
11172 "Display the entries for all address families\n"
11173 "Display only routes with non-natural netmasks\n"
11174 "Display detailed information about dampening\n"
11175 "Display flap statistics of routes\n"
11176 "Display paths suppressed due to dampening\n"
11177 "Display routes matching the communities\n"
11179 "Do not send outside local AS (well-known community)\n"
11180 "Do not advertise to any peer (well-known community)\n"
11181 "Do not export to next AS (well-known community)\n"
11182 "Graceful shutdown (well-known community)\n"
11183 "Do not export to any peer (well-known community)\n"
11184 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11185 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11186 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11187 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11188 "Should accept VPN route with local nexthop (well-known community)\n"
11189 "RT VPNv6 route filtering (well-known community)\n"
11190 "RT VPNv4 route filtering (well-known community)\n"
11191 "RT translated VPNv6 route filtering (well-known community)\n"
11192 "RT translated VPNv4 route filtering (well-known community)\n"
11193 "Exact match of the communities\n"
11195 "Increase table width for longer prefixes\n")
11197 afi_t afi
= AFI_IP6
;
11198 safi_t safi
= SAFI_UNICAST
;
11199 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11200 struct bgp
*bgp
= NULL
;
11202 int exact_match
= 0;
11203 char *community
= NULL
;
11205 uint8_t show_flags
= 0;
11210 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11213 /* [<ipv4|ipv6> [all]] */
11215 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11217 if (argv_find(argv
, argc
, "ipv4", &idx
))
11218 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11220 if (argv_find(argv
, argc
, "ipv6", &idx
))
11221 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11225 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11227 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11230 return CMD_WARNING
;
11232 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11233 sh_type
= bgp_show_type_cidr_only
;
11235 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11236 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11237 sh_type
= bgp_show_type_dampend_paths
;
11238 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11239 sh_type
= bgp_show_type_flap_statistics
;
11242 if (argv_find(argv
, argc
, "community", &idx
)) {
11243 char *maybecomm
= NULL
;
11245 if (idx
+ 1 < argc
) {
11246 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11247 maybecomm
= argv
[idx
+ 1]->arg
;
11249 maybecomm
= argv
[idx
+ 1]->text
;
11252 if (maybecomm
&& !strmatch(maybecomm
, "json")
11253 && !strmatch(maybecomm
, "exact-match"))
11254 community
= maybecomm
;
11256 if (argv_find(argv
, argc
, "exact-match", &idx
))
11260 sh_type
= bgp_show_type_community_all
;
11264 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11266 return bgp_show_community(vty
, bgp
, community
,
11267 exact_match
, afi
, safi
,
11270 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11273 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11277 vty_out(vty
, "{\n");
11279 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11280 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11281 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11284 FOREACH_SAFI (safi
) {
11285 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11289 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11296 vty_out(vty
, ",\n");
11297 vty_out(vty
, "\"%s\":{\n",
11298 get_afi_safi_str(afi
, safi
,
11302 "\nFor address family: %s\n",
11303 get_afi_safi_str(afi
, safi
,
11307 bgp_show_community(vty
, bgp
, community
,
11311 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11314 vty_out(vty
, "}\n");
11317 /* show <ip> bgp all: for each AFI and SAFI*/
11318 FOREACH_AFI_SAFI (afi
, safi
) {
11319 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11323 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11330 vty_out(vty
, ",\n");
11332 vty_out(vty
, "\"%s\":{\n",
11333 get_afi_safi_str(afi
, safi
,
11337 "\nFor address family: %s\n",
11338 get_afi_safi_str(afi
, safi
,
11342 bgp_show_community(vty
, bgp
, community
,
11346 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11349 vty_out(vty
, "}\n");
11353 vty_out(vty
, "}\n");
11355 return CMD_SUCCESS
;
11358 DEFUN (show_ip_bgp_route
,
11359 show_ip_bgp_route_cmd
,
11360 "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]",
11364 BGP_INSTANCE_HELP_STR
11366 BGP_SAFI_WITH_LABEL_HELP_STR
11367 "Network in the BGP routing table to display\n"
11369 "Network in the BGP routing table to display\n"
11371 "Display only the bestpath\n"
11372 "Display only multipaths\n"
11375 int prefix_check
= 0;
11377 afi_t afi
= AFI_IP6
;
11378 safi_t safi
= SAFI_UNICAST
;
11379 char *prefix
= NULL
;
11380 struct bgp
*bgp
= NULL
;
11381 enum bgp_path_type path_type
;
11382 bool uj
= use_json(argc
, argv
);
11386 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11389 return CMD_WARNING
;
11393 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11394 return CMD_WARNING
;
11397 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11398 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
11399 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
11401 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11402 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11405 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
11406 && afi
!= AFI_IP6
) {
11408 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11409 return CMD_WARNING
;
11411 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
11412 && afi
!= AFI_IP
) {
11414 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11415 return CMD_WARNING
;
11418 prefix
= argv
[idx
]->arg
;
11420 /* [<bestpath|multipath>] */
11421 if (argv_find(argv
, argc
, "bestpath", &idx
))
11422 path_type
= BGP_PATH_SHOW_BESTPATH
;
11423 else if (argv_find(argv
, argc
, "multipath", &idx
))
11424 path_type
= BGP_PATH_SHOW_MULTIPATH
;
11426 path_type
= BGP_PATH_SHOW_ALL
;
11428 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
11432 DEFUN (show_ip_bgp_regexp
,
11433 show_ip_bgp_regexp_cmd
,
11434 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
11438 BGP_INSTANCE_HELP_STR
11440 BGP_SAFI_WITH_LABEL_HELP_STR
11441 "Display routes matching the AS path regular expression\n"
11442 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11445 afi_t afi
= AFI_IP6
;
11446 safi_t safi
= SAFI_UNICAST
;
11447 struct bgp
*bgp
= NULL
;
11448 bool uj
= use_json(argc
, argv
);
11449 char *regstr
= NULL
;
11452 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11455 return CMD_WARNING
;
11457 // get index of regex
11458 if (argv_find(argv
, argc
, "REGEX", &idx
))
11459 regstr
= argv
[idx
]->arg
;
11462 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
11463 bgp_show_type_regexp
, uj
);
11466 DEFPY (show_ip_bgp_instance_all
,
11467 show_ip_bgp_instance_all_cmd
,
11468 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
11472 BGP_INSTANCE_ALL_HELP_STR
11474 BGP_SAFI_WITH_LABEL_HELP_STR
11476 "Increase table width for longer prefixes\n")
11478 afi_t afi
= AFI_IP
;
11479 safi_t safi
= SAFI_UNICAST
;
11480 struct bgp
*bgp
= NULL
;
11482 uint8_t show_flags
= 0;
11486 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11490 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11492 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11495 return CMD_WARNING
;
11497 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
11498 return CMD_SUCCESS
;
11501 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11502 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11507 uint8_t show_flags
= 0;
11510 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11512 if (!config_bgp_aspath_validate(regstr
)) {
11513 vty_out(vty
, "Invalid character in REGEX %s\n",
11515 return CMD_WARNING_CONFIG_FAILED
;
11518 regex
= bgp_regcomp(regstr
);
11520 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
11521 return CMD_WARNING
;
11524 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
11525 bgp_regex_free(regex
);
11529 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
11530 const char *prefix_list_str
, afi_t afi
,
11531 safi_t safi
, enum bgp_show_type type
)
11533 struct prefix_list
*plist
;
11534 uint8_t show_flags
= 0;
11536 plist
= prefix_list_lookup(afi
, prefix_list_str
);
11537 if (plist
== NULL
) {
11538 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
11540 return CMD_WARNING
;
11543 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
11546 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
11547 const char *filter
, afi_t afi
, safi_t safi
,
11548 enum bgp_show_type type
)
11550 struct as_list
*as_list
;
11551 uint8_t show_flags
= 0;
11553 as_list
= as_list_lookup(filter
);
11554 if (as_list
== NULL
) {
11555 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
11557 return CMD_WARNING
;
11560 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
11563 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
11564 const char *rmap_str
, afi_t afi
, safi_t safi
,
11565 enum bgp_show_type type
)
11567 struct route_map
*rmap
;
11568 uint8_t show_flags
= 0;
11570 rmap
= route_map_lookup_by_name(rmap_str
);
11572 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
11573 return CMD_WARNING
;
11576 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
11579 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11580 const char *comstr
, int exact
, afi_t afi
,
11581 safi_t safi
, uint8_t show_flags
)
11583 struct community
*com
;
11586 com
= community_str2com(comstr
);
11588 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
11589 return CMD_WARNING
;
11592 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11593 (exact
? bgp_show_type_community_exact
11594 : bgp_show_type_community
),
11596 community_free(&com
);
11601 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
11602 const char *com
, int exact
, afi_t afi
,
11605 struct community_list
*list
;
11606 uint8_t show_flags
= 0;
11608 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
11609 if (list
== NULL
) {
11610 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
11611 return CMD_WARNING
;
11614 return bgp_show(vty
, bgp
, afi
, safi
,
11615 (exact
? bgp_show_type_community_list_exact
11616 : bgp_show_type_community_list
),
11620 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
11621 const char *prefix
, afi_t afi
, safi_t safi
,
11622 enum bgp_show_type type
)
11626 uint8_t show_flags
= 0;
11630 ret
= str2prefix(prefix
, p
);
11632 vty_out(vty
, "%% Malformed Prefix\n");
11633 return CMD_WARNING
;
11636 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
11642 BGP_STATS_MAXBITLEN
= 0,
11644 BGP_STATS_PREFIXES
,
11646 BGP_STATS_UNAGGREGATEABLE
,
11647 BGP_STATS_MAX_AGGREGATEABLE
,
11648 BGP_STATS_AGGREGATES
,
11650 BGP_STATS_ASPATH_COUNT
,
11651 BGP_STATS_ASPATH_MAXHOPS
,
11652 BGP_STATS_ASPATH_TOTHOPS
,
11653 BGP_STATS_ASPATH_MAXSIZE
,
11654 BGP_STATS_ASPATH_TOTSIZE
,
11655 BGP_STATS_ASN_HIGHEST
,
11659 #define TABLE_STATS_IDX_VTY 0
11660 #define TABLE_STATS_IDX_JSON 1
11662 static const char *table_stats_strs
[][2] = {
11663 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
11664 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
11665 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
11666 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
11667 "unaggregateablePrefixes"},
11668 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
11669 "maximumAggregateablePrefixes"},
11670 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
11671 "bgpAggregateAdvertisements"},
11672 [BGP_STATS_SPACE
] = {"Address space advertised",
11673 "addressSpaceAdvertised"},
11674 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
11675 "advertisementsWithPaths"},
11676 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
11678 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
11680 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
11681 "averageAsPathLengthHops"},
11682 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
11683 "averageAsPathSizeBytes"},
11684 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
11685 [BGP_STATS_MAX
] = {NULL
, NULL
}
11688 struct bgp_table_stats
{
11689 struct bgp_table
*table
;
11690 unsigned long long counts
[BGP_STATS_MAX
];
11691 double total_space
;
11695 #define TALLY_SIGFIG 100000
11696 static unsigned long
11697 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
11699 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
11700 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
11701 unsigned long ret
= newtot
/ count
;
11703 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
11710 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
11711 struct bgp_table_stats
*ts
, unsigned int space
)
11713 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
11714 struct bgp_path_info
*pi
;
11715 const struct prefix
*rn_p
;
11720 if (!bgp_dest_has_bgp_path_info_data(dest
))
11723 rn_p
= bgp_dest_get_prefix(dest
);
11724 ts
->counts
[BGP_STATS_PREFIXES
]++;
11725 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
11728 ts
->counts
[BGP_STATS_AVGPLEN
]
11729 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
11730 ts
->counts
[BGP_STATS_AVGPLEN
],
11734 /* check if the prefix is included by any other announcements */
11735 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
11736 pdest
= bgp_dest_parent_nolock(pdest
);
11738 if (pdest
== NULL
|| pdest
== top
) {
11739 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
11740 /* announced address space */
11742 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
11743 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
11744 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11747 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11748 ts
->counts
[BGP_STATS_RIB
]++;
11750 if (CHECK_FLAG(pi
->attr
->flag
,
11751 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11752 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11754 /* as-path stats */
11755 if (pi
->attr
->aspath
) {
11756 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11757 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11758 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11760 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11762 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11763 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11765 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11766 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11768 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11769 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11771 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11772 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11773 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11775 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11776 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11777 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11780 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11781 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11786 static int bgp_table_stats_walker(struct thread
*t
)
11788 struct bgp_dest
*dest
, *ndest
;
11789 struct bgp_dest
*top
;
11790 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11791 unsigned int space
= 0;
11793 if (!(top
= bgp_table_top(ts
->table
)))
11796 switch (ts
->table
->afi
) {
11798 space
= IPV4_MAX_BITLEN
;
11801 space
= IPV6_MAX_BITLEN
;
11807 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11809 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
11810 if (ts
->table
->safi
== SAFI_MPLS_VPN
11811 || ts
->table
->safi
== SAFI_ENCAP
11812 || ts
->table
->safi
== SAFI_EVPN
) {
11813 struct bgp_table
*table
;
11815 table
= bgp_dest_get_bgp_table_info(dest
);
11819 top
= bgp_table_top(table
);
11820 for (ndest
= bgp_table_top(table
); ndest
;
11821 ndest
= bgp_route_next(ndest
))
11822 bgp_table_stats_rn(ndest
, top
, ts
, space
);
11824 bgp_table_stats_rn(dest
, top
, ts
, space
);
11831 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
11832 struct json_object
*json_array
)
11834 struct listnode
*node
, *nnode
;
11837 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
11838 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
11841 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11842 safi_t safi
, struct json_object
*json_array
)
11844 struct bgp_table_stats ts
;
11846 int ret
= CMD_SUCCESS
;
11848 struct json_object
*json
= NULL
;
11851 json
= json_object_new_object();
11853 if (!bgp
->rib
[afi
][safi
]) {
11854 char warning_msg
[50];
11856 snprintf(warning_msg
, sizeof(warning_msg
),
11857 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
11861 vty_out(vty
, "%s\n", warning_msg
);
11863 json_object_string_add(json
, "warning", warning_msg
);
11866 goto end_table_stats
;
11870 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
11871 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
11873 json_object_string_add(json
, "instance", bgp
->name_pretty
);
11875 /* labeled-unicast routes live in the unicast table */
11876 if (safi
== SAFI_LABELED_UNICAST
)
11877 safi
= SAFI_UNICAST
;
11879 memset(&ts
, 0, sizeof(ts
));
11880 ts
.table
= bgp
->rib
[afi
][safi
];
11881 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11883 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11884 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
11885 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
11890 case BGP_STATS_ASPATH_AVGHOPS
:
11891 case BGP_STATS_ASPATH_AVGSIZE
:
11892 case BGP_STATS_AVGPLEN
:
11893 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11894 vty_out (vty
, "%12.2f",
11895 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11898 case BGP_STATS_ASPATH_TOTHOPS
:
11899 case BGP_STATS_ASPATH_TOTSIZE
:
11902 temp_buf
, sizeof(temp_buf
), "%12.2f",
11904 ? (float)ts
.counts
[i
]
11906 [BGP_STATS_ASPATH_COUNT
]
11908 vty_out(vty
, "%-30s: %s",
11909 table_stats_strs
[i
]
11910 [TABLE_STATS_IDX_VTY
],
11913 json_object_double_add(
11915 table_stats_strs
[i
]
11916 [TABLE_STATS_IDX_JSON
],
11918 ? (double)ts
.counts
[i
]
11919 / (double)ts
.counts
11920 [BGP_STATS_ASPATH_COUNT
]
11924 case BGP_STATS_TOTPLEN
:
11927 temp_buf
, sizeof(temp_buf
), "%12.2f",
11929 ? (float)ts
.counts
[i
]
11931 [BGP_STATS_PREFIXES
]
11933 vty_out(vty
, "%-30s: %s",
11934 table_stats_strs
[i
]
11935 [TABLE_STATS_IDX_VTY
],
11938 json_object_double_add(
11940 table_stats_strs
[i
]
11941 [TABLE_STATS_IDX_JSON
],
11943 ? (double)ts
.counts
[i
]
11944 / (double)ts
.counts
11945 [BGP_STATS_PREFIXES
]
11949 case BGP_STATS_SPACE
:
11951 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
11953 vty_out(vty
, "%-30s: %s\n",
11954 table_stats_strs
[i
]
11955 [TABLE_STATS_IDX_VTY
],
11958 json_object_double_add(
11960 table_stats_strs
[i
]
11961 [TABLE_STATS_IDX_JSON
],
11962 (double)ts
.total_space
);
11964 if (afi
== AFI_IP6
) {
11966 snprintf(temp_buf
, sizeof(temp_buf
),
11969 * pow(2.0, -128 + 32));
11970 vty_out(vty
, "%30s: %s\n",
11971 "/32 equivalent %s\n",
11974 json_object_double_add(
11975 json
, "/32equivalent",
11976 (double)(ts
.total_space
11981 snprintf(temp_buf
, sizeof(temp_buf
),
11984 * pow(2.0, -128 + 48));
11985 vty_out(vty
, "%30s: %s\n",
11986 "/48 equivalent %s\n",
11989 json_object_double_add(
11990 json
, "/48equivalent",
11991 (double)(ts
.total_space
11997 snprintf(temp_buf
, sizeof(temp_buf
),
11999 ts
.total_space
* 100.
12001 vty_out(vty
, "%30s: %s\n",
12002 "% announced ", temp_buf
);
12004 json_object_double_add(
12005 json
, "%announced",
12006 (double)(ts
.total_space
* 100.
12010 snprintf(temp_buf
, sizeof(temp_buf
),
12013 * pow(2.0, -32 + 8));
12014 vty_out(vty
, "%30s: %s\n",
12015 "/8 equivalent ", temp_buf
);
12017 json_object_double_add(
12018 json
, "/8equivalent",
12019 (double)(ts
.total_space
12020 * pow(2.0, -32 + 8)));
12023 snprintf(temp_buf
, sizeof(temp_buf
),
12026 * pow(2.0, -32 + 24));
12027 vty_out(vty
, "%30s: %s\n",
12028 "/24 equivalent ", temp_buf
);
12030 json_object_double_add(
12031 json
, "/24equivalent",
12032 (double)(ts
.total_space
12033 * pow(2.0, -32 + 24)));
12039 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12041 vty_out(vty
, "%-30s: %s",
12042 table_stats_strs
[i
]
12043 [TABLE_STATS_IDX_VTY
],
12046 json_object_int_add(
12048 table_stats_strs
[i
]
12049 [TABLE_STATS_IDX_JSON
],
12054 vty_out(vty
, "\n");
12058 json_object_array_add(json_array
, json
);
12062 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12063 safi_t safi
, struct json_object
*json_array
)
12066 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12067 return CMD_SUCCESS
;
12070 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12082 PCOUNT_BPATH_SELECTED
,
12083 PCOUNT_PFCNT
, /* the figure we display to users */
12087 static const char *const pcount_strs
[] = {
12088 [PCOUNT_ADJ_IN
] = "Adj-in",
12089 [PCOUNT_DAMPED
] = "Damped",
12090 [PCOUNT_REMOVED
] = "Removed",
12091 [PCOUNT_HISTORY
] = "History",
12092 [PCOUNT_STALE
] = "Stale",
12093 [PCOUNT_VALID
] = "Valid",
12094 [PCOUNT_ALL
] = "All RIB",
12095 [PCOUNT_COUNTED
] = "PfxCt counted",
12096 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12097 [PCOUNT_PFCNT
] = "Useable",
12098 [PCOUNT_MAX
] = NULL
,
12101 struct peer_pcounts
{
12102 unsigned int count
[PCOUNT_MAX
];
12103 const struct peer
*peer
;
12104 const struct bgp_table
*table
;
12108 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12110 const struct bgp_adj_in
*ain
;
12111 const struct bgp_path_info
*pi
;
12112 const struct peer
*peer
= pc
->peer
;
12114 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12115 if (ain
->peer
== peer
)
12116 pc
->count
[PCOUNT_ADJ_IN
]++;
12118 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12120 if (pi
->peer
!= peer
)
12123 pc
->count
[PCOUNT_ALL
]++;
12125 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12126 pc
->count
[PCOUNT_DAMPED
]++;
12127 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12128 pc
->count
[PCOUNT_HISTORY
]++;
12129 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12130 pc
->count
[PCOUNT_REMOVED
]++;
12131 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12132 pc
->count
[PCOUNT_STALE
]++;
12133 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12134 pc
->count
[PCOUNT_VALID
]++;
12135 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12136 pc
->count
[PCOUNT_PFCNT
]++;
12137 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12138 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12140 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12141 pc
->count
[PCOUNT_COUNTED
]++;
12142 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12144 EC_LIB_DEVELOPMENT
,
12145 "Attempting to count but flags say it is unusable");
12147 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12149 EC_LIB_DEVELOPMENT
,
12150 "Not counted but flags say we should");
12155 static int bgp_peer_count_walker(struct thread
*t
)
12157 struct bgp_dest
*rn
, *rm
;
12158 const struct bgp_table
*table
;
12159 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12161 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12162 || pc
->safi
== SAFI_EVPN
) {
12163 /* Special handling for 2-level routing tables. */
12164 for (rn
= bgp_table_top(pc
->table
); rn
;
12165 rn
= bgp_route_next(rn
)) {
12166 table
= bgp_dest_get_bgp_table_info(rn
);
12168 for (rm
= bgp_table_top(table
); rm
;
12169 rm
= bgp_route_next(rm
))
12170 bgp_peer_count_proc(rm
, pc
);
12173 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
12174 bgp_peer_count_proc(rn
, pc
);
12179 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12180 safi_t safi
, bool use_json
)
12182 struct peer_pcounts pcounts
= {.peer
= peer
};
12184 json_object
*json
= NULL
;
12185 json_object
*json_loop
= NULL
;
12188 json
= json_object_new_object();
12189 json_loop
= json_object_new_object();
12192 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
12193 || !peer
->bgp
->rib
[afi
][safi
]) {
12195 json_object_string_add(
12197 "No such neighbor or address family");
12198 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12199 json_object_free(json
);
12201 vty_out(vty
, "%% No such neighbor or address family\n");
12203 return CMD_WARNING
;
12206 memset(&pcounts
, 0, sizeof(pcounts
));
12207 pcounts
.peer
= peer
;
12208 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
12209 pcounts
.safi
= safi
;
12211 /* in-place call via thread subsystem so as to record execution time
12212 * stats for the thread-walk (i.e. ensure this can't be blamed on
12213 * on just vty_read()).
12215 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
12218 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
12219 json_object_string_add(json
, "multiProtocol",
12220 get_afi_safi_str(afi
, safi
, true));
12221 json_object_int_add(json
, "pfxCounter",
12222 peer
->pcount
[afi
][safi
]);
12224 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12225 json_object_int_add(json_loop
, pcount_strs
[i
],
12228 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12230 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12231 json_object_string_add(json
, "pfxctDriftFor",
12233 json_object_string_add(
12234 json
, "recommended",
12235 "Please report this bug, with the above command output");
12237 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12238 json
, JSON_C_TO_STRING_PRETTY
));
12239 json_object_free(json
);
12243 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12244 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12245 peer
->hostname
, peer
->host
,
12246 get_afi_safi_str(afi
, safi
, false));
12248 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12249 get_afi_safi_str(afi
, safi
, false));
12252 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12253 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12255 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12256 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12259 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12260 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12262 "Please report this bug, with the above command output\n");
12266 return CMD_SUCCESS
;
12269 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12270 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12271 "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]",
12275 BGP_INSTANCE_HELP_STR
12278 "Detailed information on TCP and BGP neighbor connections\n"
12279 "Neighbor to display information about\n"
12280 "Neighbor to display information about\n"
12281 "Neighbor on BGP configured interface\n"
12282 "Display detailed prefix count information\n"
12285 afi_t afi
= AFI_IP6
;
12286 safi_t safi
= SAFI_UNICAST
;
12289 struct bgp
*bgp
= NULL
;
12290 bool uj
= use_json(argc
, argv
);
12295 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12298 return CMD_WARNING
;
12300 argv_find(argv
, argc
, "neighbors", &idx
);
12301 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12303 return CMD_WARNING
;
12305 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12308 #ifdef KEEP_OLD_VPN_COMMANDS
12309 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12310 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12311 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12316 "Display information about all VPNv4 NLRIs\n"
12317 "Detailed information on TCP and BGP neighbor connections\n"
12318 "Neighbor to display information about\n"
12319 "Neighbor to display information about\n"
12320 "Neighbor on BGP configured interface\n"
12321 "Display detailed prefix count information\n"
12326 bool uj
= use_json(argc
, argv
);
12328 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12330 return CMD_WARNING
;
12332 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12335 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12336 show_ip_bgp_vpn_all_route_prefix_cmd
,
12337 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12342 "Display information about all VPNv4 NLRIs\n"
12343 "Network in the BGP routing table to display\n"
12344 "Network in the BGP routing table to display\n"
12348 char *network
= NULL
;
12349 struct bgp
*bgp
= bgp_get_default();
12351 vty_out(vty
, "Can't find default instance\n");
12352 return CMD_WARNING
;
12355 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12356 network
= argv
[idx
]->arg
;
12357 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12358 network
= argv
[idx
]->arg
;
12360 vty_out(vty
, "Unable to figure out Network\n");
12361 return CMD_WARNING
;
12364 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12365 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12367 #endif /* KEEP_OLD_VPN_COMMANDS */
12369 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12370 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12371 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12376 "Network in the BGP routing table to display\n"
12377 "Network in the BGP routing table to display\n"
12378 "Network in the BGP routing table to display\n"
12379 "Network in the BGP routing table to display\n"
12383 char *network
= NULL
;
12384 int prefix_check
= 0;
12386 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12387 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12388 network
= argv
[idx
]->arg
;
12389 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12390 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12391 network
= argv
[idx
]->arg
;
12394 vty_out(vty
, "Unable to figure out Network\n");
12395 return CMD_WARNING
;
12397 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12398 prefix_check
, BGP_PATH_SHOW_ALL
,
12399 use_json(argc
, argv
));
12402 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12403 struct bgp_table
*table
, int *header1
,
12404 int *header2
, json_object
*json
,
12405 json_object
*json_scode
,
12406 json_object
*json_ocode
, bool wide
)
12408 uint64_t version
= table
? table
->version
: 0;
12412 json_object_int_add(json
, "bgpTableVersion", version
);
12413 json_object_string_add(json
, "bgpLocalRouterId",
12414 inet_ntoa(bgp
->router_id
));
12415 json_object_int_add(json
, "defaultLocPrf",
12416 bgp
->default_local_pref
);
12417 json_object_int_add(json
, "localAS", bgp
->as
);
12418 json_object_object_add(json
, "bgpStatusCodes",
12420 json_object_object_add(json
, "bgpOriginCodes",
12424 "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12425 version
, inet_ntoa(bgp
->router_id
));
12426 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12427 vty_out(vty
, "%s", VRFID_NONE_STR
);
12429 vty_out(vty
, "%u", bgp
->vrf_id
);
12430 vty_out(vty
, "\n");
12431 vty_out(vty
, "Default local pref %u, ",
12432 bgp
->default_local_pref
);
12433 vty_out(vty
, "local AS %u\n", bgp
->as
);
12434 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12435 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12436 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12442 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
12443 : BGP_SHOW_HEADER
));
12448 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12449 safi_t safi
, enum bgp_show_adj_route_type type
,
12450 const char *rmap_name
, json_object
*json
,
12451 uint8_t show_flags
)
12453 struct bgp_table
*table
;
12454 struct bgp_adj_in
*ain
;
12455 struct bgp_adj_out
*adj
;
12456 unsigned long output_count
= 0;
12457 unsigned long filtered_count
= 0;
12458 struct bgp_dest
*dest
;
12464 struct update_subgroup
*subgrp
;
12465 json_object
*json_scode
= NULL
;
12466 json_object
*json_ocode
= NULL
;
12467 json_object
*json_ar
= NULL
;
12468 struct peer_af
*paf
;
12469 bool route_filtered
;
12470 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12471 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12474 json_scode
= json_object_new_object();
12475 json_ocode
= json_object_new_object();
12476 json_ar
= json_object_new_object();
12478 json_object_string_add(json_scode
, "suppressed", "s");
12479 json_object_string_add(json_scode
, "damped", "d");
12480 json_object_string_add(json_scode
, "history", "h");
12481 json_object_string_add(json_scode
, "valid", "*");
12482 json_object_string_add(json_scode
, "best", ">");
12483 json_object_string_add(json_scode
, "multipath", "=");
12484 json_object_string_add(json_scode
, "internal", "i");
12485 json_object_string_add(json_scode
, "ribFailure", "r");
12486 json_object_string_add(json_scode
, "stale", "S");
12487 json_object_string_add(json_scode
, "removed", "R");
12489 json_object_string_add(json_ocode
, "igp", "i");
12490 json_object_string_add(json_ocode
, "egp", "e");
12491 json_object_string_add(json_ocode
, "incomplete", "?");
12498 json_object_string_add(json
, "alert", "no BGP");
12499 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12500 json_object_free(json
);
12502 vty_out(vty
, "%% No bgp\n");
12506 /* labeled-unicast routes live in the unicast table */
12507 if (safi
== SAFI_LABELED_UNICAST
)
12508 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
12510 table
= bgp
->rib
[afi
][safi
];
12512 output_count
= filtered_count
= 0;
12513 subgrp
= peer_subgroup(peer
, afi
, safi
);
12515 if (type
== bgp_show_adj_route_advertised
&& subgrp
12516 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
12518 json_object_int_add(json
, "bgpTableVersion",
12520 json_object_string_add(json
, "bgpLocalRouterId",
12521 inet_ntoa(bgp
->router_id
));
12522 json_object_int_add(json
, "defaultLocPrf",
12523 bgp
->default_local_pref
);
12524 json_object_int_add(json
, "localAS", bgp
->as
);
12525 json_object_object_add(json
, "bgpStatusCodes",
12527 json_object_object_add(json
, "bgpOriginCodes",
12529 json_object_string_add(
12530 json
, "bgpOriginatingDefaultNetwork",
12531 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12533 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
12534 table
->version
, inet_ntoa(bgp
->router_id
));
12535 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12536 vty_out(vty
, "%s", VRFID_NONE_STR
);
12538 vty_out(vty
, "%u", bgp
->vrf_id
);
12539 vty_out(vty
, "\n");
12540 vty_out(vty
, "Default local pref %u, ",
12541 bgp
->default_local_pref
);
12542 vty_out(vty
, "local AS %u\n", bgp
->as
);
12543 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
12544 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
12545 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
12547 vty_out(vty
, "Originating default network %s\n\n",
12548 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
12553 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
12554 if (type
== bgp_show_adj_route_received
12555 || type
== bgp_show_adj_route_filtered
) {
12556 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
12557 if (ain
->peer
!= peer
)
12560 show_adj_route_header(
12561 vty
, bgp
, table
, &header1
, &header2
,
12562 json
, json_scode
, json_ocode
, wide
);
12565 route_filtered
= false;
12567 /* Filter prefix using distribute list,
12568 * filter list or prefix list
12570 const struct prefix
*rn_p
=
12571 bgp_dest_get_prefix(dest
);
12572 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
12575 route_filtered
= true;
12577 /* Filter prefix using route-map */
12578 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
12579 safi
, rmap_name
, NULL
,
12582 if (type
== bgp_show_adj_route_filtered
&&
12583 !route_filtered
&& ret
!= RMAP_DENY
) {
12584 bgp_attr_undup(&attr
, ain
->attr
);
12588 if (type
== bgp_show_adj_route_received
&&
12589 (route_filtered
|| ret
== RMAP_DENY
))
12592 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
12593 use_json
, json_ar
, wide
);
12594 bgp_attr_undup(&attr
, ain
->attr
);
12597 } else if (type
== bgp_show_adj_route_advertised
) {
12598 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
12599 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
12600 if (paf
->peer
!= peer
|| !adj
->attr
)
12603 show_adj_route_header(
12604 vty
, bgp
, table
, &header1
,
12605 &header2
, json
, json_scode
,
12608 const struct prefix
*rn_p
=
12609 bgp_dest_get_prefix(dest
);
12612 ret
= bgp_output_modifier(
12613 peer
, rn_p
, &attr
, afi
, safi
,
12616 if (ret
!= RMAP_DENY
) {
12618 vty
, rn_p
, &attr
, safi
,
12626 bgp_attr_undup(&attr
, adj
->attr
);
12628 } else if (type
== bgp_show_adj_route_bestpath
) {
12629 struct bgp_path_info
*pi
;
12631 show_adj_route_header(vty
, bgp
, table
, &header1
,
12632 &header2
, json
, json_scode
,
12635 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
12637 if (pi
->peer
!= peer
)
12640 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12643 route_vty_out_tmp(vty
,
12644 bgp_dest_get_prefix(dest
),
12645 pi
->attr
, safi
, use_json
,
12653 json_object_object_add(json
, "advertisedRoutes", json_ar
);
12654 json_object_int_add(json
, "totalPrefixCounter", output_count
);
12655 json_object_int_add(json
, "filteredPrefixCounter",
12658 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12659 json
, JSON_C_TO_STRING_PRETTY
));
12661 if (!output_count
&& !filtered_count
) {
12662 json_object_free(json_scode
);
12663 json_object_free(json_ocode
);
12666 json_object_free(json
);
12667 } else if (output_count
> 0) {
12668 if (filtered_count
> 0)
12670 "\nTotal number of prefixes %ld (%ld filtered)\n",
12671 output_count
, filtered_count
);
12673 vty_out(vty
, "\nTotal number of prefixes %ld\n",
12678 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12679 safi_t safi
, enum bgp_show_adj_route_type type
,
12680 const char *rmap_name
, uint8_t show_flags
)
12682 json_object
*json
= NULL
;
12683 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12686 json
= json_object_new_object();
12688 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12690 json_object_string_add(
12692 "No such neighbor or address family");
12693 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12694 json_object_free(json
);
12696 vty_out(vty
, "%% No such neighbor or address family\n");
12698 return CMD_WARNING
;
12701 if ((type
== bgp_show_adj_route_received
12702 || type
== bgp_show_adj_route_filtered
)
12703 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
12704 PEER_FLAG_SOFT_RECONFIG
)) {
12706 json_object_string_add(
12708 "Inbound soft reconfiguration not enabled");
12709 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12710 json_object_free(json
);
12713 "%% Inbound soft reconfiguration not enabled\n");
12715 return CMD_WARNING
;
12718 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, json
, show_flags
);
12720 return CMD_SUCCESS
;
12723 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
12724 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
12725 "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]",
12729 BGP_INSTANCE_HELP_STR
12731 BGP_SAFI_WITH_LABEL_HELP_STR
12732 "Detailed information on TCP and BGP neighbor connections\n"
12733 "Neighbor to display information about\n"
12734 "Neighbor to display information about\n"
12735 "Neighbor on BGP configured interface\n"
12736 "Display the routes selected by best path\n"
12738 "Increase table width for longer prefixes\n")
12740 afi_t afi
= AFI_IP6
;
12741 safi_t safi
= SAFI_UNICAST
;
12742 char *rmap_name
= NULL
;
12743 char *peerstr
= NULL
;
12744 struct bgp
*bgp
= NULL
;
12746 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
12748 uint8_t show_flags
= 0;
12751 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12754 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12756 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12760 return CMD_WARNING
;
12762 argv_find(argv
, argc
, "neighbors", &idx
);
12763 peerstr
= argv
[++idx
]->arg
;
12765 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12767 return CMD_WARNING
;
12769 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12773 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
12774 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
12775 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
12779 BGP_INSTANCE_HELP_STR
12781 BGP_SAFI_WITH_LABEL_HELP_STR
12782 "Display the entries for all address families\n"
12783 "Detailed information on TCP and BGP neighbor connections\n"
12784 "Neighbor to display information about\n"
12785 "Neighbor to display information about\n"
12786 "Neighbor on BGP configured interface\n"
12787 "Display the routes advertised to a BGP neighbor\n"
12788 "Display the received routes from neighbor\n"
12789 "Display the filtered routes received from neighbor\n"
12790 "Route-map to modify the attributes\n"
12791 "Name of the route map\n"
12793 "Increase table width for longer prefixes\n")
12795 afi_t afi
= AFI_IP6
;
12796 safi_t safi
= SAFI_UNICAST
;
12797 char *rmap_name
= NULL
;
12798 char *peerstr
= NULL
;
12799 struct bgp
*bgp
= NULL
;
12801 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
12804 uint8_t show_flags
= 0;
12808 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12812 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
12813 if (argv_find(argv
, argc
, "ipv4", &idx
))
12814 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
12816 if (argv_find(argv
, argc
, "ipv6", &idx
))
12817 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
12821 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12823 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12826 return CMD_WARNING
;
12828 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12829 argv_find(argv
, argc
, "neighbors", &idx
);
12830 peerstr
= argv
[++idx
]->arg
;
12832 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12834 return CMD_WARNING
;
12836 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
12837 type
= bgp_show_adj_route_advertised
;
12838 else if (argv_find(argv
, argc
, "received-routes", &idx
))
12839 type
= bgp_show_adj_route_received
;
12840 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
12841 type
= bgp_show_adj_route_filtered
;
12843 if (argv_find(argv
, argc
, "route-map", &idx
))
12844 rmap_name
= argv
[++idx
]->arg
;
12847 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12850 vty_out(vty
, "{\n");
12852 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
12853 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
12854 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
12856 FOREACH_SAFI (safi
) {
12857 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12861 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12868 vty_out(vty
, ",\n");
12869 vty_out(vty
, "\"%s\":",
12870 get_afi_safi_str(afi
, safi
, true));
12872 vty_out(vty
, "\nFor address family: %s\n",
12873 get_afi_safi_str(afi
, safi
, false));
12875 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12879 FOREACH_AFI_SAFI (afi
, safi
) {
12880 if (strmatch(get_afi_safi_str(afi
, safi
, true),
12884 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
12891 vty_out(vty
, ",\n");
12892 vty_out(vty
, "\"%s\":",
12893 get_afi_safi_str(afi
, safi
, true));
12895 vty_out(vty
, "\nFor address family: %s\n",
12896 get_afi_safi_str(afi
, safi
, false));
12898 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
12903 vty_out(vty
, "}\n");
12905 return CMD_SUCCESS
;
12908 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
12909 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
12910 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
12916 "Address Family modifier\n"
12917 "Detailed information on TCP and BGP neighbor connections\n"
12918 "Neighbor to display information about\n"
12919 "Neighbor to display information about\n"
12920 "Neighbor on BGP configured interface\n"
12921 "Display information received from a BGP neighbor\n"
12922 "Display the prefixlist filter\n"
12925 afi_t afi
= AFI_IP6
;
12926 safi_t safi
= SAFI_UNICAST
;
12927 char *peerstr
= NULL
;
12930 union sockunion su
;
12936 /* show [ip] bgp */
12937 if (argv_find(argv
, argc
, "ip", &idx
))
12939 /* [<ipv4|ipv6> [unicast]] */
12940 if (argv_find(argv
, argc
, "ipv4", &idx
))
12942 if (argv_find(argv
, argc
, "ipv6", &idx
))
12944 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12945 argv_find(argv
, argc
, "neighbors", &idx
);
12946 peerstr
= argv
[++idx
]->arg
;
12948 bool uj
= use_json(argc
, argv
);
12950 ret
= str2sockunion(peerstr
, &su
);
12952 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
12955 vty_out(vty
, "{}\n");
12958 "%% Malformed address or name: %s\n",
12960 return CMD_WARNING
;
12963 peer
= peer_lookup(NULL
, &su
);
12966 vty_out(vty
, "{}\n");
12968 vty_out(vty
, "No peer\n");
12969 return CMD_WARNING
;
12973 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
12974 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
12977 vty_out(vty
, "Address Family: %s\n",
12978 get_afi_safi_str(afi
, safi
, false));
12979 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
12982 vty_out(vty
, "{}\n");
12984 vty_out(vty
, "No functional output\n");
12987 return CMD_SUCCESS
;
12990 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
12991 afi_t afi
, safi_t safi
,
12992 enum bgp_show_type type
, bool use_json
)
12994 uint8_t show_flags
= 0;
12997 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12999 /* labeled-unicast routes live in the unicast table */
13000 if (safi
== SAFI_LABELED_UNICAST
)
13001 safi
= SAFI_UNICAST
;
13003 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13005 json_object
*json_no
= NULL
;
13006 json_no
= json_object_new_object();
13007 json_object_string_add(
13008 json_no
, "warning",
13009 "No such neighbor or address family");
13010 vty_out(vty
, "%s\n",
13011 json_object_to_json_string(json_no
));
13012 json_object_free(json_no
);
13014 vty_out(vty
, "%% No such neighbor or address family\n");
13015 return CMD_WARNING
;
13018 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
13021 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13022 show_ip_bgp_flowspec_routes_detailed_cmd
,
13023 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13027 BGP_INSTANCE_HELP_STR
13030 "Detailed information on flowspec entries\n"
13033 afi_t afi
= AFI_IP
;
13034 safi_t safi
= SAFI_UNICAST
;
13035 struct bgp
*bgp
= NULL
;
13037 bool uj
= use_json(argc
, argv
);
13038 uint8_t show_flags
= 0;
13042 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13045 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13048 return CMD_WARNING
;
13050 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13054 DEFUN (show_ip_bgp_neighbor_routes
,
13055 show_ip_bgp_neighbor_routes_cmd
,
13056 "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]",
13060 BGP_INSTANCE_HELP_STR
13062 BGP_SAFI_WITH_LABEL_HELP_STR
13063 "Detailed information on TCP and BGP neighbor connections\n"
13064 "Neighbor to display information about\n"
13065 "Neighbor to display information about\n"
13066 "Neighbor on BGP configured interface\n"
13067 "Display flap statistics of the routes learned from neighbor\n"
13068 "Display the dampened routes received from neighbor\n"
13069 "Display routes learned from neighbor\n"
13072 char *peerstr
= NULL
;
13073 struct bgp
*bgp
= NULL
;
13074 afi_t afi
= AFI_IP6
;
13075 safi_t safi
= SAFI_UNICAST
;
13077 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
13079 bool uj
= use_json(argc
, argv
);
13084 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13087 return CMD_WARNING
;
13089 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13090 argv_find(argv
, argc
, "neighbors", &idx
);
13091 peerstr
= argv
[++idx
]->arg
;
13093 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13095 return CMD_WARNING
;
13097 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
13098 sh_type
= bgp_show_type_flap_neighbor
;
13099 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
13100 sh_type
= bgp_show_type_damp_neighbor
;
13101 else if (argv_find(argv
, argc
, "routes", &idx
))
13102 sh_type
= bgp_show_type_neighbor
;
13104 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
13107 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
13109 struct bgp_distance
{
13110 /* Distance value for the IP source prefix. */
13113 /* Name of the access-list to be matched. */
13117 DEFUN (show_bgp_afi_vpn_rd_route
,
13118 show_bgp_afi_vpn_rd_route_cmd
,
13119 "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]",
13123 "Address Family modifier\n"
13124 "Display information for a route distinguisher\n"
13125 "Route Distinguisher\n"
13126 "Network in the BGP routing table to display\n"
13127 "Network in the BGP routing table to display\n"
13131 struct prefix_rd prd
;
13132 afi_t afi
= AFI_MAX
;
13135 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
13136 vty_out(vty
, "%% Malformed Address Family\n");
13137 return CMD_WARNING
;
13140 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
13142 vty_out(vty
, "%% Malformed Route Distinguisher\n");
13143 return CMD_WARNING
;
13146 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
13147 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
13150 static struct bgp_distance
*bgp_distance_new(void)
13152 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
13155 static void bgp_distance_free(struct bgp_distance
*bdistance
)
13157 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
13160 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
13161 const char *ip_str
, const char *access_list_str
)
13168 struct bgp_dest
*dest
;
13169 struct bgp_distance
*bdistance
;
13171 afi
= bgp_node_afi(vty
);
13172 safi
= bgp_node_safi(vty
);
13174 ret
= str2prefix(ip_str
, &p
);
13176 vty_out(vty
, "Malformed prefix\n");
13177 return CMD_WARNING_CONFIG_FAILED
;
13180 distance
= atoi(distance_str
);
13182 /* Get BGP distance node. */
13183 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
13184 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13186 bgp_dest_unlock_node(dest
);
13188 bdistance
= bgp_distance_new();
13189 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
13192 /* Set distance value. */
13193 bdistance
->distance
= distance
;
13195 /* Reset access-list configuration. */
13196 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13197 if (access_list_str
)
13198 bdistance
->access_list
=
13199 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
13201 return CMD_SUCCESS
;
13204 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
13205 const char *ip_str
, const char *access_list_str
)
13212 struct bgp_dest
*dest
;
13213 struct bgp_distance
*bdistance
;
13215 afi
= bgp_node_afi(vty
);
13216 safi
= bgp_node_safi(vty
);
13218 ret
= str2prefix(ip_str
, &p
);
13220 vty_out(vty
, "Malformed prefix\n");
13221 return CMD_WARNING_CONFIG_FAILED
;
13224 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13226 vty_out(vty
, "Can't find specified prefix\n");
13227 return CMD_WARNING_CONFIG_FAILED
;
13230 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13231 distance
= atoi(distance_str
);
13233 if (bdistance
->distance
!= distance
) {
13234 vty_out(vty
, "Distance does not match configured\n");
13235 return CMD_WARNING_CONFIG_FAILED
;
13238 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13239 bgp_distance_free(bdistance
);
13241 bgp_dest_set_bgp_path_info(dest
, NULL
);
13242 bgp_dest_unlock_node(dest
);
13243 bgp_dest_unlock_node(dest
);
13245 return CMD_SUCCESS
;
13248 /* Apply BGP information to distance method. */
13249 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13250 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13252 struct bgp_dest
*dest
;
13255 struct bgp_distance
*bdistance
;
13256 struct access_list
*alist
;
13257 struct bgp_static
*bgp_static
;
13262 peer
= pinfo
->peer
;
13264 if (pinfo
->attr
->distance
)
13265 return pinfo
->attr
->distance
;
13267 /* Check source address. */
13268 sockunion2hostprefix(&peer
->su
, &q
);
13269 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13271 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13272 bgp_dest_unlock_node(dest
);
13274 if (bdistance
->access_list
) {
13275 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13277 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13278 return bdistance
->distance
;
13280 return bdistance
->distance
;
13283 /* Backdoor check. */
13284 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
13286 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13287 bgp_dest_unlock_node(dest
);
13289 if (bgp_static
->backdoor
) {
13290 if (bgp
->distance_local
[afi
][safi
])
13291 return bgp
->distance_local
[afi
][safi
];
13293 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13297 if (peer
->sort
== BGP_PEER_EBGP
) {
13298 if (bgp
->distance_ebgp
[afi
][safi
])
13299 return bgp
->distance_ebgp
[afi
][safi
];
13300 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
13302 if (bgp
->distance_ibgp
[afi
][safi
])
13303 return bgp
->distance_ibgp
[afi
][safi
];
13304 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13308 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13309 * we should tell ZEBRA update the routes for a specific
13310 * AFI/SAFI to reflect changes in RIB.
13312 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
13314 safi_t update_safi
)
13319 FOREACH_AFI_SAFI (afi
, safi
) {
13320 if (!bgp_fibupd_safi(safi
))
13323 if (afi
!= update_afi
&& safi
!= update_safi
)
13326 if (BGP_DEBUG(zebra
, ZEBRA
))
13328 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13329 __func__
, afi
, safi
);
13330 bgp_zebra_announce_table(bgp
, afi
, safi
);
13334 DEFUN (bgp_distance
,
13336 "distance bgp (1-255) (1-255) (1-255)",
13337 "Define an administrative distance\n"
13339 "Distance for routes external to the AS\n"
13340 "Distance for routes internal to the AS\n"
13341 "Distance for local routes\n")
13343 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13344 int idx_number
= 2;
13345 int idx_number_2
= 3;
13346 int idx_number_3
= 4;
13347 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
13348 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
13349 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
13353 afi
= bgp_node_afi(vty
);
13354 safi
= bgp_node_safi(vty
);
13356 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
13357 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
13358 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
13359 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
13360 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
13361 bgp
->distance_local
[afi
][safi
] = distance_local
;
13362 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13364 return CMD_SUCCESS
;
13367 DEFUN (no_bgp_distance
,
13368 no_bgp_distance_cmd
,
13369 "no distance bgp [(1-255) (1-255) (1-255)]",
13371 "Define an administrative distance\n"
13373 "Distance for routes external to the AS\n"
13374 "Distance for routes internal to the AS\n"
13375 "Distance for local routes\n")
13377 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13381 afi
= bgp_node_afi(vty
);
13382 safi
= bgp_node_safi(vty
);
13384 if (bgp
->distance_ebgp
[afi
][safi
] != 0
13385 || bgp
->distance_ibgp
[afi
][safi
] != 0
13386 || bgp
->distance_local
[afi
][safi
] != 0) {
13387 bgp
->distance_ebgp
[afi
][safi
] = 0;
13388 bgp
->distance_ibgp
[afi
][safi
] = 0;
13389 bgp
->distance_local
[afi
][safi
] = 0;
13390 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
13392 return CMD_SUCCESS
;
13396 DEFUN (bgp_distance_source
,
13397 bgp_distance_source_cmd
,
13398 "distance (1-255) A.B.C.D/M",
13399 "Define an administrative distance\n"
13400 "Administrative distance\n"
13401 "IP source prefix\n")
13403 int idx_number
= 1;
13404 int idx_ipv4_prefixlen
= 2;
13405 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13406 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13407 return CMD_SUCCESS
;
13410 DEFUN (no_bgp_distance_source
,
13411 no_bgp_distance_source_cmd
,
13412 "no distance (1-255) A.B.C.D/M",
13414 "Define an administrative distance\n"
13415 "Administrative distance\n"
13416 "IP source prefix\n")
13418 int idx_number
= 2;
13419 int idx_ipv4_prefixlen
= 3;
13420 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13421 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
13422 return CMD_SUCCESS
;
13425 DEFUN (bgp_distance_source_access_list
,
13426 bgp_distance_source_access_list_cmd
,
13427 "distance (1-255) A.B.C.D/M WORD",
13428 "Define an administrative distance\n"
13429 "Administrative distance\n"
13430 "IP source prefix\n"
13431 "Access list name\n")
13433 int idx_number
= 1;
13434 int idx_ipv4_prefixlen
= 2;
13436 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
13437 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13438 return CMD_SUCCESS
;
13441 DEFUN (no_bgp_distance_source_access_list
,
13442 no_bgp_distance_source_access_list_cmd
,
13443 "no distance (1-255) A.B.C.D/M WORD",
13445 "Define an administrative distance\n"
13446 "Administrative distance\n"
13447 "IP source prefix\n"
13448 "Access list name\n")
13450 int idx_number
= 2;
13451 int idx_ipv4_prefixlen
= 3;
13453 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
13454 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
13455 return CMD_SUCCESS
;
13458 DEFUN (ipv6_bgp_distance_source
,
13459 ipv6_bgp_distance_source_cmd
,
13460 "distance (1-255) X:X::X:X/M",
13461 "Define an administrative distance\n"
13462 "Administrative distance\n"
13463 "IP source prefix\n")
13465 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
13466 return CMD_SUCCESS
;
13469 DEFUN (no_ipv6_bgp_distance_source
,
13470 no_ipv6_bgp_distance_source_cmd
,
13471 "no distance (1-255) X:X::X:X/M",
13473 "Define an administrative distance\n"
13474 "Administrative distance\n"
13475 "IP source prefix\n")
13477 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
13478 return CMD_SUCCESS
;
13481 DEFUN (ipv6_bgp_distance_source_access_list
,
13482 ipv6_bgp_distance_source_access_list_cmd
,
13483 "distance (1-255) X:X::X:X/M WORD",
13484 "Define an administrative distance\n"
13485 "Administrative distance\n"
13486 "IP source prefix\n"
13487 "Access list name\n")
13489 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
13490 return CMD_SUCCESS
;
13493 DEFUN (no_ipv6_bgp_distance_source_access_list
,
13494 no_ipv6_bgp_distance_source_access_list_cmd
,
13495 "no distance (1-255) X:X::X:X/M WORD",
13497 "Define an administrative distance\n"
13498 "Administrative distance\n"
13499 "IP source prefix\n"
13500 "Access list name\n")
13502 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
13503 return CMD_SUCCESS
;
13506 DEFUN (bgp_damp_set
,
13508 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13509 "BGP Specific commands\n"
13510 "Enable route-flap dampening\n"
13511 "Half-life time for the penalty\n"
13512 "Value to start reusing a route\n"
13513 "Value to start suppressing a route\n"
13514 "Maximum duration to suppress a stable route\n")
13516 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13517 int idx_half_life
= 2;
13519 int idx_suppress
= 4;
13520 int idx_max_suppress
= 5;
13521 int half
= DEFAULT_HALF_LIFE
* 60;
13522 int reuse
= DEFAULT_REUSE
;
13523 int suppress
= DEFAULT_SUPPRESS
;
13524 int max
= 4 * half
;
13527 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13528 reuse
= atoi(argv
[idx_reuse
]->arg
);
13529 suppress
= atoi(argv
[idx_suppress
]->arg
);
13530 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
13531 } else if (argc
== 3) {
13532 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
13537 * These can't be 0 but our SA doesn't understand the
13538 * way our cli is constructed
13542 if (suppress
< reuse
) {
13544 "Suppress value cannot be less than reuse value \n");
13548 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
13549 reuse
, suppress
, max
);
13552 DEFUN (bgp_damp_unset
,
13553 bgp_damp_unset_cmd
,
13554 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
13556 "BGP Specific commands\n"
13557 "Enable route-flap dampening\n"
13558 "Half-life time for the penalty\n"
13559 "Value to start reusing a route\n"
13560 "Value to start suppressing a route\n"
13561 "Maximum duration to suppress a stable route\n")
13563 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
13564 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
13567 /* Display specified route of BGP table. */
13568 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
13569 const char *ip_str
, afi_t afi
, safi_t safi
,
13570 struct prefix_rd
*prd
, int prefix_check
)
13573 struct prefix match
;
13574 struct bgp_dest
*dest
;
13575 struct bgp_dest
*rm
;
13576 struct bgp_path_info
*pi
;
13577 struct bgp_path_info
*pi_temp
;
13579 struct bgp_table
*table
;
13581 /* BGP structure lookup. */
13583 bgp
= bgp_lookup_by_name(view_name
);
13585 vty_out(vty
, "%% Can't find BGP instance %s\n",
13587 return CMD_WARNING
;
13590 bgp
= bgp_get_default();
13592 vty_out(vty
, "%% No BGP process is configured\n");
13593 return CMD_WARNING
;
13597 /* Check IP address argument. */
13598 ret
= str2prefix(ip_str
, &match
);
13600 vty_out(vty
, "%% address is malformed\n");
13601 return CMD_WARNING
;
13604 match
.family
= afi2family(afi
);
13606 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13607 || (safi
== SAFI_EVPN
)) {
13608 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
13609 dest
= bgp_route_next(dest
)) {
13610 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13612 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
13614 table
= bgp_dest_get_bgp_table_info(dest
);
13617 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
13620 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
13623 || rm_p
->prefixlen
== match
.prefixlen
) {
13624 pi
= bgp_dest_get_bgp_path_info(rm
);
13626 if (pi
->extra
&& pi
->extra
->damp_info
) {
13627 pi_temp
= pi
->next
;
13628 bgp_damp_info_free(
13629 pi
->extra
->damp_info
,
13637 bgp_dest_unlock_node(rm
);
13640 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
13642 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
13645 || dest_p
->prefixlen
== match
.prefixlen
) {
13646 pi
= bgp_dest_get_bgp_path_info(dest
);
13648 if (pi
->extra
&& pi
->extra
->damp_info
) {
13649 pi_temp
= pi
->next
;
13650 bgp_damp_info_free(
13651 pi
->extra
->damp_info
,
13659 bgp_dest_unlock_node(dest
);
13663 return CMD_SUCCESS
;
13666 DEFUN (clear_ip_bgp_dampening
,
13667 clear_ip_bgp_dampening_cmd
,
13668 "clear ip bgp dampening",
13672 "Clear route flap dampening information\n")
13674 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
13675 return CMD_SUCCESS
;
13678 DEFUN (clear_ip_bgp_dampening_prefix
,
13679 clear_ip_bgp_dampening_prefix_cmd
,
13680 "clear ip bgp dampening A.B.C.D/M",
13684 "Clear route flap dampening information\n"
13687 int idx_ipv4_prefixlen
= 4;
13688 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
13689 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
13692 DEFUN (clear_ip_bgp_dampening_address
,
13693 clear_ip_bgp_dampening_address_cmd
,
13694 "clear ip bgp dampening A.B.C.D",
13698 "Clear route flap dampening information\n"
13699 "Network to clear damping information\n")
13702 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
13703 SAFI_UNICAST
, NULL
, 0);
13706 DEFUN (clear_ip_bgp_dampening_address_mask
,
13707 clear_ip_bgp_dampening_address_mask_cmd
,
13708 "clear ip bgp dampening A.B.C.D A.B.C.D",
13712 "Clear route flap dampening information\n"
13713 "Network to clear damping information\n"
13717 int idx_ipv4_2
= 5;
13719 char prefix_str
[BUFSIZ
];
13721 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
13724 vty_out(vty
, "%% Inconsistent address and mask\n");
13725 return CMD_WARNING
;
13728 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
13732 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
13734 struct vty
*vty
= arg
;
13735 struct peer
*peer
= bucket
->data
;
13736 char buf
[SU_ADDRSTRLEN
];
13738 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
13739 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
13742 DEFUN (show_bgp_listeners
,
13743 show_bgp_listeners_cmd
,
13744 "show bgp listeners",
13747 "Display Listen Sockets and who created them\n")
13749 bgp_dump_listener_info(vty
);
13751 return CMD_SUCCESS
;
13754 DEFUN (show_bgp_peerhash
,
13755 show_bgp_peerhash_cmd
,
13756 "show bgp peerhash",
13759 "Display information about the BGP peerhash\n")
13761 struct list
*instances
= bm
->bgp
;
13762 struct listnode
*node
;
13765 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
13766 vty_out(vty
, "BGP: %s\n", bgp
->name
);
13767 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
13771 return CMD_SUCCESS
;
13774 /* also used for encap safi */
13775 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
13776 afi_t afi
, safi_t safi
)
13778 struct bgp_dest
*pdest
;
13779 struct bgp_dest
*dest
;
13780 struct bgp_table
*table
;
13781 const struct prefix
*p
;
13782 const struct prefix_rd
*prd
;
13783 struct bgp_static
*bgp_static
;
13784 mpls_label_t label
;
13785 char buf
[SU_ADDRSTRLEN
];
13786 char rdbuf
[RD_ADDRSTRLEN
];
13788 /* Network configuration. */
13789 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13790 pdest
= bgp_route_next(pdest
)) {
13791 table
= bgp_dest_get_bgp_table_info(pdest
);
13795 for (dest
= bgp_table_top(table
); dest
;
13796 dest
= bgp_route_next(dest
)) {
13797 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13798 if (bgp_static
== NULL
)
13801 p
= bgp_dest_get_prefix(dest
);
13802 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13805 /* "network" configuration display. */
13806 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13807 label
= decode_label(&bgp_static
->label
);
13809 vty_out(vty
, " network %s/%d rd %s",
13810 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
13812 p
->prefixlen
, rdbuf
);
13813 if (safi
== SAFI_MPLS_VPN
)
13814 vty_out(vty
, " label %u", label
);
13816 if (bgp_static
->rmap
.name
)
13817 vty_out(vty
, " route-map %s",
13818 bgp_static
->rmap
.name
);
13820 if (bgp_static
->backdoor
)
13821 vty_out(vty
, " backdoor");
13823 vty_out(vty
, "\n");
13828 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
13829 afi_t afi
, safi_t safi
)
13831 struct bgp_dest
*pdest
;
13832 struct bgp_dest
*dest
;
13833 struct bgp_table
*table
;
13834 const struct prefix
*p
;
13835 const struct prefix_rd
*prd
;
13836 struct bgp_static
*bgp_static
;
13837 char buf
[PREFIX_STRLEN
* 2];
13838 char buf2
[SU_ADDRSTRLEN
];
13839 char rdbuf
[RD_ADDRSTRLEN
];
13840 char esi_buf
[ESI_BYTES
];
13842 /* Network configuration. */
13843 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
13844 pdest
= bgp_route_next(pdest
)) {
13845 table
= bgp_dest_get_bgp_table_info(pdest
);
13849 for (dest
= bgp_table_top(table
); dest
;
13850 dest
= bgp_route_next(dest
)) {
13851 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13852 if (bgp_static
== NULL
)
13855 char *macrouter
= NULL
;
13857 if (bgp_static
->router_mac
)
13858 macrouter
= prefix_mac2str(
13859 bgp_static
->router_mac
, NULL
, 0);
13860 if (bgp_static
->eth_s_id
)
13861 esi_to_str(bgp_static
->eth_s_id
,
13862 esi_buf
, sizeof(esi_buf
));
13863 p
= bgp_dest_get_prefix(dest
);
13864 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
13866 /* "network" configuration display. */
13867 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13868 if (p
->u
.prefix_evpn
.route_type
== 5) {
13869 char local_buf
[PREFIX_STRLEN
];
13870 uint8_t family
= is_evpn_prefix_ipaddr_v4((
13871 struct prefix_evpn
*)p
)
13875 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
13876 local_buf
, PREFIX_STRLEN
);
13877 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
13878 p
->u
.prefix_evpn
.prefix_addr
13879 .ip_prefix_length
);
13881 prefix2str(p
, buf
, sizeof(buf
));
13884 if (bgp_static
->gatewayIp
.family
== AF_INET
13885 || bgp_static
->gatewayIp
.family
== AF_INET6
)
13886 inet_ntop(bgp_static
->gatewayIp
.family
,
13887 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
13890 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
13892 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
13893 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
13896 XFREE(MTYPE_TMP
, macrouter
);
13901 /* Configuration of static route announcement and aggregate
13903 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13906 struct bgp_dest
*dest
;
13907 const struct prefix
*p
;
13908 struct bgp_static
*bgp_static
;
13909 struct bgp_aggregate
*bgp_aggregate
;
13910 char buf
[SU_ADDRSTRLEN
];
13912 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
13913 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
13917 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
13918 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
13922 /* Network configuration. */
13923 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
13924 dest
= bgp_route_next(dest
)) {
13925 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13926 if (bgp_static
== NULL
)
13929 p
= bgp_dest_get_prefix(dest
);
13931 vty_out(vty
, " network %s/%d",
13932 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13935 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
13936 vty_out(vty
, " label-index %u",
13937 bgp_static
->label_index
);
13939 if (bgp_static
->rmap
.name
)
13940 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
13942 if (bgp_static
->backdoor
)
13943 vty_out(vty
, " backdoor");
13945 vty_out(vty
, "\n");
13948 /* Aggregate-address configuration. */
13949 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
13950 dest
= bgp_route_next(dest
)) {
13951 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
13952 if (bgp_aggregate
== NULL
)
13955 p
= bgp_dest_get_prefix(dest
);
13957 vty_out(vty
, " aggregate-address %s/%d",
13958 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13961 if (bgp_aggregate
->as_set
)
13962 vty_out(vty
, " as-set");
13964 if (bgp_aggregate
->summary_only
)
13965 vty_out(vty
, " summary-only");
13967 if (bgp_aggregate
->rmap
.name
)
13968 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
13970 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
13971 vty_out(vty
, " origin %s",
13972 bgp_origin2str(bgp_aggregate
->origin
));
13974 if (bgp_aggregate
->match_med
)
13975 vty_out(vty
, " matching-MED-only");
13977 vty_out(vty
, "\n");
13981 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13984 struct bgp_dest
*dest
;
13985 struct bgp_distance
*bdistance
;
13987 /* Distance configuration. */
13988 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
13989 && bgp
->distance_local
[afi
][safi
]
13990 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
13991 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
13992 || bgp
->distance_local
[afi
][safi
]
13993 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
13994 vty_out(vty
, " distance bgp %d %d %d\n",
13995 bgp
->distance_ebgp
[afi
][safi
],
13996 bgp
->distance_ibgp
[afi
][safi
],
13997 bgp
->distance_local
[afi
][safi
]);
14000 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14001 dest
= bgp_route_next(dest
)) {
14002 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14003 if (bdistance
!= NULL
)
14004 vty_out(vty
, " distance %d %pRN %s\n",
14005 bdistance
->distance
, dest
,
14006 bdistance
->access_list
? bdistance
->access_list
14011 /* Allocate routing table structure and install commands. */
14012 void bgp_route_init(void)
14017 /* Init BGP distance table. */
14018 FOREACH_AFI_SAFI (afi
, safi
)
14019 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14021 /* IPv4 BGP commands. */
14022 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14023 install_element(BGP_NODE
, &bgp_network_cmd
);
14024 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14026 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14028 /* IPv4 unicast configuration. */
14029 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14030 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14031 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14033 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14035 /* IPv4 multicast configuration. */
14036 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14037 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14038 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14039 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14041 /* IPv4 labeled-unicast configuration. */
14042 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14043 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14045 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14046 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14047 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14048 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14049 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14050 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14051 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14052 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14054 install_element(VIEW_NODE
,
14055 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14056 install_element(VIEW_NODE
,
14057 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
14058 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
14059 install_element(VIEW_NODE
,
14060 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
14061 #ifdef KEEP_OLD_VPN_COMMANDS
14062 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
14063 #endif /* KEEP_OLD_VPN_COMMANDS */
14064 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
14065 install_element(VIEW_NODE
,
14066 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
14068 /* BGP dampening clear commands */
14069 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
14070 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
14072 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
14073 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
14076 install_element(ENABLE_NODE
,
14077 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
14078 #ifdef KEEP_OLD_VPN_COMMANDS
14079 install_element(ENABLE_NODE
,
14080 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
14081 #endif /* KEEP_OLD_VPN_COMMANDS */
14083 /* New config IPv6 BGP commands. */
14084 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
14085 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
14086 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
14088 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
14090 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
14092 /* IPv6 labeled unicast address family. */
14093 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
14094 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
14096 install_element(BGP_NODE
, &bgp_distance_cmd
);
14097 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
14098 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
14099 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
14100 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
14101 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
14102 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
14103 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
14104 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
14105 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
14106 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
14107 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
14108 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
14109 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
14110 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
14111 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
14112 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
14113 install_element(BGP_IPV4M_NODE
,
14114 &no_bgp_distance_source_access_list_cmd
);
14115 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
14116 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
14117 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
14118 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
14119 install_element(BGP_IPV6_NODE
,
14120 &ipv6_bgp_distance_source_access_list_cmd
);
14121 install_element(BGP_IPV6_NODE
,
14122 &no_ipv6_bgp_distance_source_access_list_cmd
);
14123 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
14124 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
14125 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
14126 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
14127 install_element(BGP_IPV6M_NODE
,
14128 &ipv6_bgp_distance_source_access_list_cmd
);
14129 install_element(BGP_IPV6M_NODE
,
14130 &no_ipv6_bgp_distance_source_access_list_cmd
);
14132 /* BGP dampening */
14133 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
14134 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
14135 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
14136 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
14137 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
14138 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
14139 install_element(BGP_IPV4L_NODE
, &bgp_damp_set_cmd
);
14140 install_element(BGP_IPV4L_NODE
, &bgp_damp_unset_cmd
);
14141 install_element(BGP_IPV6_NODE
, &bgp_damp_set_cmd
);
14142 install_element(BGP_IPV6_NODE
, &bgp_damp_unset_cmd
);
14143 install_element(BGP_IPV6M_NODE
, &bgp_damp_set_cmd
);
14144 install_element(BGP_IPV6M_NODE
, &bgp_damp_unset_cmd
);
14145 install_element(BGP_IPV6L_NODE
, &bgp_damp_set_cmd
);
14146 install_element(BGP_IPV6L_NODE
, &bgp_damp_unset_cmd
);
14148 /* Large Communities */
14149 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
14150 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
14152 /* show bgp ipv4 flowspec detailed */
14153 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
14155 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
14156 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
14159 void bgp_route_finish(void)
14164 FOREACH_AFI_SAFI (afi
, safi
) {
14165 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
14166 bgp_distance_table
[afi
][safi
] = NULL
;