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"
73 #include "bgpd/bgp_trace.h"
76 #include "bgpd/rfapi/rfapi_backend.h"
77 #include "bgpd/rfapi/vnc_import_bgp.h"
78 #include "bgpd/rfapi/vnc_export_bgp.h"
80 #include "bgpd/bgp_encap_types.h"
81 #include "bgpd/bgp_encap_tlv.h"
82 #include "bgpd/bgp_evpn.h"
83 #include "bgpd/bgp_evpn_mh.h"
84 #include "bgpd/bgp_evpn_vty.h"
85 #include "bgpd/bgp_flowspec.h"
86 #include "bgpd/bgp_flowspec_util.h"
87 #include "bgpd/bgp_pbr.h"
88 #include "northbound.h"
89 #include "northbound_cli.h"
90 #include "bgpd/bgp_nb.h"
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
96 DEFINE_HOOK(bgp_snmp_update_stats
,
97 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
100 /* Extern from bgp_dump.c */
101 extern const char *bgp_origin_str
[];
102 extern const char *bgp_origin_long_str
[];
105 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
106 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
107 static const struct message bgp_pmsi_tnltype_str
[] = {
108 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
109 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
110 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
111 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
112 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
113 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
114 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
115 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
119 #define VRFID_NONE_STR "-"
121 DEFINE_HOOK(bgp_process
,
122 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
123 struct peer
*peer
, bool withdraw
),
124 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
126 /** Test if path is suppressed. */
127 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
129 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
132 return listcount(pi
->extra
->aggr_suppressors
) > 0;
135 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
136 safi_t safi
, const struct prefix
*p
,
137 struct prefix_rd
*prd
)
139 struct bgp_dest
*dest
;
140 struct bgp_dest
*pdest
= NULL
;
144 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
145 || (safi
== SAFI_EVPN
)) {
146 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
148 if (!bgp_dest_has_bgp_path_info_data(pdest
))
149 bgp_dest_set_bgp_table_info(
150 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
152 bgp_dest_unlock_node(pdest
);
153 table
= bgp_dest_get_bgp_table_info(pdest
);
156 dest
= bgp_node_get(table
, p
);
158 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
159 || (safi
== SAFI_EVPN
))
165 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
166 safi_t safi
, const struct prefix
*p
,
167 struct prefix_rd
*prd
)
169 struct bgp_dest
*dest
;
170 struct bgp_dest
*pdest
= NULL
;
175 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
176 || (safi
== SAFI_EVPN
)) {
177 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
181 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
182 bgp_dest_unlock_node(pdest
);
186 table
= bgp_dest_get_bgp_table_info(pdest
);
189 dest
= bgp_node_lookup(table
, p
);
194 /* Allocate bgp_path_info_extra */
195 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
197 struct bgp_path_info_extra
*new;
198 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
199 sizeof(struct bgp_path_info_extra
));
200 new->label
[0] = MPLS_INVALID_LABEL
;
202 new->bgp_fs_pbr
= NULL
;
203 new->bgp_fs_iprule
= NULL
;
207 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
209 struct bgp_path_info_extra
*e
;
211 if (!extra
|| !*extra
)
218 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
221 /* FIXME: since multiple e may have the same e->parent
222 * and e->parent->net is holding a refcount for each
223 * of them, we need to do some fudging here.
225 * WARNING: if bpi->net->lock drops to 0, bpi may be
226 * freed as well (because bpi->net was holding the
227 * last reference to bpi) => write after free!
231 bpi
= bgp_path_info_lock(bpi
);
232 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
233 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
236 bgp_path_info_unlock(bpi
);
238 bgp_path_info_unlock(e
->parent
);
243 bgp_unlock(e
->bgp_orig
);
245 if (e
->aggr_suppressors
)
246 list_delete(&e
->aggr_suppressors
);
249 bgp_evpn_path_es_info_free(e
->es_info
);
251 if ((*extra
)->bgp_fs_iprule
)
252 list_delete(&((*extra
)->bgp_fs_iprule
));
253 if ((*extra
)->bgp_fs_pbr
)
254 list_delete(&((*extra
)->bgp_fs_pbr
));
255 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
258 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
259 * allocated if required.
261 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
264 pi
->extra
= bgp_path_info_extra_new();
268 /* Free bgp route information. */
269 static void bgp_path_info_free(struct bgp_path_info
*path
)
271 bgp_attr_unintern(&path
->attr
);
273 bgp_unlink_nexthop(path
);
274 bgp_path_info_extra_free(&path
->extra
);
275 bgp_path_info_mpath_free(&path
->mpath
);
277 bgp_addpath_free_info_data(&path
->tx_addpath
,
278 &path
->net
->tx_addpath
);
280 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
282 XFREE(MTYPE_BGP_ROUTE
, path
);
285 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
291 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
293 assert(path
&& path
->lock
> 0);
296 if (path
->lock
== 0) {
298 zlog_debug ("%s: unlocked and freeing", __func__
);
299 zlog_backtrace (LOG_DEBUG
);
301 bgp_path_info_free(path
);
308 zlog_debug ("%s: unlocked to 1", __func__
);
309 zlog_backtrace (LOG_DEBUG
);
316 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
317 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
320 struct bgp_path_info
*old_pi
, *nextpi
;
321 bool set_flag
= false;
322 struct bgp
*bgp
= NULL
;
323 struct bgp_table
*table
= NULL
;
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
330 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
333 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
334 if (BGP_DEBUG(update
, UPDATE_OUT
))
336 "Route %pBD is in workqueue and being processed, not deferred.",
342 table
= bgp_dest_table(dest
);
349 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
350 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
351 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
357 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
358 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
366 && BGP_PEER_RESTARTING_MODE(peer
)
368 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
379 if (set_flag
&& table
) {
380 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
381 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
382 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
383 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
384 if (BGP_DEBUG(update
, UPDATE_OUT
))
385 zlog_debug("DEFER route %pBD, dest %p", dest
,
393 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
395 struct bgp_path_info
*top
;
397 top
= bgp_dest_get_bgp_path_info(dest
);
403 bgp_dest_set_bgp_path_info(dest
, pi
);
405 bgp_path_info_lock(pi
);
406 bgp_dest_lock_node(dest
);
407 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
408 bgp_dest_set_defer_flag(dest
, false);
409 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
412 /* Do the actual removal of info from RIB, for use by bgp_process
413 completion callback *only* */
414 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
417 pi
->next
->prev
= pi
->prev
;
419 pi
->prev
->next
= pi
->next
;
421 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
423 bgp_path_info_mpath_dequeue(pi
);
424 bgp_path_info_unlock(pi
);
425 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
426 bgp_dest_unlock_node(dest
);
429 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
431 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
432 /* set of previous already took care of pcount */
433 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
436 /* undo the effects of a previous call to bgp_path_info_delete; typically
437 called when a route is deleted and then quickly re-added before the
438 deletion has been processed */
439 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
442 /* unset of previous already took care of pcount */
443 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
446 /* Adjust pcount as required */
447 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
449 struct bgp_table
*table
;
451 assert(dest
&& bgp_dest_table(dest
));
452 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
454 table
= bgp_dest_table(dest
);
456 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
459 if (!BGP_PATH_COUNTABLE(pi
)
460 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
462 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
464 /* slight hack, but more robust against errors. */
465 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
466 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
468 flog_err(EC_LIB_DEVELOPMENT
,
469 "Asked to decrement 0 prefix count for peer");
470 } else if (BGP_PATH_COUNTABLE(pi
)
471 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
472 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
473 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
477 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
478 struct bgp_path_info
*pi2
)
480 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
483 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
484 * This is here primarily to keep prefix-count in check.
486 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
489 SET_FLAG(pi
->flags
, flag
);
491 /* early bath if we know it's not a flag that changes countability state
493 if (!CHECK_FLAG(flag
,
494 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
497 bgp_pcount_adjust(dest
, pi
);
500 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
503 UNSET_FLAG(pi
->flags
, flag
);
505 /* early bath if we know it's not a flag that changes countability state
507 if (!CHECK_FLAG(flag
,
508 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
511 bgp_pcount_adjust(dest
, pi
);
514 /* Get MED value. If MED value is missing and "bgp bestpath
515 missing-as-worst" is specified, treat it as the worst value. */
516 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
518 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
521 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
528 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
530 if (pi
->addpath_rx_id
)
531 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
534 sprintf(buf
, "path %s", pi
->peer
->host
);
537 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
539 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
540 struct bgp_path_info
*exist
, int *paths_eq
,
541 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
542 char *pfx_buf
, afi_t afi
, safi_t safi
,
543 enum bgp_path_selection_reason
*reason
)
545 struct attr
*newattr
, *existattr
;
546 bgp_peer_sort_t new_sort
;
547 bgp_peer_sort_t exist_sort
;
553 uint32_t exist_weight
;
554 uint32_t newm
, existm
;
555 struct in_addr new_id
;
556 struct in_addr exist_id
;
559 int internal_as_route
;
562 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
563 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
565 uint32_t exist_mm_seq
;
572 bool new_origin
, exist_origin
;
578 *reason
= bgp_path_selection_none
;
580 zlog_debug("%s: new is NULL", pfx_buf
);
585 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
588 *reason
= bgp_path_selection_first
;
590 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
596 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
597 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
598 pfx_buf
, new_buf
, new->flags
, exist_buf
,
603 existattr
= exist
->attr
;
605 /* For EVPN routes, we cannot just go by local vs remote, we have to
606 * look at the MAC mobility sequence number, if present.
608 if (safi
== SAFI_EVPN
) {
609 /* This is an error condition described in RFC 7432 Section
611 * states that in this scenario "the PE MUST alert the operator"
613 * does not state what other action to take. In order to provide
615 * consistency in this scenario we are going to prefer the path
619 if (newattr
->sticky
!= existattr
->sticky
) {
622 bgp_dest_get_prefix(new->net
), pfx_buf
,
623 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
624 bgp_path_info_path_with_addpath_rx_str(new,
626 bgp_path_info_path_with_addpath_rx_str(
630 if (newattr
->sticky
&& !existattr
->sticky
) {
631 *reason
= bgp_path_selection_evpn_sticky_mac
;
634 "%s: %s wins over %s due to sticky MAC flag",
635 pfx_buf
, new_buf
, exist_buf
);
639 if (!newattr
->sticky
&& existattr
->sticky
) {
640 *reason
= bgp_path_selection_evpn_sticky_mac
;
643 "%s: %s loses to %s due to sticky MAC flag",
644 pfx_buf
, new_buf
, exist_buf
);
649 new_esi
= bgp_evpn_attr_get_esi(newattr
);
650 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
651 if (bgp_evpn_is_esi_valid(new_esi
) &&
652 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
658 /* If both paths have the same non-zero ES and
659 * one path is local it wins.
660 * PS: Note the local path wins even if the remote
661 * has the higher MM seq. The local path's
662 * MM seq will be fixed up to match the highest
663 * rem seq, subsequently.
666 char esi_buf
[ESI_STR_LEN
];
668 if (bgp_evpn_is_path_local(bgp
, new)) {
669 *reason
= bgp_path_selection_evpn_local_path
;
672 "%s: %s wins over %s as ES %s is same and local",
673 pfx_buf
, new_buf
, exist_buf
,
674 esi_to_str(new_esi
, esi_buf
,
678 if (bgp_evpn_is_path_local(bgp
, exist
)) {
679 *reason
= bgp_path_selection_evpn_local_path
;
682 "%s: %s loses to %s as ES %s is same and local",
683 pfx_buf
, new_buf
, exist_buf
,
684 esi_to_str(new_esi
, esi_buf
,
690 new_mm_seq
= mac_mobility_seqnum(newattr
);
691 exist_mm_seq
= mac_mobility_seqnum(existattr
);
693 if (new_mm_seq
> exist_mm_seq
) {
694 *reason
= bgp_path_selection_evpn_seq
;
697 "%s: %s wins over %s due to MM seq %u > %u",
698 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
703 if (new_mm_seq
< exist_mm_seq
) {
704 *reason
= bgp_path_selection_evpn_seq
;
707 "%s: %s loses to %s due to MM seq %u < %u",
708 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
713 /* if the sequence numbers and ESI are the same and one path
714 * is non-proxy it wins (over proxy)
716 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
717 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
718 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
719 old_proxy
!= new_proxy
) {
721 *reason
= bgp_path_selection_evpn_non_proxy
;
724 "%s: %s wins over %s, same seq/es and non-proxy",
725 pfx_buf
, new_buf
, exist_buf
);
729 *reason
= bgp_path_selection_evpn_non_proxy
;
732 "%s: %s loses to %s, same seq/es and non-proxy",
733 pfx_buf
, new_buf
, exist_buf
);
738 * if sequence numbers are the same path with the lowest IP
741 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
743 *reason
= bgp_path_selection_evpn_lower_ip
;
746 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
747 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
748 &new->attr
->nexthop
);
752 *reason
= bgp_path_selection_evpn_lower_ip
;
755 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
756 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
757 &new->attr
->nexthop
);
762 /* 1. Weight check. */
763 new_weight
= newattr
->weight
;
764 exist_weight
= existattr
->weight
;
766 if (new_weight
> exist_weight
) {
767 *reason
= bgp_path_selection_weight
;
769 zlog_debug("%s: %s wins over %s due to weight %d > %d",
770 pfx_buf
, new_buf
, exist_buf
, new_weight
,
775 if (new_weight
< exist_weight
) {
776 *reason
= bgp_path_selection_weight
;
778 zlog_debug("%s: %s loses to %s due to weight %d < %d",
779 pfx_buf
, new_buf
, exist_buf
, new_weight
,
784 /* 2. Local preference check. */
785 new_pref
= exist_pref
= bgp
->default_local_pref
;
787 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
788 new_pref
= newattr
->local_pref
;
789 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
790 exist_pref
= existattr
->local_pref
;
792 if (new_pref
> exist_pref
) {
793 *reason
= bgp_path_selection_local_pref
;
796 "%s: %s wins over %s due to localpref %d > %d",
797 pfx_buf
, new_buf
, exist_buf
, new_pref
,
802 if (new_pref
< exist_pref
) {
803 *reason
= bgp_path_selection_local_pref
;
806 "%s: %s loses to %s due to localpref %d < %d",
807 pfx_buf
, new_buf
, exist_buf
, new_pref
,
812 /* 3. Local route check. We prefer:
814 * - BGP_ROUTE_AGGREGATE
815 * - BGP_ROUTE_REDISTRIBUTE
817 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
818 new->sub_type
== BGP_ROUTE_IMPORTED
);
819 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
820 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
822 if (new_origin
&& !exist_origin
) {
823 *reason
= bgp_path_selection_local_route
;
826 "%s: %s wins over %s due to preferred BGP_ROUTE type",
827 pfx_buf
, new_buf
, exist_buf
);
831 if (!new_origin
&& exist_origin
) {
832 *reason
= bgp_path_selection_local_route
;
835 "%s: %s loses to %s due to preferred BGP_ROUTE type",
836 pfx_buf
, new_buf
, exist_buf
);
840 /* 4. AS path length check. */
841 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
842 int exist_hops
= aspath_count_hops(existattr
->aspath
);
843 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
845 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
848 aspath_hops
= aspath_count_hops(newattr
->aspath
);
849 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
851 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
852 *reason
= bgp_path_selection_confed_as_path
;
855 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
856 pfx_buf
, new_buf
, exist_buf
,
858 (exist_hops
+ exist_confeds
));
862 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
863 *reason
= bgp_path_selection_confed_as_path
;
866 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
867 pfx_buf
, new_buf
, exist_buf
,
869 (exist_hops
+ exist_confeds
));
873 int newhops
= aspath_count_hops(newattr
->aspath
);
875 if (newhops
< exist_hops
) {
876 *reason
= bgp_path_selection_as_path
;
879 "%s: %s wins over %s due to aspath hopcount %d < %d",
880 pfx_buf
, new_buf
, exist_buf
,
881 newhops
, exist_hops
);
885 if (newhops
> exist_hops
) {
886 *reason
= bgp_path_selection_as_path
;
889 "%s: %s loses to %s due to aspath hopcount %d > %d",
890 pfx_buf
, new_buf
, exist_buf
,
891 newhops
, exist_hops
);
897 /* 5. Origin check. */
898 if (newattr
->origin
< existattr
->origin
) {
899 *reason
= bgp_path_selection_origin
;
901 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
902 pfx_buf
, new_buf
, exist_buf
,
903 bgp_origin_long_str
[newattr
->origin
],
904 bgp_origin_long_str
[existattr
->origin
]);
908 if (newattr
->origin
> existattr
->origin
) {
909 *reason
= bgp_path_selection_origin
;
911 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
912 pfx_buf
, new_buf
, exist_buf
,
913 bgp_origin_long_str
[newattr
->origin
],
914 bgp_origin_long_str
[existattr
->origin
]);
919 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
920 && aspath_count_hops(existattr
->aspath
) == 0);
921 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
922 && aspath_count_confeds(existattr
->aspath
) > 0
923 && aspath_count_hops(newattr
->aspath
) == 0
924 && aspath_count_hops(existattr
->aspath
) == 0);
926 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
927 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
928 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
929 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
930 || internal_as_route
) {
931 new_med
= bgp_med_value(new->attr
, bgp
);
932 exist_med
= bgp_med_value(exist
->attr
, bgp
);
934 if (new_med
< exist_med
) {
935 *reason
= bgp_path_selection_med
;
938 "%s: %s wins over %s due to MED %d < %d",
939 pfx_buf
, new_buf
, exist_buf
, new_med
,
944 if (new_med
> exist_med
) {
945 *reason
= bgp_path_selection_med
;
948 "%s: %s loses to %s due to MED %d > %d",
949 pfx_buf
, new_buf
, exist_buf
, new_med
,
955 /* 7. Peer type check. */
956 new_sort
= new->peer
->sort
;
957 exist_sort
= exist
->peer
->sort
;
959 if (new_sort
== BGP_PEER_EBGP
960 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
961 *reason
= bgp_path_selection_peer
;
964 "%s: %s wins over %s due to eBGP peer > iBGP peer",
965 pfx_buf
, new_buf
, exist_buf
);
969 if (exist_sort
== BGP_PEER_EBGP
970 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
971 *reason
= bgp_path_selection_peer
;
974 "%s: %s loses to %s due to iBGP peer < eBGP peer",
975 pfx_buf
, new_buf
, exist_buf
);
979 /* 8. IGP metric check. */
983 newm
= new->extra
->igpmetric
;
985 existm
= exist
->extra
->igpmetric
;
990 "%s: %s wins over %s due to IGP metric %d < %d",
991 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
998 "%s: %s loses to %s due to IGP metric %d > %d",
999 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1003 /* 9. Same IGP metric. Compare the cluster list length as
1004 representative of IGP hops metric. Rewrite the metric value
1005 pair (newm, existm) with the cluster list length. Prefer the
1006 path with smaller cluster list length. */
1007 if (newm
== existm
) {
1008 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1009 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1010 && (mpath_cfg
== NULL
1012 mpath_cfg
->ibgp_flags
,
1013 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1014 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1015 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1017 if (newm
< existm
) {
1020 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1021 pfx_buf
, new_buf
, exist_buf
,
1026 if (newm
> existm
) {
1029 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1030 pfx_buf
, new_buf
, exist_buf
,
1037 /* 10. confed-external vs. confed-internal */
1038 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1039 if (new_sort
== BGP_PEER_CONFED
1040 && exist_sort
== BGP_PEER_IBGP
) {
1041 *reason
= bgp_path_selection_confed
;
1044 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1045 pfx_buf
, new_buf
, exist_buf
);
1049 if (exist_sort
== BGP_PEER_CONFED
1050 && new_sort
== BGP_PEER_IBGP
) {
1051 *reason
= bgp_path_selection_confed
;
1054 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1055 pfx_buf
, new_buf
, exist_buf
);
1060 /* 11. Maximum path check. */
1061 if (newm
== existm
) {
1062 /* If one path has a label but the other does not, do not treat
1063 * them as equals for multipath
1065 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1067 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1070 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1071 pfx_buf
, new_buf
, exist_buf
);
1072 } else if (CHECK_FLAG(bgp
->flags
,
1073 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1076 * For the two paths, all comparison steps till IGP
1078 * have succeeded - including AS_PATH hop count. Since
1080 * bestpath as-path multipath-relax' knob is on, we
1082 * an exact match of AS_PATH. Thus, mark the paths are
1084 * That will trigger both these paths to get into the
1092 "%s: %s and %s are equal via multipath-relax",
1093 pfx_buf
, new_buf
, exist_buf
);
1094 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1095 if (aspath_cmp(new->attr
->aspath
,
1096 exist
->attr
->aspath
)) {
1101 "%s: %s and %s are equal via matching aspaths",
1102 pfx_buf
, new_buf
, exist_buf
);
1104 } else if (new->peer
->as
== exist
->peer
->as
) {
1109 "%s: %s and %s are equal via same remote-as",
1110 pfx_buf
, new_buf
, exist_buf
);
1114 * TODO: If unequal cost ibgp multipath is enabled we can
1115 * mark the paths as equal here instead of returning
1120 "%s: %s wins over %s after IGP metric comparison",
1121 pfx_buf
, new_buf
, exist_buf
);
1124 "%s: %s loses to %s after IGP metric comparison",
1125 pfx_buf
, new_buf
, exist_buf
);
1127 *reason
= bgp_path_selection_igp_metric
;
1131 /* 12. If both paths are external, prefer the path that was received
1132 first (the oldest one). This step minimizes route-flap, since a
1133 newer path won't displace an older one, even if it was the
1134 preferred route based on the additional decision criteria below. */
1135 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1136 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1137 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1138 *reason
= bgp_path_selection_older
;
1141 "%s: %s wins over %s due to oldest external",
1142 pfx_buf
, new_buf
, exist_buf
);
1146 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1147 *reason
= bgp_path_selection_older
;
1150 "%s: %s loses to %s due to oldest external",
1151 pfx_buf
, new_buf
, exist_buf
);
1156 /* 13. Router-ID comparision. */
1157 /* If one of the paths is "stale", the corresponding peer router-id will
1158 * be 0 and would always win over the other path. If originator id is
1159 * used for the comparision, it will decide which path is better.
1161 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1162 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1164 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1165 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1166 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1168 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1170 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1171 *reason
= bgp_path_selection_router_id
;
1174 "%s: %s wins over %s due to Router-ID comparison",
1175 pfx_buf
, new_buf
, exist_buf
);
1179 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1180 *reason
= bgp_path_selection_router_id
;
1183 "%s: %s loses to %s due to Router-ID comparison",
1184 pfx_buf
, new_buf
, exist_buf
);
1188 /* 14. Cluster length comparision. */
1189 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1190 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1192 if (new_cluster
< exist_cluster
) {
1193 *reason
= bgp_path_selection_cluster_length
;
1196 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1197 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1202 if (new_cluster
> exist_cluster
) {
1203 *reason
= bgp_path_selection_cluster_length
;
1206 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1207 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1212 /* 15. Neighbor address comparision. */
1213 /* Do this only if neither path is "stale" as stale paths do not have
1214 * valid peer information (as the connection may or may not be up).
1216 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1217 *reason
= bgp_path_selection_stale
;
1220 "%s: %s wins over %s due to latter path being STALE",
1221 pfx_buf
, new_buf
, exist_buf
);
1225 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1226 *reason
= bgp_path_selection_stale
;
1229 "%s: %s loses to %s due to former path being STALE",
1230 pfx_buf
, new_buf
, exist_buf
);
1234 /* locally configured routes to advertise do not have su_remote */
1235 if (new->peer
->su_remote
== NULL
) {
1236 *reason
= bgp_path_selection_local_configured
;
1239 if (exist
->peer
->su_remote
== NULL
) {
1240 *reason
= bgp_path_selection_local_configured
;
1244 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1247 *reason
= bgp_path_selection_neighbor_ip
;
1250 "%s: %s loses to %s due to Neighor IP comparison",
1251 pfx_buf
, new_buf
, exist_buf
);
1256 *reason
= bgp_path_selection_neighbor_ip
;
1259 "%s: %s wins over %s due to Neighor IP comparison",
1260 pfx_buf
, new_buf
, exist_buf
);
1264 *reason
= bgp_path_selection_default
;
1266 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1267 pfx_buf
, new_buf
, exist_buf
);
1273 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1274 struct bgp_path_info
*exist
, int *paths_eq
)
1276 enum bgp_path_selection_reason reason
;
1277 char pfx_buf
[PREFIX2STR_BUFFER
];
1279 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1280 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1283 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1284 * is preferred, or 0 if they are the same (usually will only occur if
1285 * multipath is enabled
1286 * This version is compatible with */
1287 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1288 struct bgp_path_info
*exist
, char *pfx_buf
,
1289 afi_t afi
, safi_t safi
,
1290 enum bgp_path_selection_reason
*reason
)
1294 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1308 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1309 const struct prefix
*p
,
1310 struct attr
*attr
, afi_t afi
,
1313 struct bgp_filter
*filter
;
1314 enum filter_type ret
= FILTER_PERMIT
;
1316 filter
= &peer
->filter
[afi
][safi
];
1318 #define FILTER_EXIST_WARN(F, f, filter) \
1319 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1320 zlog_debug("%s: Could not find configured input %s-list %s!", \
1321 peer->host, #f, F##_IN_NAME(filter));
1323 if (DISTRIBUTE_IN_NAME(filter
)) {
1324 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1326 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1333 if (PREFIX_LIST_IN_NAME(filter
)) {
1334 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1336 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1343 if (FILTER_LIST_IN_NAME(filter
)) {
1344 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1346 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1347 == AS_FILTER_DENY
) {
1354 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1355 char pfxprint
[PREFIX2STR_BUFFER
];
1357 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1358 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1359 ret
== FILTER_PERMIT
? "permit" : "deny");
1363 #undef FILTER_EXIST_WARN
1366 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1367 const struct prefix
*p
,
1368 struct attr
*attr
, afi_t afi
,
1371 struct bgp_filter
*filter
;
1372 enum filter_type ret
= FILTER_PERMIT
;
1374 filter
= &peer
->filter
[afi
][safi
];
1376 #define FILTER_EXIST_WARN(F, f, filter) \
1377 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1378 zlog_debug("%s: Could not find configured output %s-list %s!", \
1379 peer->host, #f, F##_OUT_NAME(filter));
1381 if (DISTRIBUTE_OUT_NAME(filter
)) {
1382 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1384 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1391 if (PREFIX_LIST_OUT_NAME(filter
)) {
1392 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1394 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1401 if (FILTER_LIST_OUT_NAME(filter
)) {
1402 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1404 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1405 == AS_FILTER_DENY
) {
1411 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1412 char pfxprint
[PREFIX2STR_BUFFER
];
1414 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1415 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1416 ret
== FILTER_PERMIT
? "permit" : "deny");
1421 #undef FILTER_EXIST_WARN
1424 /* If community attribute includes no_export then return 1. */
1425 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1427 if (attr
->community
) {
1428 /* NO_ADVERTISE check. */
1429 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1432 /* NO_EXPORT check. */
1433 if (peer
->sort
== BGP_PEER_EBGP
1434 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1437 /* NO_EXPORT_SUBCONFED check. */
1438 if (peer
->sort
== BGP_PEER_EBGP
1439 || peer
->sort
== BGP_PEER_CONFED
)
1440 if (community_include(attr
->community
,
1441 COMMUNITY_NO_EXPORT_SUBCONFED
))
1447 /* Route reflection loop check. */
1448 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1450 struct in_addr cluster_id
;
1451 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1454 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1455 cluster_id
= peer
->bgp
->cluster_id
;
1457 cluster_id
= peer
->bgp
->router_id
;
1459 if (cluster_loop_check(cluster
, cluster_id
))
1465 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1466 struct attr
*attr
, afi_t afi
, safi_t safi
,
1467 const char *rmap_name
, mpls_label_t
*label
,
1468 uint32_t num_labels
, struct bgp_dest
*dest
)
1470 struct bgp_filter
*filter
;
1471 struct bgp_path_info rmap_path
= { 0 };
1472 struct bgp_path_info_extra extra
= { 0 };
1473 route_map_result_t ret
;
1474 struct route_map
*rmap
= NULL
;
1476 filter
= &peer
->filter
[afi
][safi
];
1478 /* Apply default weight value. */
1479 if (peer
->weight
[afi
][safi
])
1480 attr
->weight
= peer
->weight
[afi
][safi
];
1483 rmap
= route_map_lookup_by_name(rmap_name
);
1488 if (ROUTE_MAP_IN_NAME(filter
)) {
1489 rmap
= ROUTE_MAP_IN(filter
);
1496 /* Route map apply. */
1498 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1499 /* Duplicate current value to new strucutre for modification. */
1500 rmap_path
.peer
= peer
;
1501 rmap_path
.attr
= attr
;
1502 rmap_path
.extra
= &extra
;
1503 rmap_path
.net
= dest
;
1505 extra
.num_labels
= num_labels
;
1506 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1507 memcpy(extra
.label
, label
,
1508 num_labels
* sizeof(mpls_label_t
));
1510 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1512 /* Apply BGP route map to the attribute. */
1513 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1515 peer
->rmap_type
= 0;
1517 if (ret
== RMAP_DENYMATCH
)
1523 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1524 struct attr
*attr
, afi_t afi
, safi_t safi
,
1525 const char *rmap_name
)
1527 struct bgp_path_info rmap_path
;
1528 route_map_result_t ret
;
1529 struct route_map
*rmap
= NULL
;
1533 * So if we get to this point and have no rmap_name
1534 * we want to just show the output as it currently
1540 /* Apply default weight value. */
1541 if (peer
->weight
[afi
][safi
])
1542 attr
->weight
= peer
->weight
[afi
][safi
];
1544 rmap
= route_map_lookup_by_name(rmap_name
);
1547 * If we have a route map name and we do not find
1548 * the routemap that means we have an implicit
1554 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1555 /* Route map apply. */
1556 /* Duplicate current value to new strucutre for modification. */
1557 rmap_path
.peer
= peer
;
1558 rmap_path
.attr
= attr
;
1560 rmap_type
= peer
->rmap_type
;
1561 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1563 /* Apply BGP route map to the attribute. */
1564 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1566 peer
->rmap_type
= rmap_type
;
1568 if (ret
== RMAP_DENYMATCH
)
1570 * caller has multiple error paths with bgp_attr_flush()
1577 /* If this is an EBGP peer with remove-private-AS */
1578 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1579 struct peer
*peer
, struct attr
*attr
)
1581 if (peer
->sort
== BGP_PEER_EBGP
1582 && (peer_af_flag_check(peer
, afi
, safi
,
1583 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1584 || peer_af_flag_check(peer
, afi
, safi
,
1585 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1586 || peer_af_flag_check(peer
, afi
, safi
,
1587 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1588 || peer_af_flag_check(peer
, afi
, safi
,
1589 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1590 // Take action on the entire aspath
1591 if (peer_af_flag_check(peer
, afi
, safi
,
1592 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1593 || peer_af_flag_check(peer
, afi
, safi
,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1595 if (peer_af_flag_check(
1597 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1598 attr
->aspath
= aspath_replace_private_asns(
1599 attr
->aspath
, bgp
->as
, peer
->as
);
1601 // The entire aspath consists of private ASNs so create
1603 else if (aspath_private_as_check(attr
->aspath
))
1604 attr
->aspath
= aspath_empty_get();
1606 // There are some public and some private ASNs, remove
1609 attr
->aspath
= aspath_remove_private_asns(
1610 attr
->aspath
, peer
->as
);
1613 // 'all' was not specified so the entire aspath must be private
1615 // for us to do anything
1616 else if (aspath_private_as_check(attr
->aspath
)) {
1617 if (peer_af_flag_check(
1619 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1620 attr
->aspath
= aspath_replace_private_asns(
1621 attr
->aspath
, bgp
->as
, peer
->as
);
1623 attr
->aspath
= aspath_empty_get();
1628 /* If this is an EBGP peer with as-override */
1629 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1630 struct peer
*peer
, struct attr
*attr
)
1632 if (peer
->sort
== BGP_PEER_EBGP
1633 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1634 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1635 attr
->aspath
= aspath_replace_specific_asn(
1636 attr
->aspath
, peer
->as
, bgp
->as
);
1640 void bgp_attr_add_gshut_community(struct attr
*attr
)
1642 struct community
*old
;
1643 struct community
*new;
1644 struct community
*merge
;
1645 struct community
*gshut
;
1647 old
= attr
->community
;
1648 gshut
= community_str2com("graceful-shutdown");
1653 merge
= community_merge(community_dup(old
), gshut
);
1655 if (old
->refcnt
== 0)
1656 community_free(&old
);
1658 new = community_uniq_sort(merge
);
1659 community_free(&merge
);
1661 new = community_dup(gshut
);
1664 community_free(&gshut
);
1665 attr
->community
= new;
1666 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1668 /* When we add the graceful-shutdown community we must also
1669 * lower the local-preference */
1670 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1671 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1675 /* Notify BGP Conditional advertisement scanner process. */
1676 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1678 struct peer
*temp_peer
;
1679 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1680 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1681 afi_t afi
= SUBGRP_AFI(subgrp
);
1682 safi_t safi
= SUBGRP_SAFI(subgrp
);
1683 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1684 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1686 if (!ADVERTISE_MAP_NAME(filter
))
1689 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1690 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1693 if (peer
!= temp_peer
)
1696 temp_peer
->advmap_table_change
= true;
1702 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1704 if (family
== AF_INET
) {
1705 attr
->nexthop
.s_addr
= INADDR_ANY
;
1706 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1708 if (family
== AF_INET6
)
1709 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1710 if (family
== AF_EVPN
)
1711 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1714 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1715 struct update_subgroup
*subgrp
,
1716 const struct prefix
*p
, struct attr
*attr
,
1717 bool skip_rmap_check
)
1719 struct bgp_filter
*filter
;
1722 struct peer
*onlypeer
;
1724 struct attr
*piattr
;
1725 route_map_result_t ret
;
1730 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1731 bool nh_reset
= false;
1734 if (DISABLE_BGP_ANNOUNCE
)
1737 afi
= SUBGRP_AFI(subgrp
);
1738 safi
= SUBGRP_SAFI(subgrp
);
1739 peer
= SUBGRP_PEER(subgrp
);
1741 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1742 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1745 filter
= &peer
->filter
[afi
][safi
];
1746 bgp
= SUBGRP_INST(subgrp
);
1747 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1750 #ifdef ENABLE_BGP_VNC
1751 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1752 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1753 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1756 * direct and direct_ext type routes originate internally even
1757 * though they can have peer pointers that reference other
1760 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1766 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1767 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1768 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1769 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1771 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1776 /* With addpath we may be asked to TX all kinds of paths so make sure
1778 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1779 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1780 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1784 /* If this is not the bestpath then check to see if there is an enabled
1786 * feature that requires us to advertise it */
1787 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1788 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1793 /* Aggregate-address suppress check. */
1794 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1798 * If we are doing VRF 2 VRF leaking via the import
1799 * statement, we want to prevent the route going
1800 * off box as that the RT and RD created are localy
1801 * significant and globaly useless.
1803 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1804 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1807 /* If it's labeled safi, make sure the route has a valid label. */
1808 if (safi
== SAFI_LABELED_UNICAST
) {
1809 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1810 if (!bgp_is_valid_label(&label
)) {
1811 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1812 zlog_debug("u%" PRIu64
":s%" PRIu64
1813 " %pFX is filtered - no label (%p)",
1814 subgrp
->update_group
->id
, subgrp
->id
,
1820 /* Do not send back route to sender. */
1821 if (onlypeer
&& from
== onlypeer
) {
1825 /* Do not send the default route in the BGP table if the neighbor is
1826 * configured for default-originate */
1827 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1828 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1829 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1831 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1835 /* Transparency check. */
1836 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1837 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1842 /* If community is not disabled check the no-export and local. */
1843 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1844 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1845 zlog_debug("%s: community filter check fail for %pFX",
1850 /* If the attribute has originator-id and it is same as remote
1852 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1853 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1854 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1856 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1861 /* ORF prefix-list filter check */
1862 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1863 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1864 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1865 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1866 if (peer
->orf_plist
[afi
][safi
]) {
1867 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1869 if (bgp_debug_update(NULL
, p
,
1870 subgrp
->update_group
, 0))
1872 "%s [Update:SEND] %pFX is filtered via ORF",
1878 /* Output filter check. */
1879 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1880 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1881 zlog_debug("%s [Update:SEND] %pFX is filtered",
1886 /* AS path loop check. */
1887 if (onlypeer
&& onlypeer
->as_path_loop_detection
1888 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1889 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1891 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1892 onlypeer
->host
, onlypeer
->as
);
1896 /* If we're a CONFED we need to loop check the CONFED ID too */
1897 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1898 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1899 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1901 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1902 peer
->host
, bgp
->confed_id
);
1907 /* Route-Reflect check. */
1908 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1913 /* IBGP reflection check. */
1914 if (reflect
&& !samepeer_safe
) {
1915 /* A route from a Client peer. */
1916 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1917 PEER_FLAG_REFLECTOR_CLIENT
)) {
1918 /* Reflect to all the Non-Client peers and also to the
1919 Client peers other than the originator. Originator
1921 is already done. So there is noting to do. */
1922 /* no bgp client-to-client reflection check. */
1923 if (CHECK_FLAG(bgp
->flags
,
1924 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1925 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1926 PEER_FLAG_REFLECTOR_CLIENT
))
1929 /* A route from a Non-client peer. Reflect to all other
1931 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1932 PEER_FLAG_REFLECTOR_CLIENT
))
1937 /* For modify attribute, copy it to temporary structure. */
1940 /* If local-preference is not set. */
1941 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1942 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1943 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1944 attr
->local_pref
= bgp
->default_local_pref
;
1947 /* If originator-id is not set and the route is to be reflected,
1948 set the originator id */
1950 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1951 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1952 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1955 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1957 if (peer
->sort
== BGP_PEER_EBGP
1958 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1959 if (from
!= bgp
->peer_self
&& !transparent
1960 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1961 PEER_FLAG_MED_UNCHANGED
))
1963 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1966 /* Since the nexthop attribute can vary per peer, it is not explicitly
1968 * in announce check, only certain flags and length (or number of
1970 * -- for IPv6/MP_REACH) are set here in order to guide the update
1972 * code in setting the nexthop(s) on a per peer basis in
1974 * Typically, the source nexthop in the attribute is preserved but in
1976 * scenarios where we know it will always be overwritten, we reset the
1977 * nexthop to "0" in an attempt to achieve better Update packing. An
1978 * example of this is when a prefix from each of 2 IBGP peers needs to
1980 * announced to an EBGP peer (and they have the same attributes barring
1984 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1986 #define NEXTHOP_IS_V6 \
1987 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1988 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1989 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1990 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1992 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1994 * the peer (group) is configured to receive link-local nexthop
1996 * and it is available in the prefix OR we're not reflecting the route,
1997 * link-local nexthop address is valid and
1998 * the peer (group) to whom we're going to announce is on a shared
2000 * and this is either a self-originated route or the peer is EBGP.
2001 * By checking if nexthop LL address is valid we are sure that
2002 * we do not announce LL address as `::`.
2004 if (NEXTHOP_IS_V6
) {
2005 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2006 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2007 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2008 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2010 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2011 && peer
->shared_network
2012 && (from
== bgp
->peer_self
2013 || peer
->sort
== BGP_PEER_EBGP
))) {
2014 attr
->mp_nexthop_len
=
2015 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2018 /* Clear off link-local nexthop in source, whenever it is not
2020 * ensure more prefixes share the same attribute for
2023 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2024 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2025 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2028 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2029 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2031 /* Route map & unsuppress-map apply. */
2032 if (!skip_rmap_check
2033 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2034 struct bgp_path_info rmap_path
= {0};
2035 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2036 struct attr dummy_attr
= {0};
2038 /* Fill temp path_info */
2039 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2042 /* don't confuse inbound and outbound setting */
2043 RESET_FLAG(attr
->rmap_change_flags
);
2046 * The route reflector is not allowed to modify the attributes
2047 * of the reflected IBGP routes unless explicitly allowed.
2049 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2050 && !CHECK_FLAG(bgp
->flags
,
2051 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2053 rmap_path
.attr
= &dummy_attr
;
2056 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2058 if (bgp_path_suppressed(pi
))
2059 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2062 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2065 peer
->rmap_type
= 0;
2067 if (ret
== RMAP_DENYMATCH
) {
2068 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2070 "%s [Update:SEND] %pFX is filtered by route-map",
2073 bgp_attr_flush(attr
);
2078 /* RFC 8212 to prevent route leaks.
2079 * This specification intends to improve this situation by requiring the
2080 * explicit configuration of both BGP Import and Export Policies for any
2081 * External BGP (EBGP) session such as customers, peers, or
2082 * confederation boundaries for all enabled address families. Through
2083 * codification of the aforementioned requirement, operators will
2084 * benefit from consistent behavior across different BGP
2087 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2088 if (!bgp_outbound_policy_exists(peer
, filter
))
2091 /* draft-ietf-idr-deprecate-as-set-confed-set
2092 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2093 * Eventually, This document (if approved) updates RFC 4271
2094 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2095 * and obsoletes RFC 6472.
2097 if (peer
->bgp
->reject_as_sets
)
2098 if (aspath_check_as_sets(attr
->aspath
))
2101 /* Codification of AS 0 Processing */
2102 if (aspath_check_as_zero(attr
->aspath
))
2105 if (bgp_in_graceful_shutdown(bgp
)) {
2106 if (peer
->sort
== BGP_PEER_IBGP
2107 || peer
->sort
== BGP_PEER_CONFED
) {
2108 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2109 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2111 bgp_attr_add_gshut_community(attr
);
2115 /* After route-map has been applied, we check to see if the nexthop to
2116 * be carried in the attribute (that is used for the announcement) can
2117 * be cleared off or not. We do this in all cases where we would be
2118 * setting the nexthop to "ourselves". For IPv6, we only need to
2120 * the global nexthop here; the link-local nexthop would have been
2122 * already, and if not, it is required by the update formation code.
2123 * Also see earlier comments in this function.
2126 * If route-map has performed some operation on the nexthop or the peer
2127 * configuration says to pass it unchanged, we cannot reset the nexthop
2128 * here, so only attempt to do it if these aren't true. Note that the
2129 * route-map handler itself might have cleared the nexthop, if for
2131 * it is configured as 'peer-address'.
2133 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2134 piattr
->rmap_change_flags
)
2136 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2137 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2138 /* We can reset the nexthop, if setting (or forcing) it to
2140 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2141 PEER_FLAG_NEXTHOP_SELF
)
2142 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2143 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2145 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2146 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2147 subgroup_announce_reset_nhop(
2148 (peer_cap_enhe(peer
, afi
, safi
)
2154 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2155 /* Can also reset the nexthop if announcing to EBGP, but
2157 * no peer in the subgroup is on a shared subnet.
2158 * Note: 3rd party nexthop currently implemented for
2161 if ((p
->family
== AF_INET
) &&
2162 (!bgp_subgrp_multiaccess_check_v4(
2165 subgroup_announce_reset_nhop(
2166 (peer_cap_enhe(peer
, afi
, safi
)
2173 if ((p
->family
== AF_INET6
) &&
2174 (!bgp_subgrp_multiaccess_check_v6(
2175 piattr
->mp_nexthop_global
,
2177 subgroup_announce_reset_nhop(
2178 (peer_cap_enhe(peer
, afi
, safi
)
2187 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2189 * This flag is used for leaked vpn-vrf routes
2191 int family
= p
->family
;
2193 if (peer_cap_enhe(peer
, afi
, safi
))
2196 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2198 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2199 __func__
, family2str(family
));
2200 subgroup_announce_reset_nhop(family
, attr
);
2205 /* If IPv6/MP and nexthop does not have any override and happens
2207 * be a link-local address, reset it so that we don't pass along
2209 * source's link-local IPv6 address to recipients who may not be
2211 * the same interface.
2213 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2214 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2215 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2221 * When the next hop is set to ourselves, if all multipaths have
2222 * link-bandwidth announce the cumulative bandwidth as that makes
2223 * the most sense. However, don't modify if the link-bandwidth has
2224 * been explicitly set by user policy.
2227 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2228 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2229 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2230 attr
->ecommunity
= ecommunity_replace_linkbw(
2231 bgp
->as
, attr
->ecommunity
, cum_bw
);
2236 static int bgp_route_select_timer_expire(struct thread
*thread
)
2238 struct afi_safi_info
*info
;
2243 info
= THREAD_ARG(thread
);
2248 if (BGP_DEBUG(update
, UPDATE_OUT
))
2249 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2252 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2254 XFREE(MTYPE_TMP
, info
);
2256 /* Best path selection */
2257 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2260 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2261 struct bgp_maxpaths_cfg
*mpath_cfg
,
2262 struct bgp_path_info_pair
*result
, afi_t afi
,
2265 struct bgp_path_info
*new_select
;
2266 struct bgp_path_info
*old_select
;
2267 struct bgp_path_info
*pi
;
2268 struct bgp_path_info
*pi1
;
2269 struct bgp_path_info
*pi2
;
2270 struct bgp_path_info
*nextpi
= NULL
;
2271 int paths_eq
, do_mpath
, debug
;
2272 struct list mp_list
;
2273 char pfx_buf
[PREFIX2STR_BUFFER
];
2274 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2276 bgp_mp_list_init(&mp_list
);
2278 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2280 debug
= bgp_debug_bestpath(dest
);
2283 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2285 dest
->reason
= bgp_path_selection_none
;
2286 /* bgp deterministic-med */
2288 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2290 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2291 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2293 bgp_path_info_unset_flag(dest
, pi1
,
2294 BGP_PATH_DMED_SELECTED
);
2296 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2298 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2300 if (BGP_PATH_HOLDDOWN(pi1
))
2302 if (pi1
->peer
!= bgp
->peer_self
)
2303 if (pi1
->peer
->status
!= Established
)
2308 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2309 if (CHECK_FLAG(pi2
->flags
,
2310 BGP_PATH_DMED_CHECK
))
2312 if (BGP_PATH_HOLDDOWN(pi2
))
2314 if (pi2
->peer
!= bgp
->peer_self
2317 PEER_STATUS_NSF_WAIT
))
2318 if (pi2
->peer
->status
2322 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2324 && !aspath_cmp_left_confed(
2329 if (bgp_path_info_cmp(
2330 bgp
, pi2
, new_select
,
2331 &paths_eq
, mpath_cfg
, debug
,
2334 bgp_path_info_unset_flag(
2336 BGP_PATH_DMED_SELECTED
);
2340 bgp_path_info_set_flag(
2341 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2344 bgp_path_info_set_flag(dest
, new_select
,
2345 BGP_PATH_DMED_CHECK
);
2346 bgp_path_info_set_flag(dest
, new_select
,
2347 BGP_PATH_DMED_SELECTED
);
2350 bgp_path_info_path_with_addpath_rx_str(
2351 new_select
, path_buf
);
2353 "%pBD: %s is the bestpath from AS %u",
2355 aspath_get_first_as(
2356 new_select
->attr
->aspath
));
2361 /* Check old selected route and new selected route. */
2364 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2365 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2366 enum bgp_path_selection_reason reason
;
2368 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2371 if (BGP_PATH_HOLDDOWN(pi
)) {
2372 /* reap REMOVED routes, if needs be
2373 * selected route must stay for a while longer though
2375 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2376 && (pi
!= old_select
))
2377 bgp_path_info_reap(dest
, pi
);
2380 zlog_debug("%s: pi %p in holddown", __func__
,
2386 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2387 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2388 if (pi
->peer
->status
!= Established
) {
2392 "%s: pi %p non self peer %s not estab state",
2393 __func__
, pi
, pi
->peer
->host
);
2398 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2399 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2400 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2402 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2406 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2408 reason
= dest
->reason
;
2409 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2410 debug
, pfx_buf
, afi
, safi
,
2412 if (new_select
== NULL
&&
2413 reason
!= bgp_path_selection_none
)
2414 dest
->reason
= reason
;
2419 /* Now that we know which path is the bestpath see if any of the other
2421 * qualify as multipaths
2425 bgp_path_info_path_with_addpath_rx_str(new_select
,
2428 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2430 "%pBD: After path selection, newbest is %s oldbest was %s",
2432 old_select
? old_select
->peer
->host
: "NONE");
2435 if (do_mpath
&& new_select
) {
2436 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2437 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2440 bgp_path_info_path_with_addpath_rx_str(
2443 if (pi
== new_select
) {
2446 "%pBD: %s is the bestpath, add to the multipath list",
2448 bgp_mp_list_add(&mp_list
, pi
);
2452 if (BGP_PATH_HOLDDOWN(pi
))
2455 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2456 && !CHECK_FLAG(pi
->peer
->sflags
,
2457 PEER_STATUS_NSF_WAIT
))
2458 if (pi
->peer
->status
!= Established
)
2461 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2464 "%pBD: %s has the same nexthop as the bestpath, skip it",
2469 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2470 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2476 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2478 bgp_mp_list_add(&mp_list
, pi
);
2483 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2485 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2486 bgp_mp_list_clear(&mp_list
);
2488 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2490 result
->old
= old_select
;
2491 result
->new = new_select
;
2497 * A new route/change in bestpath of an existing route. Evaluate the path
2498 * for advertisement to the subgroup.
2500 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2501 struct bgp_path_info
*selected
,
2502 struct bgp_dest
*dest
,
2503 uint32_t addpath_tx_id
)
2505 const struct prefix
*p
;
2506 struct peer
*onlypeer
;
2513 p
= bgp_dest_get_prefix(dest
);
2514 afi
= SUBGRP_AFI(subgrp
);
2515 safi
= SUBGRP_SAFI(subgrp
);
2516 bgp
= SUBGRP_INST(subgrp
);
2517 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2520 if (BGP_DEBUG(update
, UPDATE_OUT
))
2521 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2523 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2524 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2525 PEER_STATUS_ORF_WAIT_REFRESH
))
2528 memset(&attr
, 0, sizeof(struct attr
));
2529 /* It's initialized in bgp_announce_check() */
2531 /* Announcement to the subgroup. If the route is filtered withdraw it.
2532 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2533 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2536 advertise
= bgp_check_advertise(bgp
, dest
);
2539 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2541 /* Route is selected, if the route is already installed
2542 * in FIB, then it is advertised
2545 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2548 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2552 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2554 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2559 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2560 * This is called at the end of route processing.
2562 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2564 struct bgp_path_info
*pi
;
2566 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2567 if (BGP_PATH_HOLDDOWN(pi
))
2569 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2570 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2575 * Has the route changed from the RIB's perspective? This is invoked only
2576 * if the route selection returns the same best route as earlier - to
2577 * determine if we need to update zebra or not.
2579 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2581 struct bgp_path_info
*mpinfo
;
2583 /* If this is multipath, check all selected paths for any nexthop
2584 * change or attribute change. Some attribute changes (e.g., community)
2585 * aren't of relevance to the RIB, but we'll update zebra to ensure
2586 * we handle the case of BGP nexthop change. This is the behavior
2587 * when the best path has an attribute change anyway.
2589 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2590 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2591 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2595 * If this is multipath, check all selected paths for any nexthop change
2597 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2598 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2599 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2600 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2604 /* Nothing has changed from the RIB's perspective. */
2608 struct bgp_process_queue
{
2610 STAILQ_HEAD(, bgp_dest
) pqueue
;
2611 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2613 unsigned int queued
;
2616 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2617 safi_t safi
, struct bgp_dest
*dest
,
2618 struct bgp_path_info
*new_select
,
2619 struct bgp_path_info
*old_select
)
2621 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2623 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2626 if (advertise_type5_routes(bgp
, afi
) && new_select
2627 && is_route_injectable_into_evpn(new_select
)) {
2629 /* apply the route-map */
2630 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2631 route_map_result_t ret
;
2632 struct bgp_path_info rmap_path
;
2633 struct bgp_path_info_extra rmap_path_extra
;
2634 struct attr dummy_attr
;
2636 dummy_attr
= *new_select
->attr
;
2638 /* Fill temp path_info */
2639 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2640 new_select
, new_select
->peer
,
2643 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2645 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2648 if (ret
== RMAP_DENYMATCH
) {
2649 bgp_attr_flush(&dummy_attr
);
2650 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2653 bgp_evpn_advertise_type5_route(
2654 bgp
, p
, &dummy_attr
, afi
, safi
);
2656 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2659 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2660 && is_route_injectable_into_evpn(old_select
))
2661 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2665 * old_select = The old best path
2666 * new_select = the new best path
2668 * if (!old_select && new_select)
2669 * We are sending new information on.
2671 * if (old_select && new_select) {
2672 * if (new_select != old_select)
2673 * We have a new best path send a change
2675 * We've received a update with new attributes that needs
2679 * if (old_select && !new_select)
2680 * We have no eligible route that we can announce or the rn
2683 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2684 afi_t afi
, safi_t safi
)
2686 struct bgp_path_info
*new_select
;
2687 struct bgp_path_info
*old_select
;
2688 struct bgp_path_info_pair old_and_new
;
2691 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2693 debug
= bgp_debug_bestpath(dest
);
2696 "%s: bgp delete in progress, ignoring event, p=%pBD",
2700 /* Is it end of initial update? (after startup) */
2702 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2703 sizeof(bgp
->update_delay_zebra_resume_time
));
2705 bgp
->main_zebra_update_hold
= 0;
2706 FOREACH_AFI_SAFI (afi
, safi
) {
2707 if (bgp_fibupd_safi(safi
))
2708 bgp_zebra_announce_table(bgp
, afi
, safi
);
2710 bgp
->main_peers_update_hold
= 0;
2712 bgp_start_routeadv(bgp
);
2716 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2718 debug
= bgp_debug_bestpath(dest
);
2720 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2721 afi2str(afi
), safi2str(safi
));
2723 /* The best path calculation for the route is deferred if
2724 * BGP_NODE_SELECT_DEFER is set
2726 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2727 if (BGP_DEBUG(update
, UPDATE_OUT
))
2728 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2732 /* Best path selection. */
2733 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2735 old_select
= old_and_new
.old
;
2736 new_select
= old_and_new
.new;
2738 /* Do we need to allocate or free labels?
2739 * Right now, since we only deal with per-prefix labels, it is not
2740 * necessary to do this upon changes to best path. Exceptions:
2741 * - label index has changed -> recalculate resulting label
2742 * - path_info sub_type changed -> switch to/from implicit-null
2743 * - no valid label (due to removed static label binding) -> get new one
2745 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2748 || bgp_label_index_differs(new_select
, old_select
)
2749 || new_select
->sub_type
!= old_select
->sub_type
2750 || !bgp_is_valid_label(&dest
->local_label
)) {
2751 /* Enforced penultimate hop popping:
2752 * implicit-null for local routes, aggregate
2753 * and redistributed routes
2755 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2756 || new_select
->sub_type
2757 == BGP_ROUTE_AGGREGATE
2758 || new_select
->sub_type
2759 == BGP_ROUTE_REDISTRIBUTE
) {
2762 BGP_NODE_REGISTERED_FOR_LABEL
)
2765 BGP_NODE_LABEL_REQUESTED
))
2766 bgp_unregister_for_label(dest
);
2767 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2768 &dest
->local_label
);
2769 bgp_set_valid_label(&dest
->local_label
);
2771 bgp_register_for_label(dest
,
2774 } else if (CHECK_FLAG(dest
->flags
,
2775 BGP_NODE_REGISTERED_FOR_LABEL
)
2776 || CHECK_FLAG(dest
->flags
,
2777 BGP_NODE_LABEL_REQUESTED
)) {
2778 bgp_unregister_for_label(dest
);
2780 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2781 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2782 bgp_unregister_for_label(dest
);
2787 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2788 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2789 old_select
, new_select
);
2791 /* If best route remains the same and this is not due to user-initiated
2792 * clear, see exactly what needs to be done.
2794 if (old_select
&& old_select
== new_select
2795 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2796 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2797 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2798 if (bgp_zebra_has_route_changed(old_select
)) {
2799 #ifdef ENABLE_BGP_VNC
2800 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2801 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2803 if (bgp_fibupd_safi(safi
)
2804 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2806 if (new_select
->type
== ZEBRA_ROUTE_BGP
2807 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2808 || new_select
->sub_type
2809 == BGP_ROUTE_IMPORTED
))
2811 bgp_zebra_announce(dest
, p
, old_select
,
2816 /* If there is a change of interest to peers, reannounce the
2818 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2819 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2820 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2821 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2823 /* unicast routes must also be annouced to
2824 * labeled-unicast update-groups */
2825 if (safi
== SAFI_UNICAST
)
2826 group_announce_route(bgp
, afi
,
2827 SAFI_LABELED_UNICAST
, dest
,
2830 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2831 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2834 /* advertise/withdraw type-5 routes */
2835 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2836 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2837 bgp_process_evpn_route_injection(
2838 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2840 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2841 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2842 bgp_zebra_clear_route_change_flags(dest
);
2843 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2847 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2849 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2851 /* bestpath has changed; bump version */
2852 if (old_select
|| new_select
) {
2853 bgp_bump_version(dest
);
2855 if (!bgp
->t_rmap_def_originate_eval
) {
2859 update_group_refresh_default_originate_route_map
,
2860 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2861 &bgp
->t_rmap_def_originate_eval
);
2866 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2869 zlog_debug("%s: setting SELECTED flag", __func__
);
2870 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2871 bgp_path_info_unset_flag(dest
, new_select
,
2872 BGP_PATH_ATTR_CHANGED
);
2873 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2874 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2877 #ifdef ENABLE_BGP_VNC
2878 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2879 if (old_select
!= new_select
) {
2881 vnc_import_bgp_exterior_del_route(bgp
, p
,
2883 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2886 vnc_import_bgp_exterior_add_route(bgp
, p
,
2888 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2894 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2896 /* unicast routes must also be annouced to labeled-unicast update-groups
2898 if (safi
== SAFI_UNICAST
)
2899 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2903 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2904 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2905 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2906 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2907 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2908 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2910 /* if this is an evpn imported type-5 prefix,
2911 * we need to withdraw the route first to clear
2912 * the nh neigh and the RMAC entry.
2915 is_route_parent_evpn(old_select
))
2916 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2918 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2920 /* Withdraw the route from the kernel. */
2921 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2922 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2923 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2924 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2926 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2930 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2933 /* Clear any route change flags. */
2934 bgp_zebra_clear_route_change_flags(dest
);
2936 /* Reap old select bgp_path_info, if it has been removed */
2937 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2938 bgp_path_info_reap(dest
, old_select
);
2940 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2944 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2945 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2947 struct bgp_dest
*dest
;
2949 struct afi_safi_info
*thread_info
;
2951 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
2952 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
2954 thread_info
= THREAD_ARG(t
);
2955 XFREE(MTYPE_TMP
, thread_info
);
2956 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2959 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2960 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2961 get_afi_safi_str(afi
, safi
, false),
2962 bgp
->gr_info
[afi
][safi
].gr_deferred
);
2965 /* Process the route list */
2966 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
2967 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
2968 dest
= bgp_route_next(dest
)) {
2969 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
2972 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2973 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
2974 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2976 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
2977 bgp_dest_unlock_node(dest
);
2982 /* Send EOR message when all routes are processed */
2983 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
2984 bgp_send_delayed_eor(bgp
);
2985 /* Send route processing complete message to RIB */
2986 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2987 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2991 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2993 thread_info
->afi
= afi
;
2994 thread_info
->safi
= safi
;
2995 thread_info
->bgp
= bgp
;
2997 /* If there are more routes to be processed, start the
3000 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3001 BGP_ROUTE_SELECT_DELAY
,
3002 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3006 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3008 struct bgp_process_queue
*pqnode
= data
;
3009 struct bgp
*bgp
= pqnode
->bgp
;
3010 struct bgp_table
*table
;
3011 struct bgp_dest
*dest
;
3014 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3015 bgp_process_main_one(bgp
, NULL
, 0, 0);
3016 /* should always have dedicated wq call */
3017 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3021 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3022 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3023 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3024 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3025 table
= bgp_dest_table(dest
);
3026 /* note, new DESTs may be added as part of processing */
3027 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3029 bgp_dest_unlock_node(dest
);
3030 bgp_table_unlock(table
);
3036 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3038 struct bgp_process_queue
*pqnode
= data
;
3040 bgp_unlock(pqnode
->bgp
);
3042 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3045 void bgp_process_queue_init(struct bgp
*bgp
)
3047 if (!bgp
->process_queue
) {
3050 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3051 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3054 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3055 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3056 bgp
->process_queue
->spec
.max_retries
= 0;
3057 bgp
->process_queue
->spec
.hold
= 50;
3058 /* Use a higher yield value of 50ms for main queue processing */
3059 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3062 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3064 struct bgp_process_queue
*pqnode
;
3066 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3067 sizeof(struct bgp_process_queue
));
3069 /* unlocked in bgp_processq_del */
3070 pqnode
->bgp
= bgp_lock(bgp
);
3071 STAILQ_INIT(&pqnode
->pqueue
);
3076 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3078 #define ARBITRARY_PROCESS_QLEN 10000
3079 struct work_queue
*wq
= bgp
->process_queue
;
3080 struct bgp_process_queue
*pqnode
;
3081 int pqnode_reuse
= 0;
3083 /* already scheduled for processing? */
3084 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3087 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3090 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3091 if (BGP_DEBUG(update
, UPDATE_OUT
))
3092 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3100 /* Add route nodes to an existing work queue item until reaching the
3101 limit only if is from the same BGP view and it's not an EOIU marker
3103 if (work_queue_item_count(wq
)) {
3104 struct work_queue_item
*item
= work_queue_last_item(wq
);
3105 pqnode
= item
->data
;
3107 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3108 || pqnode
->bgp
!= bgp
3109 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3110 pqnode
= bgp_processq_alloc(bgp
);
3114 pqnode
= bgp_processq_alloc(bgp
);
3115 /* all unlocked in bgp_process_wq */
3116 bgp_table_lock(bgp_dest_table(dest
));
3118 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3119 bgp_dest_lock_node(dest
);
3121 /* can't be enqueued twice */
3122 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3123 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3127 work_queue_add(wq
, pqnode
);
3132 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3134 struct bgp_process_queue
*pqnode
;
3136 if (bgp
->process_queue
== NULL
)
3139 pqnode
= bgp_processq_alloc(bgp
);
3141 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3142 work_queue_add(bgp
->process_queue
, pqnode
);
3145 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3149 peer
= THREAD_ARG(thread
);
3150 peer
->t_pmax_restart
= NULL
;
3152 if (bgp_debug_neighbor_events(peer
))
3154 "%s Maximum-prefix restart timer expired, restore peering",
3157 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3158 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3163 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3167 bool filtered
= false;
3168 struct bgp_dest
*dest
;
3169 struct bgp_adj_in
*ain
;
3170 struct attr attr
= {};
3171 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3173 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3174 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3175 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3179 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3183 if (bgp_input_modifier(
3184 peer
, rn_p
, &attr
, afi
, safi
,
3185 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3193 bgp_attr_undup(&attr
, ain
->attr
);
3200 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3204 iana_safi_t pkt_safi
;
3205 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3206 PEER_FLAG_MAX_PREFIX_FORCE
))
3207 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3208 + peer
->pcount
[afi
][safi
]
3209 : peer
->pcount
[afi
][safi
];
3211 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3214 if (pcount
> peer
->pmax
[afi
][safi
]) {
3215 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3216 PEER_STATUS_PREFIX_LIMIT
)
3221 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3222 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3223 peer
->pmax
[afi
][safi
]);
3224 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3226 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3227 PEER_FLAG_MAX_PREFIX_WARNING
))
3230 /* Convert AFI, SAFI to values for packet. */
3231 pkt_afi
= afi_int2iana(afi
);
3232 pkt_safi
= safi_int2iana(safi
);
3236 ndata
[0] = (pkt_afi
>> 8);
3238 ndata
[2] = pkt_safi
;
3239 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3240 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3241 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3242 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3244 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3245 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3246 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3250 /* Dynamic peers will just close their connection. */
3251 if (peer_dynamic_neighbor(peer
))
3254 /* restart timer start */
3255 if (peer
->pmax_restart
[afi
][safi
]) {
3256 peer
->v_pmax_restart
=
3257 peer
->pmax_restart
[afi
][safi
] * 60;
3259 if (bgp_debug_neighbor_events(peer
))
3261 "%s Maximum-prefix restart timer started for %d secs",
3262 peer
->host
, peer
->v_pmax_restart
);
3264 BGP_TIMER_ON(peer
->t_pmax_restart
,
3265 bgp_maximum_prefix_restart_timer
,
3266 peer
->v_pmax_restart
);
3271 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3272 PEER_STATUS_PREFIX_LIMIT
);
3275 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3276 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3277 PEER_STATUS_PREFIX_THRESHOLD
)
3282 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3283 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3284 peer
->pmax
[afi
][safi
]);
3285 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3286 PEER_STATUS_PREFIX_THRESHOLD
);
3288 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3289 PEER_STATUS_PREFIX_THRESHOLD
);
3293 /* Unconditionally remove the route from the RIB, without taking
3294 * damping into consideration (eg, because the session went down)
3296 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3297 struct peer
*peer
, afi_t afi
, safi_t safi
)
3300 struct bgp
*bgp
= NULL
;
3301 bool delete_route
= false;
3303 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3306 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3307 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3309 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3312 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3313 delete_route
= true;
3314 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3315 delete_route
= true;
3317 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3318 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3319 bgp
= pi
->peer
->bgp
;
3320 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3325 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3326 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3329 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3330 struct peer
*peer
, afi_t afi
, safi_t safi
,
3331 struct prefix_rd
*prd
)
3333 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3335 /* apply dampening, if result is suppressed, we'll be retaining
3336 * the bgp_path_info in the RIB for historical reference.
3338 if (peer
->sort
== BGP_PEER_EBGP
) {
3339 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3340 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3341 == BGP_DAMP_SUPPRESSED
) {
3342 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3349 #ifdef ENABLE_BGP_VNC
3350 if (safi
== SAFI_MPLS_VPN
) {
3351 struct bgp_dest
*pdest
= NULL
;
3352 struct bgp_table
*table
= NULL
;
3354 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3355 (struct prefix
*)prd
);
3356 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3357 table
= bgp_dest_get_bgp_table_info(pdest
);
3359 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3360 peer
->bgp
, prd
, table
, p
, pi
);
3362 bgp_dest_unlock_node(pdest
);
3364 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3365 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3367 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3368 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3373 /* If this is an EVPN route, process for un-import. */
3374 if (safi
== SAFI_EVPN
)
3375 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3377 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3380 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3381 struct peer
*peer
, struct attr
*attr
,
3382 struct bgp_dest
*dest
)
3384 struct bgp_path_info
*new;
3386 /* Make new BGP info. */
3387 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3389 new->instance
= instance
;
3390 new->sub_type
= sub_type
;
3393 new->uptime
= bgp_clock();
3398 static void overlay_index_update(struct attr
*attr
,
3399 union gw_addr
*gw_ip
)
3403 if (gw_ip
== NULL
) {
3404 struct bgp_route_evpn eo
;
3406 memset(&eo
, 0, sizeof(eo
));
3407 bgp_attr_set_evpn_overlay(attr
, &eo
);
3409 struct bgp_route_evpn eo
= {.gw_ip
= *gw_ip
};
3411 bgp_attr_set_evpn_overlay(attr
, &eo
);
3415 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3416 union gw_addr
*gw_ip
)
3418 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3419 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3425 if (afi
!= AFI_L2VPN
)
3428 path_gw_ip
= eo
->gw_ip
;
3430 if (gw_ip
== NULL
) {
3431 memset(&temp
, 0, sizeof(temp
));
3432 path_gw_ip_remote
= &temp
.ip
;
3434 path_gw_ip_remote
= gw_ip
;
3436 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3439 /* Check if received nexthop is valid or not. */
3440 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3441 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3442 struct bgp_dest
*dest
)
3445 bool is_bgp_static_route
=
3446 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3450 * Only validated for unicast and multicast currently.
3451 * Also valid for EVPN where the nexthop is an IP address.
3452 * If we are a bgp static route being checked then there is
3453 * no need to check to see if the nexthop is martian as
3454 * that it should be ok.
3456 if (is_bgp_static_route
||
3457 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3460 /* If NEXT_HOP is present, validate it. */
3461 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3462 if (attr
->nexthop
.s_addr
== INADDR_ANY
3463 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3464 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3468 /* If MP_NEXTHOP is present, validate it. */
3469 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3470 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3471 * it is not an IPv6 link-local address.
3473 * If we receive an UPDATE with nexthop length set to 32 bytes
3474 * we shouldn't discard an UPDATE if it's set to (::).
3475 * The link-local (2st) is validated along the code path later.
3477 if (attr
->mp_nexthop_len
) {
3478 switch (attr
->mp_nexthop_len
) {
3479 case BGP_ATTR_NHLEN_IPV4
:
3480 case BGP_ATTR_NHLEN_VPNV4
:
3481 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3483 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3484 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3488 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3489 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3490 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3491 &attr
->mp_nexthop_global
)
3492 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3493 || IN6_IS_ADDR_MULTICAST(
3494 &attr
->mp_nexthop_global
)
3495 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3498 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3499 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3500 || IN6_IS_ADDR_MULTICAST(
3501 &attr
->mp_nexthop_global
)
3502 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3515 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3517 struct community
*old
;
3518 struct community
*new;
3519 struct community
*merge
;
3520 struct community
*no_export
;
3522 old
= attr
->community
;
3523 no_export
= community_str2com("no-export");
3528 merge
= community_merge(community_dup(old
), no_export
);
3531 community_free(&old
);
3533 new = community_uniq_sort(merge
);
3534 community_free(&merge
);
3536 new = community_dup(no_export
);
3539 community_free(&no_export
);
3541 attr
->community
= new;
3542 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3545 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3546 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3547 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3548 uint32_t num_labels
, int soft_reconfig
,
3549 struct bgp_route_evpn
*evpn
)
3552 int aspath_loop_count
= 0;
3553 struct bgp_dest
*dest
;
3555 struct attr new_attr
;
3556 struct attr
*attr_new
;
3557 struct bgp_path_info
*pi
;
3558 struct bgp_path_info
*new;
3559 struct bgp_path_info_extra
*extra
;
3561 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3563 int do_loop_check
= 1;
3564 int has_valid_label
= 0;
3566 uint8_t pi_type
= 0;
3567 uint8_t pi_sub_type
= 0;
3569 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3570 char pfxprint
[PREFIX2STR_BUFFER
];
3572 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3573 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3577 #ifdef ENABLE_BGP_VNC
3578 int vnc_implicit_withdraw
= 0;
3582 memset(&new_attr
, 0, sizeof(struct attr
));
3583 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3584 new_attr
.label
= MPLS_INVALID_LABEL
;
3587 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3588 /* TODO: Check to see if we can get rid of "is_valid_label" */
3589 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3590 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3592 has_valid_label
= bgp_is_valid_label(label
);
3594 if (has_valid_label
)
3595 assert(label
!= NULL
);
3597 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3599 * Suppress fib is enabled
3600 * BGP_OPT_NO_FIB is not enabled
3601 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3602 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3604 if (BGP_SUPPRESS_FIB_ENABLED(bgp
) &&
3605 (sub_type
== BGP_ROUTE_NORMAL
) &&
3606 (!bgp_option_check(BGP_OPT_NO_FIB
)) &&
3607 (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3608 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3610 /* When peer's soft reconfiguration enabled. Record input packet in
3613 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3614 && peer
!= bgp
->peer_self
)
3615 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3617 /* Check previously received route. */
3618 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3619 if (pi
->peer
== peer
&& pi
->type
== type
3620 && pi
->sub_type
== sub_type
3621 && pi
->addpath_rx_id
== addpath_id
)
3624 /* AS path local-as loop check. */
3625 if (peer
->change_local_as
) {
3626 if (peer
->allowas_in
[afi
][safi
])
3627 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3628 else if (!CHECK_FLAG(peer
->flags
,
3629 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3630 aspath_loop_count
= 1;
3632 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3633 > aspath_loop_count
) {
3634 peer
->stat_pfx_aspath_loop
++;
3635 reason
= "as-path contains our own AS A;";
3640 /* If the peer is configured for "allowas-in origin" and the last ASN in
3642 * as-path is our ASN then we do not need to call aspath_loop_check
3644 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3645 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3648 /* AS path loop check. */
3649 if (do_loop_check
) {
3650 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3651 > peer
->allowas_in
[afi
][safi
]
3652 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3653 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3654 > peer
->allowas_in
[afi
][safi
])) {
3655 peer
->stat_pfx_aspath_loop
++;
3656 reason
= "as-path contains our own AS;";
3661 /* Route reflector originator ID check. */
3662 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3663 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3664 peer
->stat_pfx_originator_loop
++;
3665 reason
= "originator is us;";
3669 /* Route reflector cluster ID check. */
3670 if (bgp_cluster_filter(peer
, attr
)) {
3671 peer
->stat_pfx_cluster_loop
++;
3672 reason
= "reflected from the same cluster;";
3676 /* Apply incoming filter. */
3677 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3678 peer
->stat_pfx_filter
++;
3683 /* RFC 8212 to prevent route leaks.
3684 * This specification intends to improve this situation by requiring the
3685 * explicit configuration of both BGP Import and Export Policies for any
3686 * External BGP (EBGP) session such as customers, peers, or
3687 * confederation boundaries for all enabled address families. Through
3688 * codification of the aforementioned requirement, operators will
3689 * benefit from consistent behavior across different BGP
3692 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3693 if (!bgp_inbound_policy_exists(peer
,
3694 &peer
->filter
[afi
][safi
])) {
3695 reason
= "inbound policy missing";
3699 /* draft-ietf-idr-deprecate-as-set-confed-set
3700 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3701 * Eventually, This document (if approved) updates RFC 4271
3702 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3703 * and obsoletes RFC 6472.
3705 if (peer
->bgp
->reject_as_sets
)
3706 if (aspath_check_as_sets(attr
->aspath
)) {
3708 "as-path contains AS_SET or AS_CONFED_SET type;";
3714 /* Apply incoming route-map.
3715 * NB: new_attr may now contain newly allocated values from route-map
3717 * commands, so we need bgp_attr_flush in the error paths, until we
3719 * the attr (which takes over the memory references) */
3720 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3723 peer
->stat_pfx_filter
++;
3724 reason
= "route-map;";
3725 bgp_attr_flush(&new_attr
);
3729 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3730 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3731 /* remove from RIB previous entry */
3732 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3735 if (peer
->sort
== BGP_PEER_EBGP
) {
3738 * A BGP speaker receiving an announcement tagged with the
3739 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3740 * NO_EXPORT community as defined in RFC1997, or a
3741 * similar community, to prevent propagation of the
3742 * prefix outside the local AS. The community to prevent
3743 * propagation SHOULD be chosen according to the operator's
3746 if (new_attr
.community
3747 && community_include(new_attr
.community
,
3748 COMMUNITY_BLACKHOLE
))
3749 bgp_attr_add_no_export_community(&new_attr
);
3751 /* If we receive the graceful-shutdown community from an eBGP
3752 * peer we must lower local-preference */
3753 if (new_attr
.community
3754 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3755 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3756 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3758 /* If graceful-shutdown is configured then add the GSHUT
3759 * community to all paths received from eBGP peers */
3760 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3761 bgp_attr_add_gshut_community(&new_attr
);
3766 pi_sub_type
= pi
->sub_type
;
3769 /* next hop check. */
3770 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3771 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3773 peer
->stat_pfx_nh_invalid
++;
3774 reason
= "martian or self next-hop;";
3775 bgp_attr_flush(&new_attr
);
3779 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3780 peer
->stat_pfx_nh_invalid
++;
3781 reason
= "self mac;";
3785 /* Update Overlay Index */
3786 if (afi
== AFI_L2VPN
) {
3787 overlay_index_update(&new_attr
,
3788 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3791 attr_new
= bgp_attr_intern(&new_attr
);
3793 /* If maximum prefix count is configured and current prefix
3796 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3799 /* If the update is implicit withdraw. */
3801 pi
->uptime
= bgp_clock();
3802 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3804 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3806 /* Same attribute comes in. */
3807 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3809 && (!has_valid_label
3810 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3811 num_labels
* sizeof(mpls_label_t
))
3813 && (overlay_index_equal(
3815 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3816 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3817 && peer
->sort
== BGP_PEER_EBGP
3818 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3819 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3820 bgp_debug_rdpfxpath2str(
3821 afi
, safi
, prd
, p
, label
,
3822 num_labels
, addpath_id
? 1 : 0,
3823 addpath_id
, pfx_buf
,
3825 zlog_debug("%s rcvd %s", peer
->host
,
3829 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3830 != BGP_DAMP_SUPPRESSED
) {
3831 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3833 bgp_process(bgp
, dest
, afi
, safi
);
3835 } else /* Duplicate - odd */
3837 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3838 if (!peer
->rcvd_attr_printed
) {
3840 "%s rcvd UPDATE w/ attr: %s",
3842 peer
->rcvd_attr_str
);
3843 peer
->rcvd_attr_printed
= 1;
3846 bgp_debug_rdpfxpath2str(
3847 afi
, safi
, prd
, p
, label
,
3848 num_labels
, addpath_id
? 1 : 0,
3849 addpath_id
, pfx_buf
,
3852 "%s rcvd %s...duplicate ignored",
3853 peer
->host
, pfx_buf
);
3856 /* graceful restart STALE flag unset. */
3857 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3858 bgp_path_info_unset_flag(
3859 dest
, pi
, BGP_PATH_STALE
);
3860 bgp_dest_set_defer_flag(dest
, false);
3861 bgp_process(bgp
, dest
, afi
, safi
);
3865 bgp_dest_unlock_node(dest
);
3866 bgp_attr_unintern(&attr_new
);
3871 /* Withdraw/Announce before we fully processed the withdraw */
3872 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3873 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3874 bgp_debug_rdpfxpath2str(
3875 afi
, safi
, prd
, p
, label
, num_labels
,
3876 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3879 "%s rcvd %s, flapped quicker than processing",
3880 peer
->host
, pfx_buf
);
3883 bgp_path_info_restore(dest
, pi
);
3886 /* Received Logging. */
3887 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3888 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3889 num_labels
, addpath_id
? 1 : 0,
3890 addpath_id
, pfx_buf
,
3892 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3895 /* graceful restart STALE flag unset. */
3896 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3897 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3898 bgp_dest_set_defer_flag(dest
, false);
3901 /* The attribute is changed. */
3902 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3904 /* implicit withdraw, decrement aggregate and pcount here.
3905 * only if update is accepted, they'll increment below.
3907 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3909 /* Update bgp route dampening information. */
3910 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3911 && peer
->sort
== BGP_PEER_EBGP
) {
3912 /* This is implicit withdraw so we should update
3913 * dampening information.
3915 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3916 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3918 #ifdef ENABLE_BGP_VNC
3919 if (safi
== SAFI_MPLS_VPN
) {
3920 struct bgp_dest
*pdest
= NULL
;
3921 struct bgp_table
*table
= NULL
;
3923 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3924 (struct prefix
*)prd
);
3925 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3926 table
= bgp_dest_get_bgp_table_info(pdest
);
3928 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3929 bgp
, prd
, table
, p
, pi
);
3931 bgp_dest_unlock_node(pdest
);
3933 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3934 && (safi
== SAFI_UNICAST
)) {
3935 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3937 * Implicit withdraw case.
3939 ++vnc_implicit_withdraw
;
3940 vnc_import_bgp_del_route(bgp
, p
, pi
);
3941 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3946 /* Special handling for EVPN update of an existing route. If the
3947 * extended community attribute has changed, we need to
3949 * the route using its existing extended community. It will be
3950 * subsequently processed for import with the new extended
3953 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3956 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3958 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3961 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3962 attr_new
->ecommunity
);
3964 if (bgp_debug_update(peer
, p
, NULL
, 1))
3966 "Change in EXT-COMM, existing %s new %s",
3968 pi
->attr
->ecommunity
),
3970 attr_new
->ecommunity
));
3971 if (safi
== SAFI_EVPN
)
3972 bgp_evpn_unimport_route(
3973 bgp
, afi
, safi
, p
, pi
);
3974 else /* SAFI_MPLS_VPN */
3975 vpn_leak_to_vrf_withdraw(bgp
,
3981 /* Update to new attribute. */
3982 bgp_attr_unintern(&pi
->attr
);
3983 pi
->attr
= attr_new
;
3985 /* Update MPLS label */
3986 if (has_valid_label
) {
3987 extra
= bgp_path_info_extra_get(pi
);
3988 if (extra
->label
!= label
) {
3989 memcpy(&extra
->label
, label
,
3990 num_labels
* sizeof(mpls_label_t
));
3991 extra
->num_labels
= num_labels
;
3993 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3994 bgp_set_valid_label(&extra
->label
[0]);
3997 /* Update SRv6 SID */
3998 if (attr
->srv6_l3vpn
) {
3999 extra
= bgp_path_info_extra_get(pi
);
4000 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4001 sid_copy(&extra
->sid
[0],
4002 &attr
->srv6_l3vpn
->sid
);
4003 extra
->num_sids
= 1;
4005 } else if (attr
->srv6_vpn
) {
4006 extra
= bgp_path_info_extra_get(pi
);
4007 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4008 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4009 extra
->num_sids
= 1;
4013 #ifdef ENABLE_BGP_VNC
4014 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4015 && (safi
== SAFI_UNICAST
)) {
4016 if (vnc_implicit_withdraw
) {
4018 * Add back the route with its new attributes
4020 * The route is still selected, until the route
4022 * queued by bgp_process actually runs. We have
4024 * update to the VNC side immediately to avoid
4026 * configuration changes (e.g., route-map
4028 * trigger re-importation of the entire RIB.
4030 vnc_import_bgp_add_route(bgp
, p
, pi
);
4031 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4036 /* Update bgp route dampening information. */
4037 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4038 && peer
->sort
== BGP_PEER_EBGP
) {
4039 /* Now we do normal update dampening. */
4040 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4041 if (ret
== BGP_DAMP_SUPPRESSED
) {
4042 bgp_dest_unlock_node(dest
);
4047 /* Nexthop reachability check - for unicast and
4048 * labeled-unicast.. */
4049 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4050 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4051 || (safi
== SAFI_EVPN
&&
4052 bgp_evpn_is_prefix_nht_supported(p
))) {
4053 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4054 && peer
->ttl
== BGP_DEFAULT_TTL
4055 && !CHECK_FLAG(peer
->flags
,
4056 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4057 && !CHECK_FLAG(bgp
->flags
,
4058 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4063 struct bgp
*bgp_nexthop
= bgp
;
4065 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4066 bgp_nexthop
= pi
->extra
->bgp_orig
;
4068 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4070 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4071 safi
, pi
, NULL
, connected
)
4072 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4073 bgp_path_info_set_flag(dest
, pi
,
4076 if (BGP_DEBUG(nht
, NHT
)) {
4077 zlog_debug("%s(%pI4): NH unresolved",
4079 (in_addr_t
*)&attr_new
->nexthop
);
4081 bgp_path_info_unset_flag(dest
, pi
,
4085 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4087 #ifdef ENABLE_BGP_VNC
4088 if (safi
== SAFI_MPLS_VPN
) {
4089 struct bgp_dest
*pdest
= NULL
;
4090 struct bgp_table
*table
= NULL
;
4092 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4093 (struct prefix
*)prd
);
4094 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4095 table
= bgp_dest_get_bgp_table_info(pdest
);
4097 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4098 bgp
, prd
, table
, p
, pi
);
4100 bgp_dest_unlock_node(pdest
);
4104 /* If this is an EVPN route and some attribute has changed,
4106 * route for import. If the extended community has changed, we
4108 * have done the un-import earlier and the import would result
4110 * route getting injected into appropriate L2 VNIs. If it is
4112 * some other attribute change, the import will result in
4114 * the attributes for the route in the VNI(s).
4116 if (safi
== SAFI_EVPN
&& !same_attr
&&
4117 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4118 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4120 /* Process change. */
4121 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4123 bgp_process(bgp
, dest
, afi
, safi
);
4124 bgp_dest_unlock_node(dest
);
4126 if (SAFI_UNICAST
== safi
4127 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4128 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4130 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4132 if ((SAFI_MPLS_VPN
== safi
)
4133 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4135 vpn_leak_to_vrf_update(bgp
, pi
);
4138 #ifdef ENABLE_BGP_VNC
4139 if (SAFI_MPLS_VPN
== safi
) {
4140 mpls_label_t label_decoded
= decode_label(label
);
4142 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4143 type
, sub_type
, &label_decoded
);
4145 if (SAFI_ENCAP
== safi
) {
4146 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4147 type
, sub_type
, NULL
);
4152 } // End of implicit withdraw
4154 /* Received Logging. */
4155 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4156 if (!peer
->rcvd_attr_printed
) {
4157 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4158 peer
->rcvd_attr_str
);
4159 peer
->rcvd_attr_printed
= 1;
4162 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4163 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4165 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4168 /* Make new BGP info. */
4169 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4171 /* Update MPLS label */
4172 if (has_valid_label
) {
4173 extra
= bgp_path_info_extra_get(new);
4174 if (extra
->label
!= label
) {
4175 memcpy(&extra
->label
, label
,
4176 num_labels
* sizeof(mpls_label_t
));
4177 extra
->num_labels
= num_labels
;
4179 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4180 bgp_set_valid_label(&extra
->label
[0]);
4183 /* Update SRv6 SID */
4184 if (safi
== SAFI_MPLS_VPN
) {
4185 extra
= bgp_path_info_extra_get(new);
4186 if (attr
->srv6_l3vpn
) {
4187 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4188 extra
->num_sids
= 1;
4189 } else if (attr
->srv6_vpn
) {
4190 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4191 extra
->num_sids
= 1;
4195 /* Update Overlay Index */
4196 if (afi
== AFI_L2VPN
) {
4197 overlay_index_update(new->attr
,
4198 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4200 /* Nexthop reachability check. */
4201 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4202 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4203 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4204 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4205 && peer
->ttl
== BGP_DEFAULT_TTL
4206 && !CHECK_FLAG(peer
->flags
,
4207 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4208 && !CHECK_FLAG(bgp
->flags
,
4209 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4214 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4216 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4218 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4219 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4221 if (BGP_DEBUG(nht
, NHT
)) {
4222 char buf1
[INET6_ADDRSTRLEN
];
4224 (const void *)&attr_new
->nexthop
,
4225 buf1
, INET6_ADDRSTRLEN
);
4226 zlog_debug("%s(%s): NH unresolved", __func__
,
4229 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4232 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4235 new->addpath_rx_id
= addpath_id
;
4237 /* Increment prefix */
4238 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4240 /* Register new BGP information. */
4241 bgp_path_info_add(dest
, new);
4243 /* route_node_get lock */
4244 bgp_dest_unlock_node(dest
);
4246 #ifdef ENABLE_BGP_VNC
4247 if (safi
== SAFI_MPLS_VPN
) {
4248 struct bgp_dest
*pdest
= NULL
;
4249 struct bgp_table
*table
= NULL
;
4251 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4252 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4253 table
= bgp_dest_get_bgp_table_info(pdest
);
4255 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4256 bgp
, prd
, table
, p
, new);
4258 bgp_dest_unlock_node(pdest
);
4262 /* If this is an EVPN route, process for import. */
4263 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4264 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4266 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4268 /* Process change. */
4269 bgp_process(bgp
, dest
, afi
, safi
);
4271 if (SAFI_UNICAST
== safi
4272 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4273 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4274 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4276 if ((SAFI_MPLS_VPN
== safi
)
4277 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4279 vpn_leak_to_vrf_update(bgp
, new);
4281 #ifdef ENABLE_BGP_VNC
4282 if (SAFI_MPLS_VPN
== safi
) {
4283 mpls_label_t label_decoded
= decode_label(label
);
4285 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4286 sub_type
, &label_decoded
);
4288 if (SAFI_ENCAP
== safi
) {
4289 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4296 /* This BGP update is filtered. Log the reason then update BGP
4299 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4301 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4302 if (!peer
->rcvd_attr_printed
) {
4303 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4304 peer
->rcvd_attr_str
);
4305 peer
->rcvd_attr_printed
= 1;
4308 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4309 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4311 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4312 peer
->host
, pfx_buf
, reason
);
4316 /* If this is an EVPN route, un-import it as it is now filtered.
4318 if (safi
== SAFI_EVPN
)
4319 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4321 if (SAFI_UNICAST
== safi
4322 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4323 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4325 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4327 if ((SAFI_MPLS_VPN
== safi
)
4328 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4330 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4333 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4336 bgp_dest_unlock_node(dest
);
4338 #ifdef ENABLE_BGP_VNC
4340 * Filtered update is treated as an implicit withdrawal (see
4342 * a few lines above)
4344 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4345 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4353 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4354 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4355 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4356 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4359 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4360 struct bgp_dest
*dest
;
4361 struct bgp_path_info
*pi
;
4363 #ifdef ENABLE_BGP_VNC
4364 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4365 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4373 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4375 /* If peer is soft reconfiguration enabled. Record input packet for
4376 * further calculation.
4378 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4379 * routes that are filtered. This tanks out Quagga RS pretty badly due
4381 * the iteration over all RS clients.
4382 * Since we need to remove the entry from adj_in anyway, do that first
4384 * if there was no entry, we don't need to do anything more.
4386 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4387 && peer
!= bgp
->peer_self
)
4388 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4389 peer
->stat_pfx_dup_withdraw
++;
4391 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4392 bgp_debug_rdpfxpath2str(
4393 afi
, safi
, prd
, p
, label
, num_labels
,
4394 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4397 "%s withdrawing route %s not in adj-in",
4398 peer
->host
, pfx_buf
);
4400 bgp_dest_unlock_node(dest
);
4404 /* Lookup withdrawn route. */
4405 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4406 if (pi
->peer
== peer
&& pi
->type
== type
4407 && pi
->sub_type
== sub_type
4408 && pi
->addpath_rx_id
== addpath_id
)
4412 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4413 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4414 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4416 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4420 /* Withdraw specified route from routing table. */
4421 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4422 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4423 if (SAFI_UNICAST
== safi
4424 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4425 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4426 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4428 if ((SAFI_MPLS_VPN
== safi
)
4429 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4431 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4433 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4434 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4435 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4437 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4440 /* Unlock bgp_node_get() lock. */
4441 bgp_dest_unlock_node(dest
);
4446 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4449 struct update_subgroup
*subgrp
;
4450 subgrp
= peer_subgroup(peer
, afi
, safi
);
4451 subgroup_default_originate(subgrp
, withdraw
);
4456 * bgp_stop_announce_route_timer
4458 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4460 if (!paf
->t_announce_route
)
4463 thread_cancel(&paf
->t_announce_route
);
4467 * bgp_announce_route_timer_expired
4469 * Callback that is invoked when the route announcement timer for a
4472 static int bgp_announce_route_timer_expired(struct thread
*t
)
4474 struct peer_af
*paf
;
4477 paf
= THREAD_ARG(t
);
4480 if (peer
->status
!= Established
)
4483 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4486 peer_af_announce_route(paf
, 1);
4488 /* Notify BGP conditional advertisement scanner percess */
4489 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4495 * bgp_announce_route
4497 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4499 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4501 struct peer_af
*paf
;
4502 struct update_subgroup
*subgrp
;
4504 paf
= peer_af_find(peer
, afi
, safi
);
4507 subgrp
= PAF_SUBGRP(paf
);
4510 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4511 * or a refresh has already been triggered.
4513 if (!subgrp
|| paf
->t_announce_route
)
4517 * Start a timer to stagger/delay the announce. This serves
4518 * two purposes - announcement can potentially be combined for
4519 * multiple peers and the announcement doesn't happen in the
4522 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4523 (subgrp
->peer_count
== 1)
4524 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4525 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4526 &paf
->t_announce_route
);
4530 * Announce routes from all AF tables to a peer.
4532 * This should ONLY be called when there is a need to refresh the
4533 * routes to the peer based on a policy change for this peer alone
4534 * or a route refresh request received from the peer.
4535 * The operation will result in splitting the peer from its existing
4536 * subgroups and putting it in new subgroups.
4538 void bgp_announce_route_all(struct peer
*peer
)
4543 FOREACH_AFI_SAFI (afi
, safi
)
4544 bgp_announce_route(peer
, afi
, safi
);
4547 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4548 struct bgp_table
*table
,
4549 struct prefix_rd
*prd
)
4552 struct bgp_dest
*dest
;
4553 struct bgp_adj_in
*ain
;
4556 table
= peer
->bgp
->rib
[afi
][safi
];
4558 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4559 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4560 if (ain
->peer
!= peer
)
4563 struct bgp_path_info
*pi
;
4564 uint32_t num_labels
= 0;
4565 mpls_label_t
*label_pnt
= NULL
;
4566 struct bgp_route_evpn evpn
;
4568 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4570 if (pi
->peer
== peer
)
4573 if (pi
&& pi
->extra
)
4574 num_labels
= pi
->extra
->num_labels
;
4576 label_pnt
= &pi
->extra
->label
[0];
4579 bgp_attr_get_evpn_overlay(pi
->attr
),
4582 memset(&evpn
, 0, sizeof(evpn
));
4584 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4585 ain
->addpath_rx_id
, ain
->attr
, afi
,
4586 safi
, ZEBRA_ROUTE_BGP
,
4587 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4588 num_labels
, 1, &evpn
);
4591 bgp_dest_unlock_node(dest
);
4597 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4599 struct bgp_dest
*dest
;
4600 struct bgp_table
*table
;
4602 if (peer
->status
!= Established
)
4605 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4606 && (safi
!= SAFI_EVPN
))
4607 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4609 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4610 dest
= bgp_route_next(dest
)) {
4611 table
= bgp_dest_get_bgp_table_info(dest
);
4616 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4617 struct prefix_rd prd
;
4619 prd
.family
= AF_UNSPEC
;
4621 memcpy(&prd
.val
, p
->u
.val
, 8);
4623 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4628 struct bgp_clear_node_queue
{
4629 struct bgp_dest
*dest
;
4632 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4634 struct bgp_clear_node_queue
*cnq
= data
;
4635 struct bgp_dest
*dest
= cnq
->dest
;
4636 struct peer
*peer
= wq
->spec
.data
;
4637 struct bgp_path_info
*pi
;
4639 afi_t afi
= bgp_dest_table(dest
)->afi
;
4640 safi_t safi
= bgp_dest_table(dest
)->safi
;
4642 assert(dest
&& peer
);
4645 /* It is possible that we have multiple paths for a prefix from a peer
4646 * if that peer is using AddPath.
4648 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4649 if (pi
->peer
!= peer
)
4652 /* graceful restart STALE flag set. */
4653 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4654 && peer
->nsf
[afi
][safi
])
4655 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4656 PEER_STATUS_ENHANCED_REFRESH
))
4657 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4658 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4659 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4661 /* If this is an EVPN route, process for
4663 if (safi
== SAFI_EVPN
)
4664 bgp_evpn_unimport_route(
4666 bgp_dest_get_prefix(dest
), pi
);
4667 /* Handle withdraw for VRF route-leaking and L3VPN */
4668 if (SAFI_UNICAST
== safi
4669 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4670 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4671 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4674 if (SAFI_MPLS_VPN
== safi
&&
4675 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4676 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4679 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4685 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4687 struct bgp_clear_node_queue
*cnq
= data
;
4688 struct bgp_dest
*dest
= cnq
->dest
;
4689 struct bgp_table
*table
= bgp_dest_table(dest
);
4691 bgp_dest_unlock_node(dest
);
4692 bgp_table_unlock(table
);
4693 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4696 static void bgp_clear_node_complete(struct work_queue
*wq
)
4698 struct peer
*peer
= wq
->spec
.data
;
4700 /* Tickle FSM to start moving again */
4701 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4703 peer_unlock(peer
); /* bgp_clear_route */
4706 static void bgp_clear_node_queue_init(struct peer
*peer
)
4708 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4710 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4711 #undef CLEAR_QUEUE_NAME_LEN
4713 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4714 peer
->clear_node_queue
->spec
.hold
= 10;
4715 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4716 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4717 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4718 peer
->clear_node_queue
->spec
.max_retries
= 0;
4720 /* we only 'lock' this peer reference when the queue is actually active
4722 peer
->clear_node_queue
->spec
.data
= peer
;
4725 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4726 struct bgp_table
*table
)
4728 struct bgp_dest
*dest
;
4729 int force
= peer
->bgp
->process_queue
? 0 : 1;
4732 table
= peer
->bgp
->rib
[afi
][safi
];
4734 /* If still no table => afi/safi isn't configured at all or smth. */
4738 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4739 struct bgp_path_info
*pi
, *next
;
4740 struct bgp_adj_in
*ain
;
4741 struct bgp_adj_in
*ain_next
;
4743 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4744 * queued for every clearing peer, regardless of whether it is
4745 * relevant to the peer at hand.
4747 * Overview: There are 3 different indices which need to be
4748 * scrubbed, potentially, when a peer is removed:
4750 * 1 peer's routes visible via the RIB (ie accepted routes)
4751 * 2 peer's routes visible by the (optional) peer's adj-in index
4752 * 3 other routes visible by the peer's adj-out index
4754 * 3 there is no hurry in scrubbing, once the struct peer is
4755 * removed from bgp->peer, we could just GC such deleted peer's
4756 * adj-outs at our leisure.
4758 * 1 and 2 must be 'scrubbed' in some way, at least made
4759 * invisible via RIB index before peer session is allowed to be
4760 * brought back up. So one needs to know when such a 'search' is
4765 * - there'd be a single global queue or a single RIB walker
4766 * - rather than tracking which route_nodes still need to be
4767 * examined on a peer basis, we'd track which peers still
4770 * Given that our per-peer prefix-counts now should be reliable,
4771 * this may actually be achievable. It doesn't seem to be a huge
4772 * problem at this time,
4774 * It is possible that we have multiple paths for a prefix from
4776 * if that peer is using AddPath.
4780 ain_next
= ain
->next
;
4782 if (ain
->peer
== peer
) {
4783 bgp_adj_in_remove(dest
, ain
);
4784 bgp_dest_unlock_node(dest
);
4790 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4792 if (pi
->peer
!= peer
)
4796 bgp_path_info_reap(dest
, pi
);
4798 struct bgp_clear_node_queue
*cnq
;
4800 /* both unlocked in bgp_clear_node_queue_del */
4801 bgp_table_lock(bgp_dest_table(dest
));
4802 bgp_dest_lock_node(dest
);
4804 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4805 sizeof(struct bgp_clear_node_queue
));
4807 work_queue_add(peer
->clear_node_queue
, cnq
);
4815 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4817 struct bgp_dest
*dest
;
4818 struct bgp_table
*table
;
4820 if (peer
->clear_node_queue
== NULL
)
4821 bgp_clear_node_queue_init(peer
);
4823 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4824 * Idle until it receives a Clearing_Completed event. This protects
4825 * against peers which flap faster than we can we clear, which could
4828 * a) race with routes from the new session being installed before
4829 * clear_route_node visits the node (to delete the route of that
4831 * b) resource exhaustion, clear_route_node likely leads to an entry
4832 * on the process_main queue. Fast-flapping could cause that queue
4836 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4837 * the unlock will happen upon work-queue completion; other wise, the
4838 * unlock happens at the end of this function.
4840 if (!peer
->clear_node_queue
->thread
)
4843 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4844 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4846 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4847 dest
= bgp_route_next(dest
)) {
4848 table
= bgp_dest_get_bgp_table_info(dest
);
4852 bgp_clear_route_table(peer
, afi
, safi
, table
);
4855 /* unlock if no nodes got added to the clear-node-queue. */
4856 if (!peer
->clear_node_queue
->thread
)
4860 void bgp_clear_route_all(struct peer
*peer
)
4865 FOREACH_AFI_SAFI (afi
, safi
)
4866 bgp_clear_route(peer
, afi
, safi
);
4868 #ifdef ENABLE_BGP_VNC
4869 rfapiProcessPeerDown(peer
);
4873 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4875 struct bgp_table
*table
;
4876 struct bgp_dest
*dest
;
4877 struct bgp_adj_in
*ain
;
4878 struct bgp_adj_in
*ain_next
;
4880 table
= peer
->bgp
->rib
[afi
][safi
];
4882 /* It is possible that we have multiple paths for a prefix from a peer
4883 * if that peer is using AddPath.
4885 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4889 ain_next
= ain
->next
;
4891 if (ain
->peer
== peer
) {
4892 bgp_adj_in_remove(dest
, ain
);
4893 bgp_dest_unlock_node(dest
);
4901 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4903 struct bgp_dest
*dest
;
4904 struct bgp_path_info
*pi
;
4905 struct bgp_table
*table
;
4907 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4908 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4909 dest
= bgp_route_next(dest
)) {
4910 struct bgp_dest
*rm
;
4912 /* look for neighbor in tables */
4913 table
= bgp_dest_get_bgp_table_info(dest
);
4917 for (rm
= bgp_table_top(table
); rm
;
4918 rm
= bgp_route_next(rm
))
4919 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4921 if (pi
->peer
!= peer
)
4923 if (!CHECK_FLAG(pi
->flags
,
4927 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4932 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4933 dest
= bgp_route_next(dest
))
4934 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4936 if (pi
->peer
!= peer
)
4938 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4940 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4946 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4948 struct bgp_dest
*dest
, *ndest
;
4949 struct bgp_path_info
*pi
;
4950 struct bgp_table
*table
;
4952 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4953 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4954 dest
= bgp_route_next(dest
)) {
4955 table
= bgp_dest_get_bgp_table_info(dest
);
4959 for (ndest
= bgp_table_top(table
); ndest
;
4960 ndest
= bgp_route_next(ndest
)) {
4961 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
4963 if (pi
->peer
!= peer
)
4967 peer
->af_sflags
[afi
][safi
],
4968 PEER_STATUS_ENHANCED_REFRESH
))
4969 && !CHECK_FLAG(pi
->flags
,
4973 BGP_PATH_UNUSEABLE
)) {
4974 if (bgp_debug_neighbor_events(
4977 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4981 bgp_dest_get_prefix(
4984 bgp_path_info_set_flag(
4992 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4993 dest
= bgp_route_next(dest
)) {
4994 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4996 if (pi
->peer
!= peer
)
4999 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5000 PEER_STATUS_ENHANCED_REFRESH
))
5001 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5002 && !CHECK_FLAG(pi
->flags
,
5003 BGP_PATH_UNUSEABLE
)) {
5004 if (bgp_debug_neighbor_events(peer
))
5006 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5010 bgp_dest_get_prefix(
5013 bgp_path_info_set_flag(dest
, pi
,
5021 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5023 if (peer
->sort
== BGP_PEER_IBGP
)
5026 if (peer
->sort
== BGP_PEER_EBGP
5027 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5028 || FILTER_LIST_OUT_NAME(filter
)
5029 || DISTRIBUTE_OUT_NAME(filter
)))
5034 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5036 if (peer
->sort
== BGP_PEER_IBGP
)
5039 if (peer
->sort
== BGP_PEER_EBGP
5040 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5041 || FILTER_LIST_IN_NAME(filter
)
5042 || DISTRIBUTE_IN_NAME(filter
)))
5047 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5050 struct bgp_dest
*dest
;
5051 struct bgp_path_info
*pi
;
5052 struct bgp_path_info
*next
;
5054 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5055 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5056 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5060 /* Unimport EVPN routes from VRFs */
5061 if (safi
== SAFI_EVPN
)
5062 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5065 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5066 && pi
->type
== ZEBRA_ROUTE_BGP
5067 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5068 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5069 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5071 if (bgp_fibupd_safi(safi
))
5072 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5075 bgp_path_info_reap(dest
, pi
);
5079 /* Delete all kernel routes. */
5080 void bgp_cleanup_routes(struct bgp
*bgp
)
5083 struct bgp_dest
*dest
;
5084 struct bgp_table
*table
;
5086 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5087 if (afi
== AFI_L2VPN
)
5089 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5092 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5094 if (afi
!= AFI_L2VPN
) {
5096 safi
= SAFI_MPLS_VPN
;
5097 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5098 dest
= bgp_route_next(dest
)) {
5099 table
= bgp_dest_get_bgp_table_info(dest
);
5100 if (table
!= NULL
) {
5101 bgp_cleanup_table(bgp
, table
, safi
);
5102 bgp_table_finish(&table
);
5103 bgp_dest_set_bgp_table_info(dest
, NULL
);
5104 bgp_dest_unlock_node(dest
);
5108 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5109 dest
= bgp_route_next(dest
)) {
5110 table
= bgp_dest_get_bgp_table_info(dest
);
5111 if (table
!= NULL
) {
5112 bgp_cleanup_table(bgp
, table
, safi
);
5113 bgp_table_finish(&table
);
5114 bgp_dest_set_bgp_table_info(dest
, NULL
);
5115 bgp_dest_unlock_node(dest
);
5120 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5121 dest
= bgp_route_next(dest
)) {
5122 table
= bgp_dest_get_bgp_table_info(dest
);
5123 if (table
!= NULL
) {
5124 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5125 bgp_table_finish(&table
);
5126 bgp_dest_set_bgp_table_info(dest
, NULL
);
5127 bgp_dest_unlock_node(dest
);
5132 void bgp_reset(void)
5135 bgp_zclient_reset();
5136 access_list_reset();
5137 prefix_list_reset();
5140 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5142 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5143 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5144 PEER_CAP_ADDPATH_AF_TX_RCV
));
5147 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5149 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5150 struct bgp_nlri
*packet
)
5159 int addpath_encoded
;
5160 uint32_t addpath_id
;
5163 lim
= pnt
+ packet
->length
;
5165 safi
= packet
->safi
;
5167 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5169 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5170 syntactic validity. If the field is syntactically incorrect,
5171 then the Error Subcode is set to Invalid Network Field. */
5172 for (; pnt
< lim
; pnt
+= psize
) {
5173 /* Clear prefix structure. */
5174 memset(&p
, 0, sizeof(struct prefix
));
5176 if (addpath_encoded
) {
5178 /* When packet overflow occurs return immediately. */
5179 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5180 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5182 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5183 addpath_id
= ntohl(addpath_id
);
5184 pnt
+= BGP_ADDPATH_ID_LEN
;
5187 /* Fetch prefix length. */
5188 p
.prefixlen
= *pnt
++;
5189 /* afi/safi validity already verified by caller,
5190 * bgp_update_receive */
5191 p
.family
= afi2family(afi
);
5193 /* Prefix length check. */
5194 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5197 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5198 peer
->host
, p
.prefixlen
, packet
->afi
);
5199 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5202 /* Packet size overflow check. */
5203 psize
= PSIZE(p
.prefixlen
);
5205 /* When packet overflow occur return immediately. */
5206 if (pnt
+ psize
> lim
) {
5209 "%s [Error] Update packet error (prefix length %d overflows packet)",
5210 peer
->host
, p
.prefixlen
);
5211 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5214 /* Defensive coding, double-check the psize fits in a struct
5216 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5219 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5220 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5221 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5224 /* Fetch prefix from NLRI packet. */
5225 memcpy(p
.u
.val
, pnt
, psize
);
5227 /* Check address. */
5228 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5229 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5230 /* From RFC4271 Section 6.3:
5232 * If a prefix in the NLRI field is semantically
5234 * (e.g., an unexpected multicast IP address),
5236 * be logged locally, and the prefix SHOULD be
5241 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5242 peer
->host
, &p
.u
.prefix4
);
5247 /* Check address. */
5248 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5249 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5254 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5256 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5261 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5266 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5268 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5275 /* Normal process. */
5277 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5278 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5279 NULL
, NULL
, 0, 0, NULL
);
5281 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5282 safi
, ZEBRA_ROUTE_BGP
,
5283 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5286 /* Do not send BGP notification twice when maximum-prefix count
5288 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5289 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5291 /* Address family configuration mismatch. */
5293 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5296 /* Packet length consistency check. */
5300 "%s [Error] Update packet error (prefix length mismatch with total length)",
5302 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5305 return BGP_NLRI_PARSE_OK
;
5308 static struct bgp_static
*bgp_static_new(void)
5310 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5313 static void bgp_static_free(struct bgp_static
*bgp_static
)
5315 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5316 route_map_counter_decrement(bgp_static
->rmap
.map
);
5318 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5319 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5322 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5323 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5325 struct bgp_dest
*dest
;
5326 struct bgp_path_info
*pi
;
5327 struct bgp_path_info
*new;
5328 struct bgp_path_info rmap_path
;
5330 struct attr
*attr_new
;
5331 route_map_result_t ret
;
5332 #ifdef ENABLE_BGP_VNC
5333 int vnc_implicit_withdraw
= 0;
5338 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5340 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5342 attr
.nexthop
= bgp_static
->igpnexthop
;
5343 attr
.med
= bgp_static
->igpmetric
;
5344 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5346 if (bgp_static
->atomic
)
5347 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5349 /* Store label index, if required. */
5350 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5351 attr
.label_index
= bgp_static
->label_index
;
5352 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5355 /* Apply route-map. */
5356 if (bgp_static
->rmap
.name
) {
5357 struct attr attr_tmp
= attr
;
5359 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5360 rmap_path
.peer
= bgp
->peer_self
;
5361 rmap_path
.attr
= &attr_tmp
;
5363 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5365 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5367 bgp
->peer_self
->rmap_type
= 0;
5369 if (ret
== RMAP_DENYMATCH
) {
5370 /* Free uninterned attribute. */
5371 bgp_attr_flush(&attr_tmp
);
5373 /* Unintern original. */
5374 aspath_unintern(&attr
.aspath
);
5375 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5379 if (bgp_in_graceful_shutdown(bgp
))
5380 bgp_attr_add_gshut_community(&attr_tmp
);
5382 attr_new
= bgp_attr_intern(&attr_tmp
);
5385 if (bgp_in_graceful_shutdown(bgp
))
5386 bgp_attr_add_gshut_community(&attr
);
5388 attr_new
= bgp_attr_intern(&attr
);
5391 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5392 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5393 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5397 if (attrhash_cmp(pi
->attr
, attr_new
)
5398 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5399 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5400 bgp_dest_unlock_node(dest
);
5401 bgp_attr_unintern(&attr_new
);
5402 aspath_unintern(&attr
.aspath
);
5405 /* The attribute is changed. */
5406 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5408 /* Rewrite BGP route information. */
5409 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5410 bgp_path_info_restore(dest
, pi
);
5412 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5413 #ifdef ENABLE_BGP_VNC
5414 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5415 && (safi
== SAFI_UNICAST
)) {
5416 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5418 * Implicit withdraw case.
5419 * We have to do this before pi is
5422 ++vnc_implicit_withdraw
;
5423 vnc_import_bgp_del_route(bgp
, p
, pi
);
5424 vnc_import_bgp_exterior_del_route(
5429 bgp_attr_unintern(&pi
->attr
);
5430 pi
->attr
= attr_new
;
5431 pi
->uptime
= bgp_clock();
5432 #ifdef ENABLE_BGP_VNC
5433 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5434 && (safi
== SAFI_UNICAST
)) {
5435 if (vnc_implicit_withdraw
) {
5436 vnc_import_bgp_add_route(bgp
, p
, pi
);
5437 vnc_import_bgp_exterior_add_route(
5443 /* Nexthop reachability check. */
5444 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5445 && (safi
== SAFI_UNICAST
5446 || safi
== SAFI_LABELED_UNICAST
)) {
5448 struct bgp
*bgp_nexthop
= bgp
;
5450 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5451 bgp_nexthop
= pi
->extra
->bgp_orig
;
5453 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5454 afi
, safi
, pi
, NULL
,
5456 bgp_path_info_set_flag(dest
, pi
,
5459 if (BGP_DEBUG(nht
, NHT
)) {
5460 char buf1
[INET6_ADDRSTRLEN
];
5461 inet_ntop(p
->family
,
5465 "%s(%s): Route not in table, not advertising",
5468 bgp_path_info_unset_flag(
5469 dest
, pi
, BGP_PATH_VALID
);
5472 /* Delete the NHT structure if any, if we're
5474 * enabling/disabling import check. We
5475 * deregister the route
5476 * from NHT to avoid overloading NHT and the
5477 * process interaction
5479 bgp_unlink_nexthop(pi
);
5480 bgp_path_info_set_flag(dest
, pi
,
5483 /* Process change. */
5484 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5485 bgp_process(bgp
, dest
, afi
, safi
);
5487 if (SAFI_UNICAST
== safi
5488 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5490 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5491 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5495 bgp_dest_unlock_node(dest
);
5496 aspath_unintern(&attr
.aspath
);
5501 /* Make new BGP info. */
5502 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5504 /* Nexthop reachability check. */
5505 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5506 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5507 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0))
5508 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5510 if (BGP_DEBUG(nht
, NHT
)) {
5511 char buf1
[INET6_ADDRSTRLEN
];
5512 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5515 "%s(%s): Route not in table, not advertising",
5518 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5521 /* Delete the NHT structure if any, if we're toggling between
5522 * enabling/disabling import check. We deregister the route
5523 * from NHT to avoid overloading NHT and the process interaction
5525 bgp_unlink_nexthop(new);
5527 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5530 /* Aggregate address increment. */
5531 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5533 /* Register new BGP information. */
5534 bgp_path_info_add(dest
, new);
5536 /* route_node_get lock */
5537 bgp_dest_unlock_node(dest
);
5539 /* Process change. */
5540 bgp_process(bgp
, dest
, afi
, safi
);
5542 if (SAFI_UNICAST
== safi
5543 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5544 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5545 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5548 /* Unintern original. */
5549 aspath_unintern(&attr
.aspath
);
5552 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5555 struct bgp_dest
*dest
;
5556 struct bgp_path_info
*pi
;
5558 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5560 /* Check selected route and self inserted route. */
5561 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5562 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5563 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5566 /* Withdraw static BGP route from routing table. */
5568 if (SAFI_UNICAST
== safi
5569 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5570 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5571 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5573 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5574 bgp_unlink_nexthop(pi
);
5575 bgp_path_info_delete(dest
, pi
);
5576 bgp_process(bgp
, dest
, afi
, safi
);
5579 /* Unlock bgp_node_lookup. */
5580 bgp_dest_unlock_node(dest
);
5584 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5586 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5587 afi_t afi
, safi_t safi
,
5588 struct prefix_rd
*prd
)
5590 struct bgp_dest
*dest
;
5591 struct bgp_path_info
*pi
;
5593 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5595 /* Check selected route and self inserted route. */
5596 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5597 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5598 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5601 /* Withdraw static BGP route from routing table. */
5603 #ifdef ENABLE_BGP_VNC
5604 rfapiProcessWithdraw(
5605 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5606 1); /* Kill, since it is an administrative change */
5608 if (SAFI_MPLS_VPN
== safi
5609 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5610 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5612 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5613 bgp_path_info_delete(dest
, pi
);
5614 bgp_process(bgp
, dest
, afi
, safi
);
5617 /* Unlock bgp_node_lookup. */
5618 bgp_dest_unlock_node(dest
);
5621 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5622 struct bgp_static
*bgp_static
, afi_t afi
,
5625 struct bgp_dest
*dest
;
5626 struct bgp_path_info
*new;
5627 struct attr
*attr_new
;
5628 struct attr attr
= {0};
5629 struct bgp_path_info
*pi
;
5630 #ifdef ENABLE_BGP_VNC
5631 mpls_label_t label
= 0;
5633 uint32_t num_labels
= 0;
5638 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5640 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5643 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5645 attr
.nexthop
= bgp_static
->igpnexthop
;
5646 attr
.med
= bgp_static
->igpmetric
;
5647 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5649 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5650 || (safi
== SAFI_ENCAP
)) {
5651 if (afi
== AFI_IP
) {
5652 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5653 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5656 if (afi
== AFI_L2VPN
) {
5657 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5659 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5660 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5661 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5662 sizeof(struct in6_addr
));
5663 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5664 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5665 struct bgp_encap_type_vxlan bet
;
5666 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5667 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5668 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5670 if (bgp_static
->router_mac
) {
5671 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5674 /* Apply route-map. */
5675 if (bgp_static
->rmap
.name
) {
5676 struct attr attr_tmp
= attr
;
5677 struct bgp_path_info rmap_path
;
5678 route_map_result_t ret
;
5680 rmap_path
.peer
= bgp
->peer_self
;
5681 rmap_path
.attr
= &attr_tmp
;
5683 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5685 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5687 bgp
->peer_self
->rmap_type
= 0;
5689 if (ret
== RMAP_DENYMATCH
) {
5690 /* Free uninterned attribute. */
5691 bgp_attr_flush(&attr_tmp
);
5693 /* Unintern original. */
5694 aspath_unintern(&attr
.aspath
);
5695 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5700 attr_new
= bgp_attr_intern(&attr_tmp
);
5702 attr_new
= bgp_attr_intern(&attr
);
5705 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5706 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5707 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5711 memset(&add
, 0, sizeof(union gw_addr
));
5712 if (attrhash_cmp(pi
->attr
, attr_new
)
5713 && overlay_index_equal(afi
, pi
, &add
)
5714 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5715 bgp_dest_unlock_node(dest
);
5716 bgp_attr_unintern(&attr_new
);
5717 aspath_unintern(&attr
.aspath
);
5720 /* The attribute is changed. */
5721 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5723 /* Rewrite BGP route information. */
5724 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5725 bgp_path_info_restore(dest
, pi
);
5727 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5728 bgp_attr_unintern(&pi
->attr
);
5729 pi
->attr
= attr_new
;
5730 pi
->uptime
= bgp_clock();
5731 #ifdef ENABLE_BGP_VNC
5733 label
= decode_label(&pi
->extra
->label
[0]);
5736 /* Process change. */
5737 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5738 bgp_process(bgp
, dest
, afi
, safi
);
5740 if (SAFI_MPLS_VPN
== safi
5741 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5742 vpn_leak_to_vrf_update(bgp
, pi
);
5744 #ifdef ENABLE_BGP_VNC
5745 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5746 pi
->attr
, afi
, safi
, pi
->type
,
5747 pi
->sub_type
, &label
);
5749 bgp_dest_unlock_node(dest
);
5750 aspath_unintern(&attr
.aspath
);
5756 /* Make new BGP info. */
5757 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5759 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5760 new->extra
= bgp_path_info_extra_new();
5762 new->extra
->label
[0] = bgp_static
->label
;
5763 new->extra
->num_labels
= num_labels
;
5765 #ifdef ENABLE_BGP_VNC
5766 label
= decode_label(&bgp_static
->label
);
5769 /* Aggregate address increment. */
5770 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5772 /* Register new BGP information. */
5773 bgp_path_info_add(dest
, new);
5774 /* route_node_get lock */
5775 bgp_dest_unlock_node(dest
);
5777 /* Process change. */
5778 bgp_process(bgp
, dest
, afi
, safi
);
5780 if (SAFI_MPLS_VPN
== safi
5781 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5782 vpn_leak_to_vrf_update(bgp
, new);
5784 #ifdef ENABLE_BGP_VNC
5785 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5786 safi
, new->type
, new->sub_type
, &label
);
5789 /* Unintern original. */
5790 aspath_unintern(&attr
.aspath
);
5793 /* Configure static BGP network. When user don't run zebra, static
5794 route should be installed as valid. */
5795 int bgp_static_set(struct bgp
*bgp
, const char *negate
, struct prefix
*pfx
,
5796 afi_t afi
, safi_t safi
, const char *rmap
, int backdoor
,
5797 uint32_t label_index
, char *errmsg
, size_t errmsg_len
)
5800 struct bgp_static
*bgp_static
;
5801 struct bgp_dest
*dest
;
5802 uint8_t need_update
= 0;
5804 prefix_copy(&p
, pfx
);
5809 /* Set BGP static route configuration. */
5810 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5813 snprintf(errmsg
, errmsg_len
,
5814 "Can't find static route specified\n");
5818 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5820 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5821 && (label_index
!= bgp_static
->label_index
)) {
5822 snprintf(errmsg
, errmsg_len
,
5823 "label-index doesn't match static route\n");
5827 if ((rmap
&& bgp_static
->rmap
.name
)
5828 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5829 snprintf(errmsg
, errmsg_len
,
5830 "route-map name doesn't match static route\n");
5834 /* Update BGP RIB. */
5835 if (!bgp_static
->backdoor
)
5836 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5838 /* Clear configuration. */
5839 bgp_static_free(bgp_static
);
5840 bgp_dest_set_bgp_static_info(dest
, NULL
);
5841 bgp_dest_unlock_node(dest
);
5842 bgp_dest_unlock_node(dest
);
5845 /* Set BGP static route configuration. */
5846 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5847 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5849 /* Configuration change. */
5850 /* Label index cannot be changed. */
5851 if (bgp_static
->label_index
!= label_index
) {
5852 snprintf(errmsg
, errmsg_len
,
5853 "cannot change label-index\n");
5857 /* Check previous routes are installed into BGP. */
5858 if (bgp_static
->valid
5859 && bgp_static
->backdoor
!= backdoor
)
5862 bgp_static
->backdoor
= backdoor
;
5865 XFREE(MTYPE_ROUTE_MAP_NAME
,
5866 bgp_static
->rmap
.name
);
5867 route_map_counter_decrement(
5868 bgp_static
->rmap
.map
);
5869 bgp_static
->rmap
.name
=
5870 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5871 bgp_static
->rmap
.map
=
5872 route_map_lookup_by_name(rmap
);
5873 route_map_counter_increment(
5874 bgp_static
->rmap
.map
);
5876 XFREE(MTYPE_ROUTE_MAP_NAME
,
5877 bgp_static
->rmap
.name
);
5878 route_map_counter_decrement(
5879 bgp_static
->rmap
.map
);
5880 bgp_static
->rmap
.map
= NULL
;
5881 bgp_static
->valid
= 0;
5883 bgp_dest_unlock_node(dest
);
5885 /* New configuration. */
5886 bgp_static
= bgp_static_new();
5887 bgp_static
->backdoor
= backdoor
;
5888 bgp_static
->valid
= 0;
5889 bgp_static
->igpmetric
= 0;
5890 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5891 bgp_static
->label_index
= label_index
;
5894 XFREE(MTYPE_ROUTE_MAP_NAME
,
5895 bgp_static
->rmap
.name
);
5896 route_map_counter_decrement(
5897 bgp_static
->rmap
.map
);
5898 bgp_static
->rmap
.name
=
5899 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5900 bgp_static
->rmap
.map
=
5901 route_map_lookup_by_name(rmap
);
5902 route_map_counter_increment(
5903 bgp_static
->rmap
.map
);
5905 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5908 bgp_static
->valid
= 1;
5910 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5912 if (!bgp_static
->backdoor
)
5913 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5919 void bgp_static_add(struct bgp
*bgp
)
5923 struct bgp_dest
*dest
;
5924 struct bgp_dest
*rm
;
5925 struct bgp_table
*table
;
5926 struct bgp_static
*bgp_static
;
5928 FOREACH_AFI_SAFI (afi
, safi
)
5929 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5930 dest
= bgp_route_next(dest
)) {
5931 if (!bgp_dest_has_bgp_path_info_data(dest
))
5934 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5935 || (safi
== SAFI_EVPN
)) {
5936 table
= bgp_dest_get_bgp_table_info(dest
);
5938 for (rm
= bgp_table_top(table
); rm
;
5939 rm
= bgp_route_next(rm
)) {
5941 bgp_dest_get_bgp_static_info(
5943 bgp_static_update_safi(
5944 bgp
, bgp_dest_get_prefix(rm
),
5945 bgp_static
, afi
, safi
);
5949 bgp
, bgp_dest_get_prefix(dest
),
5950 bgp_dest_get_bgp_static_info(dest
), afi
,
5956 /* Called from bgp_delete(). Delete all static routes from the BGP
5958 void bgp_static_delete(struct bgp
*bgp
)
5962 struct bgp_dest
*dest
;
5963 struct bgp_dest
*rm
;
5964 struct bgp_table
*table
;
5965 struct bgp_static
*bgp_static
;
5967 FOREACH_AFI_SAFI (afi
, safi
)
5968 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5969 dest
= bgp_route_next(dest
)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest
))
5973 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5974 || (safi
== SAFI_EVPN
)) {
5975 table
= bgp_dest_get_bgp_table_info(dest
);
5977 for (rm
= bgp_table_top(table
); rm
;
5978 rm
= bgp_route_next(rm
)) {
5980 bgp_dest_get_bgp_static_info(
5985 bgp_static_withdraw_safi(
5986 bgp
, bgp_dest_get_prefix(rm
),
5988 (struct prefix_rd
*)
5989 bgp_dest_get_prefix(
5991 bgp_static_free(bgp_static
);
5992 bgp_dest_set_bgp_static_info(rm
,
5994 bgp_dest_unlock_node(rm
);
5997 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5998 bgp_static_withdraw(bgp
,
5999 bgp_dest_get_prefix(dest
),
6001 bgp_static_free(bgp_static
);
6002 bgp_dest_set_bgp_static_info(dest
, NULL
);
6003 bgp_dest_unlock_node(dest
);
6008 void bgp_static_redo_import_check(struct bgp
*bgp
)
6012 struct bgp_dest
*dest
;
6013 struct bgp_dest
*rm
;
6014 struct bgp_table
*table
;
6015 struct bgp_static
*bgp_static
;
6017 /* Use this flag to force reprocessing of the route */
6018 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6019 FOREACH_AFI_SAFI (afi
, safi
) {
6020 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6021 dest
= bgp_route_next(dest
)) {
6022 if (!bgp_dest_has_bgp_path_info_data(dest
))
6025 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6026 || (safi
== SAFI_EVPN
)) {
6027 table
= bgp_dest_get_bgp_table_info(dest
);
6029 for (rm
= bgp_table_top(table
); rm
;
6030 rm
= bgp_route_next(rm
)) {
6032 bgp_dest_get_bgp_static_info(
6034 bgp_static_update_safi(
6035 bgp
, bgp_dest_get_prefix(rm
),
6036 bgp_static
, afi
, safi
);
6039 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6040 bgp_static_update(bgp
,
6041 bgp_dest_get_prefix(dest
),
6042 bgp_static
, afi
, safi
);
6046 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6049 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6052 struct bgp_table
*table
;
6053 struct bgp_dest
*dest
;
6054 struct bgp_path_info
*pi
;
6056 /* Do not install the aggregate route if BGP is in the
6057 * process of termination.
6059 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6060 || (bgp
->peer_self
== NULL
))
6063 table
= bgp
->rib
[afi
][safi
];
6064 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6065 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6066 if (pi
->peer
== bgp
->peer_self
6067 && ((pi
->type
== ZEBRA_ROUTE_BGP
6068 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6069 || (pi
->type
!= ZEBRA_ROUTE_BGP
6071 == BGP_ROUTE_REDISTRIBUTE
))) {
6072 bgp_aggregate_decrement(
6073 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6075 bgp_unlink_nexthop(pi
);
6076 bgp_path_info_delete(dest
, pi
);
6077 bgp_process(bgp
, dest
, afi
, safi
);
6084 * Purge all networks and redistributed routes from routing table.
6085 * Invoked upon the instance going down.
6087 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6092 FOREACH_AFI_SAFI (afi
, safi
)
6093 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6098 * Currently this is used to set static routes for VPN and ENCAP.
6099 * I think it can probably be factored with bgp_static_set.
6101 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6102 const char *ip_str
, const char *rd_str
,
6103 const char *label_str
, const char *rmap_str
,
6104 int evpn_type
, const char *esi
, const char *gwip
,
6105 const char *ethtag
, const char *routermac
)
6107 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6110 struct prefix_rd prd
;
6111 struct bgp_dest
*pdest
;
6112 struct bgp_dest
*dest
;
6113 struct bgp_table
*table
;
6114 struct bgp_static
*bgp_static
;
6115 mpls_label_t label
= MPLS_INVALID_LABEL
;
6116 struct prefix gw_ip
;
6118 /* validate ip prefix */
6119 ret
= str2prefix(ip_str
, &p
);
6121 vty_out(vty
, "%% Malformed prefix\n");
6122 return CMD_WARNING_CONFIG_FAILED
;
6125 if ((afi
== AFI_L2VPN
)
6126 && (bgp_build_evpn_prefix(evpn_type
,
6127 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6128 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6129 return CMD_WARNING_CONFIG_FAILED
;
6132 ret
= str2prefix_rd(rd_str
, &prd
);
6134 vty_out(vty
, "%% Malformed rd\n");
6135 return CMD_WARNING_CONFIG_FAILED
;
6139 unsigned long label_val
;
6140 label_val
= strtoul(label_str
, NULL
, 10);
6141 encode_label(label_val
, &label
);
6144 if (safi
== SAFI_EVPN
) {
6145 if (esi
&& str2esi(esi
, NULL
) == 0) {
6146 vty_out(vty
, "%% Malformed ESI\n");
6147 return CMD_WARNING_CONFIG_FAILED
;
6149 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6150 vty_out(vty
, "%% Malformed Router MAC\n");
6151 return CMD_WARNING_CONFIG_FAILED
;
6154 memset(&gw_ip
, 0, sizeof(struct prefix
));
6155 ret
= str2prefix(gwip
, &gw_ip
);
6157 vty_out(vty
, "%% Malformed GatewayIp\n");
6158 return CMD_WARNING_CONFIG_FAILED
;
6160 if ((gw_ip
.family
== AF_INET
6161 && is_evpn_prefix_ipaddr_v6(
6162 (struct prefix_evpn
*)&p
))
6163 || (gw_ip
.family
== AF_INET6
6164 && is_evpn_prefix_ipaddr_v4(
6165 (struct prefix_evpn
*)&p
))) {
6167 "%% GatewayIp family differs with IP prefix\n");
6168 return CMD_WARNING_CONFIG_FAILED
;
6172 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6173 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6174 bgp_dest_set_bgp_table_info(pdest
,
6175 bgp_table_init(bgp
, afi
, safi
));
6176 table
= bgp_dest_get_bgp_table_info(pdest
);
6178 dest
= bgp_node_get(table
, &p
);
6180 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6181 vty_out(vty
, "%% Same network configuration exists\n");
6182 bgp_dest_unlock_node(dest
);
6184 /* New configuration. */
6185 bgp_static
= bgp_static_new();
6186 bgp_static
->backdoor
= 0;
6187 bgp_static
->valid
= 0;
6188 bgp_static
->igpmetric
= 0;
6189 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6190 bgp_static
->label
= label
;
6191 bgp_static
->prd
= prd
;
6194 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6195 route_map_counter_decrement(bgp_static
->rmap
.map
);
6196 bgp_static
->rmap
.name
=
6197 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6198 bgp_static
->rmap
.map
=
6199 route_map_lookup_by_name(rmap_str
);
6200 route_map_counter_increment(bgp_static
->rmap
.map
);
6203 if (safi
== SAFI_EVPN
) {
6205 bgp_static
->eth_s_id
=
6208 str2esi(esi
, bgp_static
->eth_s_id
);
6211 bgp_static
->router_mac
=
6212 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6213 (void)prefix_str2mac(routermac
,
6214 bgp_static
->router_mac
);
6217 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6219 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6221 bgp_static
->valid
= 1;
6222 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6228 /* Configure static BGP network. */
6229 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6230 const char *ip_str
, const char *rd_str
,
6231 const char *label_str
, int evpn_type
, const char *esi
,
6232 const char *gwip
, const char *ethtag
)
6234 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6237 struct prefix_rd prd
;
6238 struct bgp_dest
*pdest
;
6239 struct bgp_dest
*dest
;
6240 struct bgp_table
*table
;
6241 struct bgp_static
*bgp_static
;
6242 mpls_label_t label
= MPLS_INVALID_LABEL
;
6244 /* Convert IP prefix string to struct prefix. */
6245 ret
= str2prefix(ip_str
, &p
);
6247 vty_out(vty
, "%% Malformed prefix\n");
6248 return CMD_WARNING_CONFIG_FAILED
;
6251 if ((afi
== AFI_L2VPN
)
6252 && (bgp_build_evpn_prefix(evpn_type
,
6253 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6254 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6255 return CMD_WARNING_CONFIG_FAILED
;
6257 ret
= str2prefix_rd(rd_str
, &prd
);
6259 vty_out(vty
, "%% Malformed rd\n");
6260 return CMD_WARNING_CONFIG_FAILED
;
6264 unsigned long label_val
;
6265 label_val
= strtoul(label_str
, NULL
, 10);
6266 encode_label(label_val
, &label
);
6269 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6270 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6271 bgp_dest_set_bgp_table_info(pdest
,
6272 bgp_table_init(bgp
, afi
, safi
));
6274 bgp_dest_unlock_node(pdest
);
6275 table
= bgp_dest_get_bgp_table_info(pdest
);
6277 dest
= bgp_node_lookup(table
, &p
);
6280 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6282 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6283 bgp_static_free(bgp_static
);
6284 bgp_dest_set_bgp_static_info(dest
, NULL
);
6285 bgp_dest_unlock_node(dest
);
6286 bgp_dest_unlock_node(dest
);
6288 vty_out(vty
, "%% Can't find the route\n");
6293 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6294 const char *rmap_name
)
6296 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6297 struct bgp_rmap
*rmap
;
6299 rmap
= &bgp
->table_map
[afi
][safi
];
6301 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6302 route_map_counter_decrement(rmap
->map
);
6303 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6304 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6305 route_map_counter_increment(rmap
->map
);
6307 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6308 route_map_counter_decrement(rmap
->map
);
6312 if (bgp_fibupd_safi(safi
))
6313 bgp_zebra_announce_table(bgp
, afi
, safi
);
6318 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6319 const char *rmap_name
)
6321 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6322 struct bgp_rmap
*rmap
;
6324 rmap
= &bgp
->table_map
[afi
][safi
];
6325 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6326 route_map_counter_decrement(rmap
->map
);
6329 if (bgp_fibupd_safi(safi
))
6330 bgp_zebra_announce_table(bgp
, afi
, safi
);
6335 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6338 if (bgp
->table_map
[afi
][safi
].name
) {
6339 vty_out(vty
, " table-map %s\n",
6340 bgp
->table_map
[afi
][safi
].name
);
6344 DEFUN (bgp_table_map
,
6347 "BGP table to RIB route download filter\n"
6348 "Name of the route map\n")
6351 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6352 argv
[idx_word
]->arg
);
6354 DEFUN (no_bgp_table_map
,
6355 no_bgp_table_map_cmd
,
6356 "no table-map WORD",
6358 "BGP table to RIB route download filter\n"
6359 "Name of the route map\n")
6362 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6363 argv
[idx_word
]->arg
);
6366 DEFPY_YANG (bgp_network
, bgp_network_cmd
,
6368 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6369 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6370 backdoor$backdoor}]",
6372 "Specify a network to announce via BGP\n"
6377 "Route-map to modify the attributes\n"
6378 "Name of the route map\n"
6379 "Label index to associate with the prefix\n"
6380 "Label index value\n"
6381 "Specify a BGP backdoor route\n")
6383 char addr_prefix_str
[PREFIX_STRLEN
];
6384 char base_xpath
[XPATH_MAXLEN
];
6391 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6394 vty_out(vty
, "%% Inconsistent address and mask\n");
6395 return CMD_WARNING_CONFIG_FAILED
;
6399 afi
= bgp_node_afi(vty
);
6400 safi
= bgp_node_safi(vty
);
6403 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6405 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6408 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6409 NB_OP_CREATE
, map_name
);
6411 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6412 NB_OP_DESTROY
, NULL
);
6414 if (label_index_str
)
6415 nb_cli_enqueue_change(vty
, "./label-index",
6416 NB_OP_MODIFY
, label_index_str
);
6418 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6419 backdoor
? "true" : "false");
6423 base_xpath
, sizeof(base_xpath
),
6424 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6425 yang_afi_safi_value2identity(afi
, safi
),
6426 bgp_afi_safi_get_container_str(afi
, safi
),
6427 address_str
? addr_prefix_str
: prefix_str
);
6429 return nb_cli_apply_changes(vty
, base_xpath
);
6432 DEFPY_YANG (ipv6_bgp_network
,
6433 ipv6_bgp_network_cmd
,
6434 "[no] network X:X::X:X/M$prefix \
6435 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6437 "Specify a network to announce via BGP\n"
6439 "Route-map to modify the attributes\n"
6440 "Name of the route map\n"
6441 "Label index to associate with the prefix\n"
6442 "Label index value\n")
6444 char base_xpath
[XPATH_MAXLEN
];
6448 afi
= bgp_node_afi(vty
);
6449 safi
= bgp_node_safi(vty
);
6452 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6454 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6457 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6458 NB_OP_MODIFY
, map_name
);
6460 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6461 NB_OP_DESTROY
, NULL
);
6463 if (label_index_str
)
6464 nb_cli_enqueue_change(vty
, "./label-index",
6465 NB_OP_MODIFY
, label_index_str
);
6469 base_xpath
, sizeof(base_xpath
),
6470 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6471 yang_afi_safi_value2identity(afi
, safi
),
6472 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6474 return nb_cli_apply_changes(vty
, base_xpath
);
6477 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6478 struct lyd_node
*dnode
,
6481 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6483 if (yang_dnode_exists(dnode
, "./label-index"))
6484 vty_out(vty
, " label-index %s",
6485 yang_dnode_get_string(dnode
, "./label-index"));
6487 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6488 vty_out(vty
, " route-map %s",
6489 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6491 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6492 vty_out(vty
, " backdoor");
6497 static struct bgp_aggregate
*bgp_aggregate_new(void)
6499 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6502 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6504 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6505 route_map_counter_decrement(aggregate
->suppress_map
);
6506 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6507 route_map_counter_decrement(aggregate
->rmap
.map
);
6508 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6512 * Helper function to avoid repeated code: prepare variables for a
6513 * `route_map_apply` call.
6515 * \returns `true` on route map match, otherwise `false`.
6517 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6518 struct bgp_aggregate
*aggregate
,
6519 struct bgp_path_info
*pi
)
6521 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6522 route_map_result_t rmr
= RMAP_DENYMATCH
;
6523 struct bgp_path_info rmap_path
= {};
6524 struct attr attr
= {};
6526 /* No route map entries created, just don't match. */
6527 if (aggregate
->suppress_map
== NULL
)
6530 /* Call route map matching and return result. */
6531 attr
.aspath
= aspath_empty();
6532 rmap_path
.peer
= bgp
->peer_self
;
6533 rmap_path
.attr
= &attr
;
6535 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6536 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6537 bgp
->peer_self
->rmap_type
= 0;
6539 bgp_attr_flush(&attr
);
6541 return rmr
== RMAP_PERMITMATCH
;
6544 /** Test whether the aggregation has suppressed this path or not. */
6545 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6546 struct bgp_path_info
*pi
)
6548 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6551 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6555 * Suppress this path and keep the reference.
6557 * \returns `true` if needs processing otherwise `false`.
6559 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6560 struct bgp_path_info
*pi
)
6562 struct bgp_path_info_extra
*pie
;
6564 /* Path is already suppressed by this aggregation. */
6565 if (aggr_suppress_exists(aggregate
, pi
))
6568 pie
= bgp_path_info_extra_get(pi
);
6570 /* This is the first suppression, allocate memory and list it. */
6571 if (pie
->aggr_suppressors
== NULL
)
6572 pie
->aggr_suppressors
= list_new();
6574 listnode_add(pie
->aggr_suppressors
, aggregate
);
6576 /* Only mark for processing if suppressed. */
6577 if (listcount(pie
->aggr_suppressors
) == 1) {
6578 if (BGP_DEBUG(update
, UPDATE_OUT
))
6579 zlog_debug("aggregate-address suppressing: %pFX",
6580 bgp_dest_get_prefix(pi
->net
));
6582 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6590 * Unsuppress this path and remove the reference.
6592 * \returns `true` if needs processing otherwise `false`.
6594 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6595 struct bgp_path_info
*pi
)
6597 /* Path wasn't suppressed. */
6598 if (!aggr_suppress_exists(aggregate
, pi
))
6601 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6603 /* Unsuppress and free extra memory if last item. */
6604 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6605 if (BGP_DEBUG(update
, UPDATE_OUT
))
6606 zlog_debug("aggregate-address unsuppressing: %pFX",
6607 bgp_dest_get_prefix(pi
->net
));
6609 list_delete(&pi
->extra
->aggr_suppressors
);
6610 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6617 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6618 struct aspath
*aspath
,
6619 struct community
*comm
,
6620 struct ecommunity
*ecomm
,
6621 struct lcommunity
*lcomm
)
6623 static struct aspath
*ae
= NULL
;
6626 ae
= aspath_empty();
6631 if (origin
!= pi
->attr
->origin
)
6634 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6637 if (!community_cmp(pi
->attr
->community
, comm
))
6640 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6643 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6646 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6652 static void bgp_aggregate_install(
6653 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6654 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6655 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6656 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6658 struct bgp_dest
*dest
;
6659 struct bgp_table
*table
;
6660 struct bgp_path_info
*pi
, *orig
, *new;
6663 table
= bgp
->rib
[afi
][safi
];
6665 dest
= bgp_node_get(table
, p
);
6667 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6668 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6669 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6673 * If we have paths with different MEDs, then don't install
6674 * (or uninstall) the aggregate route.
6676 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6677 goto uninstall_aggregate_route
;
6679 if (aggregate
->count
> 0) {
6681 * If the aggregate information has not changed
6682 * no need to re-install it again.
6684 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6685 ecommunity
, lcommunity
)) {
6686 bgp_dest_unlock_node(dest
);
6689 aspath_free(aspath
);
6691 community_free(&community
);
6693 ecommunity_free(&ecommunity
);
6695 lcommunity_free(&lcommunity
);
6701 * Mark the old as unusable
6704 bgp_path_info_delete(dest
, pi
);
6706 attr
= bgp_attr_aggregate_intern(
6707 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6708 aggregate
, atomic_aggregate
, p
);
6711 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6712 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6713 zlog_debug("%s: %pFX null attribute", __func__
,
6718 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6719 bgp
->peer_self
, attr
, dest
);
6721 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6723 bgp_path_info_add(dest
, new);
6724 bgp_process(bgp
, dest
, afi
, safi
);
6726 uninstall_aggregate_route
:
6727 for (pi
= orig
; pi
; pi
= pi
->next
)
6728 if (pi
->peer
== bgp
->peer_self
6729 && pi
->type
== ZEBRA_ROUTE_BGP
6730 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6733 /* Withdraw static BGP route from routing table. */
6735 bgp_path_info_delete(dest
, pi
);
6736 bgp_process(bgp
, dest
, afi
, safi
);
6740 bgp_dest_unlock_node(dest
);
6744 * Check if the current path has different MED than other known paths.
6746 * \returns `true` if the MED matched the others else `false`.
6748 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6749 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6751 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6753 /* This is the first route being analyzed. */
6754 if (!aggregate
->med_initialized
) {
6755 aggregate
->med_initialized
= true;
6756 aggregate
->med_mismatched
= false;
6757 aggregate
->med_matched_value
= cur_med
;
6759 /* Check if routes with different MED showed up. */
6760 if (cur_med
!= aggregate
->med_matched_value
)
6761 aggregate
->med_mismatched
= true;
6764 return !aggregate
->med_mismatched
;
6768 * Initializes and tests all routes in the aggregate address path for MED
6771 * \returns `true` if all MEDs are the same otherwise `false`.
6773 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6774 struct bgp
*bgp
, const struct prefix
*p
,
6775 afi_t afi
, safi_t safi
)
6777 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6778 const struct prefix
*dest_p
;
6779 struct bgp_dest
*dest
, *top
;
6780 struct bgp_path_info
*pi
;
6781 bool med_matched
= true;
6783 aggregate
->med_initialized
= false;
6785 top
= bgp_node_get(table
, p
);
6786 for (dest
= bgp_node_get(table
, p
); dest
;
6787 dest
= bgp_route_next_until(dest
, top
)) {
6788 dest_p
= bgp_dest_get_prefix(dest
);
6789 if (dest_p
->prefixlen
<= p
->prefixlen
)
6792 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6793 if (BGP_PATH_HOLDDOWN(pi
))
6795 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6797 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6798 med_matched
= false;
6805 bgp_dest_unlock_node(top
);
6811 * Toggles the route suppression status for this aggregate address
6814 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6815 struct bgp
*bgp
, const struct prefix
*p
,
6816 afi_t afi
, safi_t safi
, bool suppress
)
6818 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6819 const struct prefix
*dest_p
;
6820 struct bgp_dest
*dest
, *top
;
6821 struct bgp_path_info
*pi
;
6822 bool toggle_suppression
;
6824 /* We've found a different MED we must revert any suppressed routes. */
6825 top
= bgp_node_get(table
, p
);
6826 for (dest
= bgp_node_get(table
, p
); dest
;
6827 dest
= bgp_route_next_until(dest
, top
)) {
6828 dest_p
= bgp_dest_get_prefix(dest
);
6829 if (dest_p
->prefixlen
<= p
->prefixlen
)
6832 toggle_suppression
= false;
6833 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6834 if (BGP_PATH_HOLDDOWN(pi
))
6836 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6839 /* We are toggling suppression back. */
6841 /* Suppress route if not suppressed already. */
6842 if (aggr_suppress_path(aggregate
, pi
))
6843 toggle_suppression
= true;
6847 /* Install route if there is no more suppression. */
6848 if (aggr_unsuppress_path(aggregate
, pi
))
6849 toggle_suppression
= true;
6852 if (toggle_suppression
)
6853 bgp_process(bgp
, dest
, afi
, safi
);
6855 bgp_dest_unlock_node(top
);
6859 * Aggregate address MED matching incremental test: this function is called
6860 * when the initial aggregation occurred and we are only testing a single
6863 * In addition to testing and setting the MED validity it also installs back
6864 * suppressed routes (if summary is configured).
6866 * Must not be called in `bgp_aggregate_route`.
6868 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6869 struct bgp
*bgp
, const struct prefix
*p
,
6870 afi_t afi
, safi_t safi
,
6871 struct bgp_path_info
*pi
, bool is_adding
)
6873 /* MED matching disabled. */
6874 if (!aggregate
->match_med
)
6877 /* Aggregation with different MED, nothing to do. */
6878 if (aggregate
->med_mismatched
)
6882 * Test the current entry:
6884 * is_adding == true: if the new entry doesn't match then we must
6885 * install all suppressed routes.
6887 * is_adding == false: if the entry being removed was the last
6888 * unmatching entry then we can suppress all routes.
6891 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6892 && aggregate
->summary_only
)
6893 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6896 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6898 /* No mismatches, just quit. */
6899 if (!aggregate
->med_mismatched
)
6902 /* Route summarization is disabled. */
6903 if (!aggregate
->summary_only
)
6906 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6909 /* Update an aggregate as routes are added/removed from the BGP table */
6910 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6911 safi_t safi
, struct bgp_aggregate
*aggregate
)
6913 struct bgp_table
*table
;
6914 struct bgp_dest
*top
;
6915 struct bgp_dest
*dest
;
6917 struct aspath
*aspath
= NULL
;
6918 struct community
*community
= NULL
;
6919 struct ecommunity
*ecommunity
= NULL
;
6920 struct lcommunity
*lcommunity
= NULL
;
6921 struct bgp_path_info
*pi
;
6922 unsigned long match
= 0;
6923 uint8_t atomic_aggregate
= 0;
6925 /* If the bgp instance is being deleted or self peer is deleted
6926 * then do not create aggregate route
6928 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6929 || (bgp
->peer_self
== NULL
))
6932 /* Initialize and test routes for MED difference. */
6933 if (aggregate
->match_med
)
6934 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6937 * Reset aggregate count: we might've been called from route map
6938 * update so in that case we must retest all more specific routes.
6940 * \see `bgp_route_map_process_update`.
6942 aggregate
->count
= 0;
6943 aggregate
->incomplete_origin_count
= 0;
6944 aggregate
->incomplete_origin_count
= 0;
6945 aggregate
->egp_origin_count
= 0;
6947 /* ORIGIN attribute: If at least one route among routes that are
6948 aggregated has ORIGIN with the value INCOMPLETE, then the
6949 aggregated route must have the ORIGIN attribute with the value
6950 INCOMPLETE. Otherwise, if at least one route among routes that
6951 are aggregated has ORIGIN with the value EGP, then the aggregated
6952 route must have the origin attribute with the value EGP. In all
6953 other case the value of the ORIGIN attribute of the aggregated
6954 route is INTERNAL. */
6955 origin
= BGP_ORIGIN_IGP
;
6957 table
= bgp
->rib
[afi
][safi
];
6959 top
= bgp_node_get(table
, p
);
6960 for (dest
= bgp_node_get(table
, p
); dest
;
6961 dest
= bgp_route_next_until(dest
, top
)) {
6962 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6964 if (dest_p
->prefixlen
<= p
->prefixlen
)
6967 /* If suppress fib is enabled and route not installed
6968 * in FIB, skip the route
6970 if (!bgp_check_advertise(bgp
, dest
))
6975 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6976 if (BGP_PATH_HOLDDOWN(pi
))
6980 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6981 atomic_aggregate
= 1;
6983 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6987 * summary-only aggregate route suppress
6988 * aggregated route announcements.
6991 * Don't create summaries if MED didn't match
6992 * otherwise neither the specific routes and the
6993 * aggregation will be announced.
6995 if (aggregate
->summary_only
6996 && AGGREGATE_MED_VALID(aggregate
)) {
6997 if (aggr_suppress_path(aggregate
, pi
))
7002 * Suppress more specific routes that match the route
7006 * Don't suppress routes if MED matching is enabled and
7007 * it mismatched otherwise we might end up with no
7008 * routes for this path.
7010 if (aggregate
->suppress_map_name
7011 && AGGREGATE_MED_VALID(aggregate
)
7012 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7013 if (aggr_suppress_path(aggregate
, pi
))
7020 * If at least one route among routes that are
7021 * aggregated has ORIGIN with the value INCOMPLETE,
7022 * then the aggregated route MUST have the ORIGIN
7023 * attribute with the value INCOMPLETE. Otherwise, if
7024 * at least one route among routes that are aggregated
7025 * has ORIGIN with the value EGP, then the aggregated
7026 * route MUST have the ORIGIN attribute with the value
7029 switch (pi
->attr
->origin
) {
7030 case BGP_ORIGIN_INCOMPLETE
:
7031 aggregate
->incomplete_origin_count
++;
7033 case BGP_ORIGIN_EGP
:
7034 aggregate
->egp_origin_count
++;
7042 if (!aggregate
->as_set
)
7046 * as-set aggregate route generate origin, as path,
7047 * and community aggregation.
7049 /* Compute aggregate route's as-path.
7051 bgp_compute_aggregate_aspath_hash(aggregate
,
7054 /* Compute aggregate route's community.
7056 if (pi
->attr
->community
)
7057 bgp_compute_aggregate_community_hash(
7059 pi
->attr
->community
);
7061 /* Compute aggregate route's extended community.
7063 if (pi
->attr
->ecommunity
)
7064 bgp_compute_aggregate_ecommunity_hash(
7066 pi
->attr
->ecommunity
);
7068 /* Compute aggregate route's large community.
7070 if (pi
->attr
->lcommunity
)
7071 bgp_compute_aggregate_lcommunity_hash(
7073 pi
->attr
->lcommunity
);
7076 bgp_process(bgp
, dest
, afi
, safi
);
7078 if (aggregate
->as_set
) {
7079 bgp_compute_aggregate_aspath_val(aggregate
);
7080 bgp_compute_aggregate_community_val(aggregate
);
7081 bgp_compute_aggregate_ecommunity_val(aggregate
);
7082 bgp_compute_aggregate_lcommunity_val(aggregate
);
7086 bgp_dest_unlock_node(top
);
7089 if (aggregate
->incomplete_origin_count
> 0)
7090 origin
= BGP_ORIGIN_INCOMPLETE
;
7091 else if (aggregate
->egp_origin_count
> 0)
7092 origin
= BGP_ORIGIN_EGP
;
7094 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7095 origin
= aggregate
->origin
;
7097 if (aggregate
->as_set
) {
7098 if (aggregate
->aspath
)
7099 /* Retrieve aggregate route's as-path.
7101 aspath
= aspath_dup(aggregate
->aspath
);
7103 if (aggregate
->community
)
7104 /* Retrieve aggregate route's community.
7106 community
= community_dup(aggregate
->community
);
7108 if (aggregate
->ecommunity
)
7109 /* Retrieve aggregate route's ecommunity.
7111 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7113 if (aggregate
->lcommunity
)
7114 /* Retrieve aggregate route's lcommunity.
7116 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7119 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7120 ecommunity
, lcommunity
, atomic_aggregate
,
7124 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7125 safi_t safi
, struct bgp_aggregate
*aggregate
)
7127 struct bgp_table
*table
;
7128 struct bgp_dest
*top
;
7129 struct bgp_dest
*dest
;
7130 struct bgp_path_info
*pi
;
7131 unsigned long match
;
7133 table
= bgp
->rib
[afi
][safi
];
7135 /* If routes exists below this node, generate aggregate routes. */
7136 top
= bgp_node_get(table
, p
);
7137 for (dest
= bgp_node_get(table
, p
); dest
;
7138 dest
= bgp_route_next_until(dest
, top
)) {
7139 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7141 if (dest_p
->prefixlen
<= p
->prefixlen
)
7145 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7146 if (BGP_PATH_HOLDDOWN(pi
))
7149 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7152 if (aggregate
->summary_only
&& pi
->extra
7153 && AGGREGATE_MED_VALID(aggregate
)) {
7154 if (aggr_unsuppress_path(aggregate
, pi
))
7158 if (aggregate
->suppress_map_name
7159 && AGGREGATE_MED_VALID(aggregate
)
7160 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7161 if (aggr_unsuppress_path(aggregate
, pi
))
7167 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7168 aggregate
->incomplete_origin_count
--;
7169 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7170 aggregate
->egp_origin_count
--;
7172 if (aggregate
->as_set
) {
7173 /* Remove as-path from aggregate.
7175 bgp_remove_aspath_from_aggregate_hash(
7179 if (pi
->attr
->community
)
7180 /* Remove community from aggregate.
7182 bgp_remove_comm_from_aggregate_hash(
7184 pi
->attr
->community
);
7186 if (pi
->attr
->ecommunity
)
7187 /* Remove ecommunity from aggregate.
7189 bgp_remove_ecomm_from_aggregate_hash(
7191 pi
->attr
->ecommunity
);
7193 if (pi
->attr
->lcommunity
)
7194 /* Remove lcommunity from aggregate.
7196 bgp_remove_lcomm_from_aggregate_hash(
7198 pi
->attr
->lcommunity
);
7202 /* If this node was suppressed, process the change. */
7204 bgp_process(bgp
, dest
, afi
, safi
);
7206 if (aggregate
->as_set
) {
7207 aspath_free(aggregate
->aspath
);
7208 aggregate
->aspath
= NULL
;
7209 if (aggregate
->community
)
7210 community_free(&aggregate
->community
);
7211 if (aggregate
->ecommunity
)
7212 ecommunity_free(&aggregate
->ecommunity
);
7213 if (aggregate
->lcommunity
)
7214 lcommunity_free(&aggregate
->lcommunity
);
7217 bgp_dest_unlock_node(top
);
7220 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7221 const struct prefix
*aggr_p
,
7222 struct bgp_path_info
*pinew
, afi_t afi
,
7224 struct bgp_aggregate
*aggregate
)
7227 struct aspath
*aspath
= NULL
;
7228 uint8_t atomic_aggregate
= 0;
7229 struct community
*community
= NULL
;
7230 struct ecommunity
*ecommunity
= NULL
;
7231 struct lcommunity
*lcommunity
= NULL
;
7233 /* If the bgp instance is being deleted or self peer is deleted
7234 * then do not create aggregate route
7236 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7237 || (bgp
->peer_self
== NULL
))
7240 /* ORIGIN attribute: If at least one route among routes that are
7241 * aggregated has ORIGIN with the value INCOMPLETE, then the
7242 * aggregated route must have the ORIGIN attribute with the value
7243 * INCOMPLETE. Otherwise, if at least one route among routes that
7244 * are aggregated has ORIGIN with the value EGP, then the aggregated
7245 * route must have the origin attribute with the value EGP. In all
7246 * other case the value of the ORIGIN attribute of the aggregated
7247 * route is INTERNAL.
7249 origin
= BGP_ORIGIN_IGP
;
7254 * This must be called before `summary` check to avoid
7255 * "suppressing" twice.
7257 if (aggregate
->match_med
)
7258 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7261 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7262 aggr_suppress_path(aggregate
, pinew
);
7264 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7265 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7266 aggr_suppress_path(aggregate
, pinew
);
7268 switch (pinew
->attr
->origin
) {
7269 case BGP_ORIGIN_INCOMPLETE
:
7270 aggregate
->incomplete_origin_count
++;
7272 case BGP_ORIGIN_EGP
:
7273 aggregate
->egp_origin_count
++;
7281 if (aggregate
->incomplete_origin_count
> 0)
7282 origin
= BGP_ORIGIN_INCOMPLETE
;
7283 else if (aggregate
->egp_origin_count
> 0)
7284 origin
= BGP_ORIGIN_EGP
;
7286 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7287 origin
= aggregate
->origin
;
7289 if (aggregate
->as_set
) {
7290 /* Compute aggregate route's as-path.
7292 bgp_compute_aggregate_aspath(aggregate
,
7293 pinew
->attr
->aspath
);
7295 /* Compute aggregate route's community.
7297 if (pinew
->attr
->community
)
7298 bgp_compute_aggregate_community(
7300 pinew
->attr
->community
);
7302 /* Compute aggregate route's extended community.
7304 if (pinew
->attr
->ecommunity
)
7305 bgp_compute_aggregate_ecommunity(
7307 pinew
->attr
->ecommunity
);
7309 /* Compute aggregate route's large community.
7311 if (pinew
->attr
->lcommunity
)
7312 bgp_compute_aggregate_lcommunity(
7314 pinew
->attr
->lcommunity
);
7316 /* Retrieve aggregate route's as-path.
7318 if (aggregate
->aspath
)
7319 aspath
= aspath_dup(aggregate
->aspath
);
7321 /* Retrieve aggregate route's community.
7323 if (aggregate
->community
)
7324 community
= community_dup(aggregate
->community
);
7326 /* Retrieve aggregate route's ecommunity.
7328 if (aggregate
->ecommunity
)
7329 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7331 /* Retrieve aggregate route's lcommunity.
7333 if (aggregate
->lcommunity
)
7334 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7337 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7338 aspath
, community
, ecommunity
,
7339 lcommunity
, atomic_aggregate
, aggregate
);
7342 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7344 struct bgp_path_info
*pi
,
7345 struct bgp_aggregate
*aggregate
,
7346 const struct prefix
*aggr_p
)
7349 struct aspath
*aspath
= NULL
;
7350 uint8_t atomic_aggregate
= 0;
7351 struct community
*community
= NULL
;
7352 struct ecommunity
*ecommunity
= NULL
;
7353 struct lcommunity
*lcommunity
= NULL
;
7354 unsigned long match
= 0;
7356 /* If the bgp instance is being deleted or self peer is deleted
7357 * then do not create aggregate route
7359 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7360 || (bgp
->peer_self
== NULL
))
7363 if (BGP_PATH_HOLDDOWN(pi
))
7366 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7369 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7370 if (aggr_unsuppress_path(aggregate
, pi
))
7373 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7374 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7375 if (aggr_unsuppress_path(aggregate
, pi
))
7379 * This must be called after `summary`, `suppress-map` check to avoid
7380 * "unsuppressing" twice.
7382 if (aggregate
->match_med
)
7383 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7386 if (aggregate
->count
> 0)
7389 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7390 aggregate
->incomplete_origin_count
--;
7391 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7392 aggregate
->egp_origin_count
--;
7394 if (aggregate
->as_set
) {
7395 /* Remove as-path from aggregate.
7397 bgp_remove_aspath_from_aggregate(aggregate
,
7400 if (pi
->attr
->community
)
7401 /* Remove community from aggregate.
7403 bgp_remove_community_from_aggregate(
7405 pi
->attr
->community
);
7407 if (pi
->attr
->ecommunity
)
7408 /* Remove ecommunity from aggregate.
7410 bgp_remove_ecommunity_from_aggregate(
7412 pi
->attr
->ecommunity
);
7414 if (pi
->attr
->lcommunity
)
7415 /* Remove lcommunity from aggregate.
7417 bgp_remove_lcommunity_from_aggregate(
7419 pi
->attr
->lcommunity
);
7422 /* If this node was suppressed, process the change. */
7424 bgp_process(bgp
, pi
->net
, afi
, safi
);
7426 origin
= BGP_ORIGIN_IGP
;
7427 if (aggregate
->incomplete_origin_count
> 0)
7428 origin
= BGP_ORIGIN_INCOMPLETE
;
7429 else if (aggregate
->egp_origin_count
> 0)
7430 origin
= BGP_ORIGIN_EGP
;
7432 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7433 origin
= aggregate
->origin
;
7435 if (aggregate
->as_set
) {
7436 /* Retrieve aggregate route's as-path.
7438 if (aggregate
->aspath
)
7439 aspath
= aspath_dup(aggregate
->aspath
);
7441 /* Retrieve aggregate route's community.
7443 if (aggregate
->community
)
7444 community
= community_dup(aggregate
->community
);
7446 /* Retrieve aggregate route's ecommunity.
7448 if (aggregate
->ecommunity
)
7449 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7451 /* Retrieve aggregate route's lcommunity.
7453 if (aggregate
->lcommunity
)
7454 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7457 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7458 aspath
, community
, ecommunity
,
7459 lcommunity
, atomic_aggregate
, aggregate
);
7462 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7463 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7465 struct bgp_dest
*child
;
7466 struct bgp_dest
*dest
;
7467 struct bgp_aggregate
*aggregate
;
7468 struct bgp_table
*table
;
7470 table
= bgp
->aggregate
[afi
][safi
];
7472 /* No aggregates configured. */
7473 if (bgp_table_top_nolock(table
) == NULL
)
7476 if (p
->prefixlen
== 0)
7479 if (BGP_PATH_HOLDDOWN(pi
))
7482 /* If suppress fib is enabled and route not installed
7483 * in FIB, do not update the aggregate route
7485 if (!bgp_check_advertise(bgp
, pi
->net
))
7488 child
= bgp_node_get(table
, p
);
7490 /* Aggregate address configuration check. */
7491 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7492 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7494 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7495 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7496 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7500 bgp_dest_unlock_node(child
);
7503 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7504 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7506 struct bgp_dest
*child
;
7507 struct bgp_dest
*dest
;
7508 struct bgp_aggregate
*aggregate
;
7509 struct bgp_table
*table
;
7511 table
= bgp
->aggregate
[afi
][safi
];
7513 /* No aggregates configured. */
7514 if (bgp_table_top_nolock(table
) == NULL
)
7517 if (p
->prefixlen
== 0)
7520 child
= bgp_node_get(table
, p
);
7522 /* Aggregate address configuration check. */
7523 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7524 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7526 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7527 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7528 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7532 bgp_dest_unlock_node(child
);
7535 /* Aggregate route attribute. */
7536 #define AGGREGATE_SUMMARY_ONLY 1
7537 #define AGGREGATE_AS_SET 1
7538 #define AGGREGATE_AS_UNSET 0
7540 static const char *bgp_origin2str(uint8_t origin
)
7543 case BGP_ORIGIN_IGP
:
7545 case BGP_ORIGIN_EGP
:
7547 case BGP_ORIGIN_INCOMPLETE
:
7548 return "incomplete";
7553 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7554 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7556 struct bgp_dest
*dest
;
7557 struct bgp_aggregate
*aggregate
;
7559 /* If the bgp instance is being deleted or self peer is deleted
7560 * then do not create aggregate route
7562 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7563 || (bgp
->peer_self
== NULL
))
7567 /* Old configuration check. */
7568 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7570 snprintf(errmsg
, errmsg_len
,
7571 "There is no aggregate-address configuration.\n");
7575 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7576 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7577 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7580 /* Unlock aggregate address configuration. */
7581 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7583 if (aggregate
->community
)
7584 community_free(&aggregate
->community
);
7586 if (aggregate
->community_hash
) {
7587 /* Delete all communities in the hash.
7589 hash_clean(aggregate
->community_hash
,
7590 bgp_aggr_community_remove
);
7591 /* Free up the community_hash.
7593 hash_free(aggregate
->community_hash
);
7596 if (aggregate
->ecommunity
)
7597 ecommunity_free(&aggregate
->ecommunity
);
7599 if (aggregate
->ecommunity_hash
) {
7600 /* Delete all ecommunities in the hash.
7602 hash_clean(aggregate
->ecommunity_hash
,
7603 bgp_aggr_ecommunity_remove
);
7604 /* Free up the ecommunity_hash.
7606 hash_free(aggregate
->ecommunity_hash
);
7609 if (aggregate
->lcommunity
)
7610 lcommunity_free(&aggregate
->lcommunity
);
7612 if (aggregate
->lcommunity_hash
) {
7613 /* Delete all lcommunities in the hash.
7615 hash_clean(aggregate
->lcommunity_hash
,
7616 bgp_aggr_lcommunity_remove
);
7617 /* Free up the lcommunity_hash.
7619 hash_free(aggregate
->lcommunity_hash
);
7622 if (aggregate
->aspath
)
7623 aspath_free(aggregate
->aspath
);
7625 if (aggregate
->aspath_hash
) {
7626 /* Delete all as-paths in the hash.
7628 hash_clean(aggregate
->aspath_hash
,
7629 bgp_aggr_aspath_remove
);
7630 /* Free up the aspath_hash.
7632 hash_free(aggregate
->aspath_hash
);
7635 bgp_aggregate_free(aggregate
);
7636 bgp_dest_unlock_node(dest
);
7637 bgp_dest_unlock_node(dest
);
7642 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7643 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7644 uint8_t as_set
, uint8_t origin
, bool match_med
,
7645 const char *suppress_map
,
7646 char *errmsg
, size_t errmsg_len
)
7649 struct bgp_dest
*dest
;
7650 struct bgp_aggregate
*aggregate
;
7651 uint8_t as_set_new
= as_set
;
7652 char buf
[PREFIX2STR_BUFFER
];
7654 if (suppress_map
&& summary_only
) {
7655 snprintf(errmsg
, errmsg_len
,
7656 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7662 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7663 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7666 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7667 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7671 /* Old configuration check. */
7672 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7673 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7676 snprintf(errmsg
, errmsg_len
,
7677 "There is already same aggregate network.\n");
7678 /* try to remove the old entry */
7679 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7682 snprintf(errmsg
, errmsg_len
,
7683 "Error deleting aggregate.\n");
7684 bgp_dest_unlock_node(dest
);
7689 /* Make aggregate address structure. */
7690 aggregate
= bgp_aggregate_new();
7691 aggregate
->summary_only
= summary_only
;
7692 aggregate
->match_med
= match_med
;
7694 /* Network operators MUST NOT locally generate any new
7695 * announcements containing AS_SET or AS_CONFED_SET. If they have
7696 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7697 * SHOULD withdraw those routes and re-announce routes for the
7698 * aggregate or component prefixes (i.e., the more-specific routes
7699 * subsumed by the previously aggregated route) without AS_SET
7700 * or AS_CONFED_SET in the updates.
7702 if (bgp
->reject_as_sets
) {
7703 if (as_set
== AGGREGATE_AS_SET
) {
7704 as_set_new
= AGGREGATE_AS_UNSET
;
7706 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7710 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7714 aggregate
->as_set
= as_set_new
;
7715 aggregate
->safi
= safi
;
7716 /* Override ORIGIN attribute if defined.
7717 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7718 * to IGP which is not what rfc4271 says.
7719 * This enables the same behavior, optionally.
7721 aggregate
->origin
= origin
;
7724 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7725 route_map_counter_decrement(aggregate
->rmap
.map
);
7726 aggregate
->rmap
.name
=
7727 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7728 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7729 route_map_counter_increment(aggregate
->rmap
.map
);
7733 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7734 route_map_counter_decrement(aggregate
->suppress_map
);
7736 aggregate
->suppress_map_name
=
7737 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7738 aggregate
->suppress_map
=
7739 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7740 route_map_counter_increment(aggregate
->suppress_map
);
7743 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7745 /* Aggregate address insert into BGP routing table. */
7746 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
7752 aggregate_addressv4
, aggregate_addressv4_cmd
,
7753 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7755 "|summary-only$summary_only"
7756 "|route-map WORD$rmap_name"
7757 "|origin <egp|igp|incomplete>$origin_s"
7758 "|matching-MED-only$match_med"
7759 "|suppress-map WORD$suppress_map"
7762 "Configure BGP aggregate entries\n"
7763 "Aggregate prefix\n"
7764 "Aggregate address\n"
7766 "Generate AS set path information\n"
7767 "Filter more specific routes from updates\n"
7768 "Apply route map to aggregate network\n"
7773 "Unknown heritage\n"
7774 "Only aggregate routes with matching MED\n"
7775 "Suppress the selected more specific routes\n"
7776 "Route map with the route selectors\n")
7778 char base_xpath
[XPATH_MAXLEN
];
7779 safi_t safi
= bgp_node_safi(vty
);
7780 char prefix_buf
[PREFIX2STR_BUFFER
];
7783 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
)
7785 vty_out(vty
, "%% Inconsistent address and mask\n");
7786 return CMD_WARNING_CONFIG_FAILED
;
7789 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
7792 if (!no
&& origin_s
)
7793 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7795 if (!no
&& as_set_s
)
7796 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7798 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7800 if (!no
&& summary_only
)
7801 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7804 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7807 if (!no
&& match_med
)
7808 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7810 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7814 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7817 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
7818 NB_OP_DESTROY
, NULL
);
7821 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7824 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7828 base_xpath
, sizeof(base_xpath
),
7829 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7830 yang_afi_safi_value2identity(AFI_IP
, safi
),
7831 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
7834 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7836 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7838 return nb_cli_apply_changes(vty
, base_xpath
);
7841 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
7842 "[no] aggregate-address X:X::X:X/M$prefix {"
7844 "|summary-only$summary_only"
7845 "|route-map WORD$rmap_name"
7846 "|origin <egp|igp|incomplete>$origin_s"
7847 "|matching-MED-only$match_med"
7848 "|suppress-map WORD$suppress_map"
7851 "Configure BGP aggregate entries\n"
7852 "Aggregate prefix\n"
7853 "Generate AS set path information\n"
7854 "Filter more specific routes from updates\n"
7855 "Apply route map to aggregate network\n"
7860 "Unknown heritage\n"
7861 "Only aggregate routes with matching MED\n"
7862 "Suppress the selected more specific routes\n"
7863 "Route map with the route selectors\n")
7865 char base_xpath
[XPATH_MAXLEN
];
7866 safi_t safi
= bgp_node_safi(vty
);
7868 if (!no
&& origin_s
)
7869 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7871 if (!no
&& as_set_s
)
7872 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7874 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7876 if (!no
&& summary_only
)
7877 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7880 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7883 if (!no
&& match_med
)
7884 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7886 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7890 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7894 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7897 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7901 base_xpath
, sizeof(base_xpath
),
7902 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7903 yang_afi_safi_value2identity(AFI_IP6
, safi
),
7904 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
7907 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7909 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7911 return nb_cli_apply_changes(vty
, base_xpath
);
7914 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7915 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
7919 vty_out(vty
, " aggregate-address %s",
7920 yang_dnode_get_string(dnode
, "./prefix"));
7922 if (yang_dnode_get_bool(dnode
, "./as-set"))
7923 vty_out(vty
, " as-set");
7925 if (yang_dnode_get_bool(dnode
, "./summary-only"))
7926 vty_out(vty
, " summary-only");
7928 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
7929 vty_out(vty
, " route-map %s",
7930 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
7932 origin
= yang_dnode_get_enum(dnode
, "./origin");
7933 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
7934 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
7936 if (yang_dnode_get_bool(dnode
, "./match-med"))
7937 vty_out(vty
, " matching-MED-only");
7942 /* Redistribute route treatment. */
7943 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7944 const union g_addr
*nexthop
, ifindex_t ifindex
,
7945 enum nexthop_types_t nhtype
, uint32_t metric
,
7946 uint8_t type
, unsigned short instance
,
7949 struct bgp_path_info
*new;
7950 struct bgp_path_info
*bpi
;
7951 struct bgp_path_info rmap_path
;
7952 struct bgp_dest
*bn
;
7954 struct attr
*new_attr
;
7956 route_map_result_t ret
;
7957 struct bgp_redist
*red
;
7959 /* Make default attribute. */
7960 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7962 * This must not be NULL to satisfy Coverity SA
7964 assert(attr
.aspath
);
7967 case NEXTHOP_TYPE_IFINDEX
:
7969 case NEXTHOP_TYPE_IPV4
:
7970 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7971 attr
.nexthop
= nexthop
->ipv4
;
7973 case NEXTHOP_TYPE_IPV6
:
7974 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7975 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7976 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7978 case NEXTHOP_TYPE_BLACKHOLE
:
7979 switch (p
->family
) {
7981 attr
.nexthop
.s_addr
= INADDR_ANY
;
7984 memset(&attr
.mp_nexthop_global
, 0,
7985 sizeof(attr
.mp_nexthop_global
));
7986 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7991 attr
.nh_ifindex
= ifindex
;
7994 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7997 afi
= family2afi(p
->family
);
7999 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8001 struct attr attr_new
;
8003 /* Copy attribute for modification. */
8006 if (red
->redist_metric_flag
)
8007 attr_new
.med
= red
->redist_metric
;
8009 /* Apply route-map. */
8010 if (red
->rmap
.name
) {
8011 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8012 rmap_path
.peer
= bgp
->peer_self
;
8013 rmap_path
.attr
= &attr_new
;
8015 SET_FLAG(bgp
->peer_self
->rmap_type
,
8016 PEER_RMAP_TYPE_REDISTRIBUTE
);
8018 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8020 bgp
->peer_self
->rmap_type
= 0;
8022 if (ret
== RMAP_DENYMATCH
) {
8023 /* Free uninterned attribute. */
8024 bgp_attr_flush(&attr_new
);
8026 /* Unintern original. */
8027 aspath_unintern(&attr
.aspath
);
8028 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8033 if (bgp_in_graceful_shutdown(bgp
))
8034 bgp_attr_add_gshut_community(&attr_new
);
8036 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8037 SAFI_UNICAST
, p
, NULL
);
8039 new_attr
= bgp_attr_intern(&attr_new
);
8041 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8042 if (bpi
->peer
== bgp
->peer_self
8043 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8047 /* Ensure the (source route) type is updated. */
8049 if (attrhash_cmp(bpi
->attr
, new_attr
)
8050 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8051 bgp_attr_unintern(&new_attr
);
8052 aspath_unintern(&attr
.aspath
);
8053 bgp_dest_unlock_node(bn
);
8056 /* The attribute is changed. */
8057 bgp_path_info_set_flag(bn
, bpi
,
8058 BGP_PATH_ATTR_CHANGED
);
8060 /* Rewrite BGP route information. */
8061 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8062 bgp_path_info_restore(bn
, bpi
);
8064 bgp_aggregate_decrement(
8065 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8066 bgp_attr_unintern(&bpi
->attr
);
8067 bpi
->attr
= new_attr
;
8068 bpi
->uptime
= bgp_clock();
8070 /* Process change. */
8071 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8073 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8074 bgp_dest_unlock_node(bn
);
8075 aspath_unintern(&attr
.aspath
);
8077 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8079 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8081 vpn_leak_from_vrf_update(
8082 bgp_get_default(), bgp
, bpi
);
8088 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8089 bgp
->peer_self
, new_attr
, bn
);
8090 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8092 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8093 bgp_path_info_add(bn
, new);
8094 bgp_dest_unlock_node(bn
);
8095 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8097 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8098 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8100 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8104 /* Unintern original. */
8105 aspath_unintern(&attr
.aspath
);
8108 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8109 unsigned short instance
)
8112 struct bgp_dest
*dest
;
8113 struct bgp_path_info
*pi
;
8114 struct bgp_redist
*red
;
8116 afi
= family2afi(p
->family
);
8118 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8120 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8121 SAFI_UNICAST
, p
, NULL
);
8123 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8124 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8128 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8129 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8131 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8134 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8135 bgp_path_info_delete(dest
, pi
);
8136 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8138 bgp_dest_unlock_node(dest
);
8142 /* Withdraw specified route type's route. */
8143 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8144 unsigned short instance
)
8146 struct bgp_dest
*dest
;
8147 struct bgp_path_info
*pi
;
8148 struct bgp_table
*table
;
8150 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8152 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8153 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8154 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8155 && pi
->instance
== instance
)
8159 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8160 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8162 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8165 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8166 pi
, afi
, SAFI_UNICAST
);
8167 bgp_path_info_delete(dest
, pi
);
8168 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8173 /* Static function to display route. */
8174 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
8175 json_object
*json
, bool wide
)
8181 if (p
->family
== AF_INET
) {
8183 len
= vty_out(vty
, "%pFX", p
);
8185 json_object_string_add(json
, "prefix",
8186 inet_ntop(p
->family
,
8189 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8190 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8191 json_object_string_add(json
, "network", buf2
);
8193 } else if (p
->family
== AF_ETHERNET
) {
8194 len
= vty_out(vty
, "%pFX", p
);
8195 } else if (p
->family
== AF_EVPN
) {
8197 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8199 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8200 } else if (p
->family
== AF_FLOWSPEC
) {
8201 route_vty_out_flowspec(vty
, p
, NULL
,
8203 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8204 NLRI_STRING_FORMAT_MIN
, json
);
8207 len
= vty_out(vty
, "%pFX", p
);
8209 json_object_string_add(json
, "prefix",
8210 inet_ntop(p
->family
,
8213 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8214 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8215 json_object_string_add(json
, "network", buf2
);
8220 len
= wide
? (45 - len
) : (17 - len
);
8222 vty_out(vty
, "\n%*s", 20, " ");
8224 vty_out(vty
, "%*s", len
, " ");
8228 enum bgp_display_type
{
8233 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8236 case bgp_path_selection_none
:
8237 return "Nothing to Select";
8238 case bgp_path_selection_first
:
8239 return "First path received";
8240 case bgp_path_selection_evpn_sticky_mac
:
8241 return "EVPN Sticky Mac";
8242 case bgp_path_selection_evpn_seq
:
8243 return "EVPN sequence number";
8244 case bgp_path_selection_evpn_lower_ip
:
8245 return "EVPN lower IP";
8246 case bgp_path_selection_evpn_local_path
:
8247 return "EVPN local ES path";
8248 case bgp_path_selection_evpn_non_proxy
:
8249 return "EVPN non proxy";
8250 case bgp_path_selection_weight
:
8252 case bgp_path_selection_local_pref
:
8253 return "Local Pref";
8254 case bgp_path_selection_local_route
:
8255 return "Local Route";
8256 case bgp_path_selection_confed_as_path
:
8257 return "Confederation based AS Path";
8258 case bgp_path_selection_as_path
:
8260 case bgp_path_selection_origin
:
8262 case bgp_path_selection_med
:
8264 case bgp_path_selection_peer
:
8266 case bgp_path_selection_confed
:
8267 return "Confed Peer Type";
8268 case bgp_path_selection_igp_metric
:
8269 return "IGP Metric";
8270 case bgp_path_selection_older
:
8271 return "Older Path";
8272 case bgp_path_selection_router_id
:
8274 case bgp_path_selection_cluster_length
:
8275 return "Cluster length";
8276 case bgp_path_selection_stale
:
8277 return "Path Staleness";
8278 case bgp_path_selection_local_configured
:
8279 return "Locally configured route";
8280 case bgp_path_selection_neighbor_ip
:
8281 return "Neighbor IP";
8282 case bgp_path_selection_default
:
8283 return "Nothing left to compare";
8285 return "Invalid (internal error)";
8288 /* Print the short form route status for a bgp_path_info */
8289 static void route_vty_short_status_out(struct vty
*vty
,
8290 struct bgp_path_info
*path
,
8291 json_object
*json_path
)
8295 /* Route status display. */
8296 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8297 json_object_boolean_true_add(json_path
, "removed");
8299 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8300 json_object_boolean_true_add(json_path
, "stale");
8302 if (path
->extra
&& bgp_path_suppressed(path
))
8303 json_object_boolean_true_add(json_path
, "suppressed");
8305 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8306 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8307 json_object_boolean_true_add(json_path
, "valid");
8310 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8311 json_object_boolean_true_add(json_path
, "history");
8313 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8314 json_object_boolean_true_add(json_path
, "damped");
8316 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8317 json_object_boolean_true_add(json_path
, "bestpath");
8318 json_object_string_add(json_path
, "selectionReason",
8319 bgp_path_selection_reason2str(
8320 path
->net
->reason
));
8323 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8324 json_object_boolean_true_add(json_path
, "multipath");
8326 /* Internal route. */
8327 if ((path
->peer
->as
)
8328 && (path
->peer
->as
== path
->peer
->local_as
))
8329 json_object_string_add(json_path
, "pathFrom",
8332 json_object_string_add(json_path
, "pathFrom",
8338 /* Route status display. */
8339 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8341 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8343 else if (bgp_path_suppressed(path
))
8345 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8346 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8352 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8354 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8356 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8358 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8363 /* Internal route. */
8364 if (path
->peer
&& (path
->peer
->as
)
8365 && (path
->peer
->as
== path
->peer
->local_as
))
8371 static char *bgp_nexthop_hostname(struct peer
*peer
,
8372 struct bgp_nexthop_cache
*bnc
)
8375 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8376 return peer
->hostname
;
8380 /* called from terminal list command */
8381 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8382 struct bgp_path_info
*path
, int display
, safi_t safi
,
8383 json_object
*json_paths
, bool wide
)
8386 struct attr
*attr
= path
->attr
;
8387 json_object
*json_path
= NULL
;
8388 json_object
*json_nexthops
= NULL
;
8389 json_object
*json_nexthop_global
= NULL
;
8390 json_object
*json_nexthop_ll
= NULL
;
8391 json_object
*json_ext_community
= NULL
;
8392 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8394 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8395 bool nexthop_othervrf
= false;
8396 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8397 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8398 char *nexthop_hostname
=
8399 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8400 char esi_buf
[ESI_STR_LEN
];
8403 json_path
= json_object_new_object();
8405 /* short status lead text */
8406 route_vty_short_status_out(vty
, path
, json_path
);
8409 /* print prefix and mask */
8411 route_vty_out_route(p
, vty
, json_path
, wide
);
8413 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8415 route_vty_out_route(p
, vty
, json_path
, wide
);
8419 * If vrf id of nexthop is different from that of prefix,
8420 * set up printable string to append
8422 if (path
->extra
&& path
->extra
->bgp_orig
) {
8423 const char *self
= "";
8428 nexthop_othervrf
= true;
8429 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8431 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8432 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8433 "@%s%s", VRFID_NONE_STR
, self
);
8435 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8436 path
->extra
->bgp_orig
->vrf_id
, self
);
8438 if (path
->extra
->bgp_orig
->inst_type
8439 != BGP_INSTANCE_TYPE_DEFAULT
)
8441 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8443 const char *self
= "";
8448 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8452 * For ENCAP and EVPN routes, nexthop address family is not
8453 * neccessarily the same as the prefix address family.
8454 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8455 * EVPN routes are also exchanged with a MP nexthop. Currently,
8457 * is only IPv4, the value will be present in either
8459 * attr->mp_nexthop_global_in
8461 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8464 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8468 snprintf(nexthop
, sizeof(nexthop
), "%s",
8469 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8473 snprintf(nexthop
, sizeof(nexthop
), "%s",
8474 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8478 snprintf(nexthop
, sizeof(nexthop
), "?");
8483 json_nexthop_global
= json_object_new_object();
8485 json_object_string_add(json_nexthop_global
, "ip",
8488 if (path
->peer
->hostname
)
8489 json_object_string_add(json_nexthop_global
,
8491 path
->peer
->hostname
);
8493 json_object_string_add(json_nexthop_global
, "afi",
8494 (af
== AF_INET
) ? "ipv4"
8496 json_object_boolean_true_add(json_nexthop_global
,
8499 if (nexthop_hostname
)
8500 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8501 nexthop_hostname
, vrf_id_str
);
8503 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8505 len
= wide
? (41 - len
) : (16 - len
);
8507 vty_out(vty
, "\n%*s", 36, " ");
8509 vty_out(vty
, "%*s", len
, " ");
8511 } else if (safi
== SAFI_EVPN
) {
8513 char buf
[BUFSIZ
] = {0};
8515 json_nexthop_global
= json_object_new_object();
8517 json_object_string_add(json_nexthop_global
, "ip",
8519 &attr
->nexthop
, buf
,
8522 if (path
->peer
->hostname
)
8523 json_object_string_add(json_nexthop_global
,
8525 path
->peer
->hostname
);
8527 json_object_string_add(json_nexthop_global
, "afi",
8529 json_object_boolean_true_add(json_nexthop_global
,
8532 if (nexthop_hostname
)
8533 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8534 nexthop_hostname
, vrf_id_str
);
8536 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8539 len
= wide
? (41 - len
) : (16 - len
);
8541 vty_out(vty
, "\n%*s", 36, " ");
8543 vty_out(vty
, "%*s", len
, " ");
8545 } else if (safi
== SAFI_FLOWSPEC
) {
8546 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8548 char buf
[BUFSIZ
] = {0};
8550 json_nexthop_global
= json_object_new_object();
8552 json_object_string_add(json_nexthop_global
,
8554 json_object_string_add(
8555 json_nexthop_global
, "ip",
8556 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8559 if (path
->peer
->hostname
)
8560 json_object_string_add(
8561 json_nexthop_global
, "hostname",
8562 path
->peer
->hostname
);
8564 json_object_boolean_true_add(
8565 json_nexthop_global
,
8568 if (nexthop_hostname
)
8569 len
= vty_out(vty
, "%pI4(%s)%s",
8574 len
= vty_out(vty
, "%pI4%s",
8578 len
= wide
? (41 - len
) : (16 - len
);
8580 vty_out(vty
, "\n%*s", 36, " ");
8582 vty_out(vty
, "%*s", len
, " ");
8585 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8587 char buf
[BUFSIZ
] = {0};
8589 json_nexthop_global
= json_object_new_object();
8591 json_object_string_add(json_nexthop_global
, "ip",
8593 &attr
->nexthop
, buf
,
8596 if (path
->peer
->hostname
)
8597 json_object_string_add(json_nexthop_global
,
8599 path
->peer
->hostname
);
8601 json_object_string_add(json_nexthop_global
, "afi",
8603 json_object_boolean_true_add(json_nexthop_global
,
8606 if (nexthop_hostname
)
8607 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8608 nexthop_hostname
, vrf_id_str
);
8610 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8613 len
= wide
? (41 - len
) : (16 - len
);
8615 vty_out(vty
, "\n%*s", 36, " ");
8617 vty_out(vty
, "%*s", len
, " ");
8622 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8626 json_nexthop_global
= json_object_new_object();
8627 json_object_string_add(
8628 json_nexthop_global
, "ip",
8629 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8632 if (path
->peer
->hostname
)
8633 json_object_string_add(json_nexthop_global
,
8635 path
->peer
->hostname
);
8637 json_object_string_add(json_nexthop_global
, "afi",
8639 json_object_string_add(json_nexthop_global
, "scope",
8642 /* We display both LL & GL if both have been
8644 if ((attr
->mp_nexthop_len
8645 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8646 || (path
->peer
->conf_if
)) {
8647 json_nexthop_ll
= json_object_new_object();
8648 json_object_string_add(
8649 json_nexthop_ll
, "ip",
8651 &attr
->mp_nexthop_local
, buf
,
8654 if (path
->peer
->hostname
)
8655 json_object_string_add(
8656 json_nexthop_ll
, "hostname",
8657 path
->peer
->hostname
);
8659 json_object_string_add(json_nexthop_ll
, "afi",
8661 json_object_string_add(json_nexthop_ll
, "scope",
8664 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8665 &attr
->mp_nexthop_local
)
8667 && !attr
->mp_nexthop_prefer_global
)
8668 json_object_boolean_true_add(
8669 json_nexthop_ll
, "used");
8671 json_object_boolean_true_add(
8672 json_nexthop_global
, "used");
8674 json_object_boolean_true_add(
8675 json_nexthop_global
, "used");
8677 /* Display LL if LL/Global both in table unless
8678 * prefer-global is set */
8679 if (((attr
->mp_nexthop_len
8680 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8681 && !attr
->mp_nexthop_prefer_global
)
8682 || (path
->peer
->conf_if
)) {
8683 if (path
->peer
->conf_if
) {
8684 len
= vty_out(vty
, "%s",
8685 path
->peer
->conf_if
);
8686 /* len of IPv6 addr + max len of def
8688 len
= wide
? (41 - len
) : (16 - len
);
8691 vty_out(vty
, "\n%*s", 36, " ");
8693 vty_out(vty
, "%*s", len
, " ");
8695 if (nexthop_hostname
)
8698 &attr
->mp_nexthop_local
,
8704 &attr
->mp_nexthop_local
,
8707 len
= wide
? (41 - len
) : (16 - len
);
8710 vty_out(vty
, "\n%*s", 36, " ");
8712 vty_out(vty
, "%*s", len
, " ");
8715 if (nexthop_hostname
)
8716 len
= vty_out(vty
, "%pI6(%s)%s",
8717 &attr
->mp_nexthop_global
,
8721 len
= vty_out(vty
, "%pI6%s",
8722 &attr
->mp_nexthop_global
,
8725 len
= wide
? (41 - len
) : (16 - len
);
8728 vty_out(vty
, "\n%*s", 36, " ");
8730 vty_out(vty
, "%*s", len
, " ");
8736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8738 json_object_int_add(json_path
, "metric", attr
->med
);
8740 vty_out(vty
, "%7u", attr
->med
);
8742 vty_out(vty
, "%10u", attr
->med
);
8743 else if (!json_paths
) {
8745 vty_out(vty
, "%*s", 7, " ");
8747 vty_out(vty
, "%*s", 10, " ");
8751 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8753 json_object_int_add(json_path
, "locPrf",
8756 vty_out(vty
, "%7u", attr
->local_pref
);
8757 else if (!json_paths
)
8761 json_object_int_add(json_path
, "weight", attr
->weight
);
8763 vty_out(vty
, "%7u ", attr
->weight
);
8767 json_object_string_add(
8768 json_path
, "peerId",
8769 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8775 json_object_string_add(json_path
, "path",
8778 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8783 json_object_string_add(json_path
, "origin",
8784 bgp_origin_long_str
[attr
->origin
]);
8786 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8789 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8790 json_object_string_add(json_path
, "esi",
8791 esi_to_str(&attr
->esi
,
8792 esi_buf
, sizeof(esi_buf
)));
8794 if (safi
== SAFI_EVPN
&&
8795 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8796 json_ext_community
= json_object_new_object();
8797 json_object_string_add(json_ext_community
,
8799 attr
->ecommunity
->str
);
8800 json_object_object_add(json_path
,
8801 "extendedCommunity",
8802 json_ext_community
);
8806 json_object_boolean_true_add(json_path
,
8807 "announceNexthopSelf");
8808 if (nexthop_othervrf
) {
8809 json_object_string_add(json_path
, "nhVrfName",
8812 json_object_int_add(json_path
, "nhVrfId",
8813 ((nexthop_vrfid
== VRF_UNKNOWN
)
8815 : (int)nexthop_vrfid
));
8820 if (json_nexthop_global
|| json_nexthop_ll
) {
8821 json_nexthops
= json_object_new_array();
8823 if (json_nexthop_global
)
8824 json_object_array_add(json_nexthops
,
8825 json_nexthop_global
);
8827 if (json_nexthop_ll
)
8828 json_object_array_add(json_nexthops
,
8831 json_object_object_add(json_path
, "nexthops",
8835 json_object_array_add(json_paths
, json_path
);
8839 if (safi
== SAFI_EVPN
) {
8840 struct bgp_path_es_info
*path_es_info
= NULL
;
8843 path_es_info
= path
->extra
->es_info
;
8845 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8846 /* XXX - add these params to the json out */
8847 vty_out(vty
, "%*s", 20, " ");
8848 vty_out(vty
, "ESI:%s",
8849 esi_to_str(&attr
->esi
, esi_buf
,
8851 if (path_es_info
&& path_es_info
->es
)
8852 vty_out(vty
, " VNI: %u",
8857 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8858 vty_out(vty
, "%*s", 20, " ");
8859 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8863 #ifdef ENABLE_BGP_VNC
8864 /* prints an additional line, indented, with VNC info, if
8866 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8867 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8872 /* called from terminal list command */
8873 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8874 struct attr
*attr
, safi_t safi
, bool use_json
,
8875 json_object
*json_ar
, bool wide
)
8877 json_object
*json_status
= NULL
;
8878 json_object
*json_net
= NULL
;
8882 /* Route status display. */
8884 json_status
= json_object_new_object();
8885 json_net
= json_object_new_object();
8892 /* print prefix and mask */
8894 if (safi
== SAFI_EVPN
)
8895 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8896 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8897 json_object_string_add(
8898 json_net
, "addrPrefix",
8899 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8901 json_object_int_add(json_net
, "prefixLen",
8903 prefix2str(p
, buff
, PREFIX_STRLEN
);
8904 json_object_string_add(json_net
, "network", buff
);
8907 route_vty_out_route(p
, vty
, NULL
, wide
);
8909 /* Print attribute */
8912 char buf
[BUFSIZ
] = {0};
8914 if (p
->family
== AF_INET
8915 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8916 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8917 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8918 json_object_string_add(
8919 json_net
, "nextHop",
8922 &attr
->mp_nexthop_global_in
,
8925 json_object_string_add(
8926 json_net
, "nextHop",
8928 &attr
->nexthop
, buf
,
8930 } else if (p
->family
== AF_INET6
8931 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8934 json_object_string_add(
8935 json_net
, "nextHopGlobal",
8937 &attr
->mp_nexthop_global
, buf
,
8939 } else if (p
->family
== AF_EVPN
8940 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8941 char buf
[BUFSIZ
] = {0};
8943 json_object_string_add(
8944 json_net
, "nextHop",
8946 &attr
->mp_nexthop_global_in
,
8951 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8952 json_object_int_add(json_net
, "metric",
8955 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8956 json_object_int_add(json_net
, "locPrf",
8959 json_object_int_add(json_net
, "weight", attr
->weight
);
8963 json_object_string_add(json_net
, "path",
8967 json_object_string_add(json_net
, "bgpOriginCode",
8968 bgp_origin_str
[attr
->origin
]);
8970 if (p
->family
== AF_INET
8971 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8972 || safi
== SAFI_EVPN
8973 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8974 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8975 || safi
== SAFI_EVPN
)
8976 vty_out(vty
, "%-16pI4",
8977 &attr
->mp_nexthop_global_in
);
8979 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
8981 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
8982 } else if (p
->family
== AF_INET6
8983 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8989 &attr
->mp_nexthop_global
, buf
,
8991 len
= wide
? (41 - len
) : (16 - len
);
8993 vty_out(vty
, "\n%*s", 36, " ");
8995 vty_out(vty
, "%*s", len
, " ");
8998 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9000 vty_out(vty
, "%7u", attr
->med
);
9002 vty_out(vty
, "%10u", attr
->med
);
9008 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9009 vty_out(vty
, "%7u", attr
->local_pref
);
9013 vty_out(vty
, "%7u ", attr
->weight
);
9017 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9020 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9024 json_object_boolean_true_add(json_status
, "*");
9025 json_object_boolean_true_add(json_status
, ">");
9026 json_object_object_add(json_net
, "appliedStatusSymbols",
9029 prefix2str(p
, buff
, PREFIX_STRLEN
);
9030 json_object_object_add(json_ar
, buff
, json_net
);
9035 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9036 struct bgp_path_info
*path
, int display
, safi_t safi
,
9039 json_object
*json_out
= NULL
;
9041 mpls_label_t label
= MPLS_INVALID_LABEL
;
9047 json_out
= json_object_new_object();
9049 /* short status lead text */
9050 route_vty_short_status_out(vty
, path
, json_out
);
9052 /* print prefix and mask */
9055 route_vty_out_route(p
, vty
, NULL
, false);
9057 vty_out(vty
, "%*s", 17, " ");
9060 /* Print attribute */
9062 if (((p
->family
== AF_INET
)
9063 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9064 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9065 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9066 char buf
[BUFSIZ
] = {0};
9068 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9069 || safi
== SAFI_EVPN
) {
9071 json_object_string_add(
9072 json_out
, "mpNexthopGlobalIn",
9074 &attr
->mp_nexthop_global_in
,
9077 vty_out(vty
, "%-16pI4",
9078 &attr
->mp_nexthop_global_in
);
9081 json_object_string_add(
9082 json_out
, "nexthop",
9083 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9086 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9088 } else if (((p
->family
== AF_INET6
)
9089 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9090 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9091 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9094 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9096 json_object_string_add(
9097 json_out
, "mpNexthopGlobalIn",
9099 &attr
->mp_nexthop_global
,
9100 buf_a
, sizeof(buf_a
)));
9104 &attr
->mp_nexthop_global
,
9105 buf_a
, sizeof(buf_a
)));
9106 } else if (attr
->mp_nexthop_len
9107 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9108 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9109 &attr
->mp_nexthop_global
,
9110 &attr
->mp_nexthop_local
);
9112 json_object_string_add(json_out
,
9113 "mpNexthopGlobalLocal",
9116 vty_out(vty
, "%s", buf_a
);
9120 label
= decode_label(&path
->extra
->label
[0]);
9122 if (bgp_is_valid_label(&label
)) {
9124 json_object_int_add(json_out
, "notag", label
);
9125 json_object_array_add(json
, json_out
);
9127 vty_out(vty
, "notag/%d", label
);
9133 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9134 struct bgp_path_info
*path
, int display
,
9135 json_object
*json_paths
)
9138 char buf
[BUFSIZ
] = {0};
9139 json_object
*json_path
= NULL
;
9140 json_object
*json_nexthop
= NULL
;
9141 json_object
*json_overlay
= NULL
;
9147 json_path
= json_object_new_object();
9148 json_overlay
= json_object_new_object();
9149 json_nexthop
= json_object_new_object();
9152 /* short status lead text */
9153 route_vty_short_status_out(vty
, path
, json_path
);
9155 /* print prefix and mask */
9157 route_vty_out_route(p
, vty
, json_path
, false);
9159 vty_out(vty
, "%*s", 17, " ");
9161 /* Print attribute */
9164 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9168 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9170 vty_out(vty
, "%-16s", buf
);
9172 json_object_string_add(json_nexthop
, "ip", buf
);
9174 json_object_string_add(json_nexthop
, "afi", "ipv4");
9176 json_object_object_add(json_path
, "nexthop",
9181 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9182 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9184 vty_out(vty
, "%s(%s)", buf
, buf1
);
9186 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9188 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9191 json_object_string_add(json_nexthop
, "afi", "ipv6");
9193 json_object_object_add(json_path
, "nexthop",
9201 json_object_string_add(json_nexthop
, "Error",
9202 "Unsupported address-family");
9206 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9208 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9209 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9210 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9211 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9214 vty_out(vty
, "/%s", buf
);
9216 json_object_string_add(json_overlay
, "gw", buf
);
9218 if (attr
->ecommunity
) {
9220 struct ecommunity_val
*routermac
= ecommunity_lookup(
9221 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9222 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9225 mac
= ecom_mac2str((char *)routermac
->val
);
9228 vty_out(vty
, "/%s", mac
);
9230 json_object_string_add(json_overlay
, "rmac",
9233 XFREE(MTYPE_TMP
, mac
);
9240 json_object_object_add(json_path
, "overlay", json_overlay
);
9242 json_object_array_add(json_paths
, json_path
);
9246 /* dampening route */
9247 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9248 struct bgp_path_info
*path
, int display
,
9249 afi_t afi
, safi_t safi
, bool use_json
,
9254 char timebuf
[BGP_UPTIME_LEN
];
9256 /* short status lead text */
9257 route_vty_short_status_out(vty
, path
, json
);
9259 /* print prefix and mask */
9262 route_vty_out_route(p
, vty
, NULL
, false);
9264 vty_out(vty
, "%*s", 17, " ");
9267 len
= vty_out(vty
, "%s", path
->peer
->host
);
9271 vty_out(vty
, "\n%*s", 34, " ");
9274 json_object_int_add(json
, "peerHost", len
);
9276 vty_out(vty
, "%*s", len
, " ");
9280 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9281 safi
, use_json
, json
);
9284 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9285 BGP_UPTIME_LEN
, afi
, safi
,
9288 /* Print attribute */
9294 json_object_string_add(json
, "asPath",
9297 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9302 json_object_string_add(json
, "origin",
9303 bgp_origin_str
[attr
->origin
]);
9305 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9312 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9313 struct bgp_path_info
*path
, int display
,
9314 afi_t afi
, safi_t safi
, bool use_json
,
9318 struct bgp_damp_info
*bdi
;
9319 char timebuf
[BGP_UPTIME_LEN
];
9325 bdi
= path
->extra
->damp_info
;
9327 /* short status lead text */
9328 route_vty_short_status_out(vty
, path
, json
);
9330 /* print prefix and mask */
9333 route_vty_out_route(p
, vty
, NULL
, false);
9335 vty_out(vty
, "%*s", 17, " ");
9338 len
= vty_out(vty
, "%s", path
->peer
->host
);
9342 vty_out(vty
, "\n%*s", 33, " ");
9345 json_object_int_add(json
, "peerHost", len
);
9347 vty_out(vty
, "%*s", len
, " ");
9350 len
= vty_out(vty
, "%d", bdi
->flap
);
9357 json_object_int_add(json
, "bdiFlap", len
);
9359 vty_out(vty
, "%*s", len
, " ");
9363 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9366 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9367 BGP_UPTIME_LEN
, 0, NULL
));
9369 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9370 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9372 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9373 BGP_UPTIME_LEN
, afi
, safi
,
9377 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9378 BGP_UPTIME_LEN
, afi
,
9379 safi
, use_json
, json
));
9382 vty_out(vty
, "%*s ", 8, " ");
9385 /* Print attribute */
9391 json_object_string_add(json
, "asPath",
9394 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9399 json_object_string_add(json
, "origin",
9400 bgp_origin_str
[attr
->origin
]);
9402 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9408 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9409 int *first
, const char *header
,
9410 json_object
*json_adv_to
)
9412 char buf1
[INET6_ADDRSTRLEN
];
9413 json_object
*json_peer
= NULL
;
9416 /* 'advertised-to' is a dictionary of peers we have advertised
9418 * prefix too. The key is the peer's IP or swpX, the value is
9420 * hostname if we know it and "" if not.
9422 json_peer
= json_object_new_object();
9425 json_object_string_add(json_peer
, "hostname",
9429 json_object_object_add(json_adv_to
, peer
->conf_if
,
9432 json_object_object_add(
9434 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9438 vty_out(vty
, "%s", header
);
9443 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9445 vty_out(vty
, " %s(%s)", peer
->hostname
,
9448 vty_out(vty
, " %s(%s)", peer
->hostname
,
9449 sockunion2str(&peer
->su
, buf1
,
9453 vty_out(vty
, " %s", peer
->conf_if
);
9456 sockunion2str(&peer
->su
, buf1
,
9462 static void route_vty_out_tx_ids(struct vty
*vty
,
9463 struct bgp_addpath_info_data
*d
)
9467 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9468 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9469 d
->addpath_tx_id
[i
],
9470 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9474 static void route_vty_out_detail_es_info(struct vty
*vty
,
9475 struct bgp_path_info
*pi
,
9477 json_object
*json_path
)
9479 char esi_buf
[ESI_STR_LEN
];
9480 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9481 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9482 ATTR_ES_PEER_ROUTER
);
9483 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9484 ATTR_ES_PEER_ACTIVE
);
9485 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9486 ATTR_ES_PEER_PROXY
);
9487 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9489 json_object
*json_es_info
= NULL
;
9491 json_object_string_add(
9494 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9495 json_es_info
= json_object_new_object();
9497 json_object_boolean_true_add(
9498 json_es_info
, "localEs");
9500 json_object_boolean_true_add(
9501 json_es_info
, "peerActive");
9503 json_object_boolean_true_add(
9504 json_es_info
, "peerProxy");
9506 json_object_boolean_true_add(
9507 json_es_info
, "peerRouter");
9508 if (attr
->mm_sync_seqnum
)
9509 json_object_int_add(
9510 json_es_info
, "peerSeq",
9511 attr
->mm_sync_seqnum
);
9512 json_object_object_add(
9513 json_path
, "es_info",
9517 if (bgp_evpn_attr_is_sync(attr
))
9519 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9521 es_local
? "local-es":"",
9522 peer_proxy
? "proxy " : "",
9523 peer_active
? "active ":"",
9524 peer_router
? "router ":"",
9525 attr
->mm_sync_seqnum
);
9527 vty_out(vty
, " ESI %s %s\n",
9529 es_local
? "local-es":"");
9533 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
9534 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
9535 afi_t afi
, safi_t safi
, json_object
*json_paths
)
9537 char buf
[INET6_ADDRSTRLEN
];
9539 struct attr
*attr
= path
->attr
;
9540 int sockunion_vty_out(struct vty
*, union sockunion
*);
9542 json_object
*json_bestpath
= NULL
;
9543 json_object
*json_cluster_list
= NULL
;
9544 json_object
*json_cluster_list_list
= NULL
;
9545 json_object
*json_ext_community
= NULL
;
9546 json_object
*json_last_update
= NULL
;
9547 json_object
*json_pmsi
= NULL
;
9548 json_object
*json_nexthop_global
= NULL
;
9549 json_object
*json_nexthop_ll
= NULL
;
9550 json_object
*json_nexthops
= NULL
;
9551 json_object
*json_path
= NULL
;
9552 json_object
*json_peer
= NULL
;
9553 json_object
*json_string
= NULL
;
9554 json_object
*json_adv_to
= NULL
;
9556 struct listnode
*node
, *nnode
;
9558 int addpath_capable
;
9560 unsigned int first_as
;
9562 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9564 char *nexthop_hostname
=
9565 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9568 json_path
= json_object_new_object();
9569 json_peer
= json_object_new_object();
9570 json_nexthop_global
= json_object_new_object();
9577 if (path
->extra
&& path
->extra
->num_labels
) {
9578 bgp_evpn_label2str(path
->extra
->label
,
9579 path
->extra
->num_labels
, tag_buf
,
9582 if (safi
== SAFI_EVPN
) {
9584 vty_out(vty
, " Route %pFX",
9585 (struct prefix_evpn
*)
9586 bgp_dest_get_prefix(bn
));
9587 if (tag_buf
[0] != '\0')
9588 vty_out(vty
, " VNI %s", tag_buf
);
9592 json_object_string_add(json_path
, "VNI",
9597 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9598 struct bgp_path_info
*parent_ri
;
9599 struct bgp_dest
*dest
, *pdest
;
9601 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9602 dest
= parent_ri
->net
;
9603 if (dest
&& dest
->pdest
) {
9604 pdest
= dest
->pdest
;
9606 (struct prefix_rd
*)bgp_dest_get_prefix(
9608 buf1
, sizeof(buf1
));
9609 if (is_pi_family_evpn(parent_ri
)) {
9611 " Imported from %s:%pFX, VNI %s\n",
9613 (struct prefix_evpn
*)
9614 bgp_dest_get_prefix(
9619 " Imported from %s:%pFX\n",
9621 (struct prefix_evpn
*)
9622 bgp_dest_get_prefix(
9628 /* Line1 display AS-path, Aggregator */
9631 if (!attr
->aspath
->json
)
9632 aspath_str_update(attr
->aspath
, true);
9633 json_object_lock(attr
->aspath
->json
);
9634 json_object_object_add(json_path
, "aspath",
9635 attr
->aspath
->json
);
9637 if (attr
->aspath
->segments
)
9638 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9640 vty_out(vty
, " Local");
9644 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9646 json_object_boolean_true_add(json_path
, "removed");
9648 vty_out(vty
, ", (removed)");
9651 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9653 json_object_boolean_true_add(json_path
, "stale");
9655 vty_out(vty
, ", (stale)");
9658 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9660 char buf
[BUFSIZ
] = {0};
9662 json_object_int_add(json_path
, "aggregatorAs",
9663 attr
->aggregator_as
);
9664 json_object_string_add(json_path
, "aggregatorId",
9666 &attr
->aggregator_addr
,
9669 vty_out(vty
, ", (aggregated by %u %pI4)",
9670 attr
->aggregator_as
, &attr
->aggregator_addr
);
9674 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9675 PEER_FLAG_REFLECTOR_CLIENT
)) {
9677 json_object_boolean_true_add(json_path
,
9678 "rxedFromRrClient");
9680 vty_out(vty
, ", (Received from a RR-client)");
9683 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9684 PEER_FLAG_RSERVER_CLIENT
)) {
9686 json_object_boolean_true_add(json_path
,
9687 "rxedFromRsClient");
9689 vty_out(vty
, ", (Received from a RS-client)");
9692 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9694 json_object_boolean_true_add(json_path
,
9695 "dampeningHistoryEntry");
9697 vty_out(vty
, ", (history entry)");
9698 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9700 json_object_boolean_true_add(json_path
,
9701 "dampeningSuppressed");
9703 vty_out(vty
, ", (suppressed due to dampening)");
9709 /* Line2 display Next-hop, Neighbor, Router-id */
9710 /* Display the nexthop */
9711 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9713 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9714 || bn_p
->family
== AF_EVPN
)
9715 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9716 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9717 char buf
[BUFSIZ
] = {0};
9719 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9720 || safi
== SAFI_EVPN
) {
9722 json_object_string_add(
9723 json_nexthop_global
, "ip",
9725 &attr
->mp_nexthop_global_in
,
9728 if (path
->peer
->hostname
)
9729 json_object_string_add(
9730 json_nexthop_global
, "hostname",
9731 path
->peer
->hostname
);
9733 if (nexthop_hostname
)
9734 vty_out(vty
, " %pI4(%s)",
9735 &attr
->mp_nexthop_global_in
,
9738 vty_out(vty
, " %pI4",
9739 &attr
->mp_nexthop_global_in
);
9743 json_object_string_add(
9744 json_nexthop_global
, "ip",
9745 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9748 if (path
->peer
->hostname
)
9749 json_object_string_add(
9750 json_nexthop_global
, "hostname",
9751 path
->peer
->hostname
);
9753 if (nexthop_hostname
)
9754 vty_out(vty
, " %pI4(%s)",
9758 vty_out(vty
, " %pI4",
9764 json_object_string_add(json_nexthop_global
, "afi",
9768 json_object_string_add(
9769 json_nexthop_global
, "ip",
9770 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9771 buf
, INET6_ADDRSTRLEN
));
9773 if (path
->peer
->hostname
)
9774 json_object_string_add(json_nexthop_global
,
9776 path
->peer
->hostname
);
9778 json_object_string_add(json_nexthop_global
, "afi",
9780 json_object_string_add(json_nexthop_global
, "scope",
9783 if (nexthop_hostname
)
9784 vty_out(vty
, " %pI6(%s)",
9785 &attr
->mp_nexthop_global
,
9788 vty_out(vty
, " %pI6",
9789 &attr
->mp_nexthop_global
);
9793 /* Display the IGP cost or 'inaccessible' */
9794 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9796 json_object_boolean_false_add(json_nexthop_global
,
9799 vty_out(vty
, " (inaccessible)");
9801 if (path
->extra
&& path
->extra
->igpmetric
) {
9803 json_object_int_add(json_nexthop_global
,
9805 path
->extra
->igpmetric
);
9807 vty_out(vty
, " (metric %u)",
9808 path
->extra
->igpmetric
);
9811 /* IGP cost is 0, display this only for json */
9814 json_object_int_add(json_nexthop_global
,
9819 json_object_boolean_true_add(json_nexthop_global
,
9823 /* Display peer "from" output */
9824 /* This path was originated locally */
9825 if (path
->peer
== bgp
->peer_self
) {
9827 if (safi
== SAFI_EVPN
9828 || (bn_p
->family
== AF_INET
9829 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9831 json_object_string_add(json_peer
, "peerId",
9834 vty_out(vty
, " from 0.0.0.0 ");
9837 json_object_string_add(json_peer
, "peerId",
9840 vty_out(vty
, " from :: ");
9844 char buf
[BUFSIZ
] = {0};
9846 json_object_string_add(json_peer
, "routerId",
9848 &bgp
->router_id
, buf
,
9851 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
9855 /* We RXed this path from one of our peers */
9859 json_object_string_add(json_peer
, "peerId",
9860 sockunion2str(&path
->peer
->su
,
9863 json_object_string_add(json_peer
, "routerId",
9865 &path
->peer
->remote_id
,
9866 buf1
, sizeof(buf1
)));
9868 if (path
->peer
->hostname
)
9869 json_object_string_add(json_peer
, "hostname",
9870 path
->peer
->hostname
);
9872 if (path
->peer
->domainname
)
9873 json_object_string_add(json_peer
, "domainname",
9874 path
->peer
->domainname
);
9876 if (path
->peer
->conf_if
)
9877 json_object_string_add(json_peer
, "interface",
9878 path
->peer
->conf_if
);
9880 if (path
->peer
->conf_if
) {
9881 if (path
->peer
->hostname
9882 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9883 BGP_FLAG_SHOW_HOSTNAME
))
9884 vty_out(vty
, " from %s(%s)",
9885 path
->peer
->hostname
,
9886 path
->peer
->conf_if
);
9888 vty_out(vty
, " from %s",
9889 path
->peer
->conf_if
);
9891 if (path
->peer
->hostname
9892 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9893 BGP_FLAG_SHOW_HOSTNAME
))
9894 vty_out(vty
, " from %s(%s)",
9895 path
->peer
->hostname
,
9898 vty_out(vty
, " from %s",
9899 sockunion2str(&path
->peer
->su
,
9904 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9905 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
9907 vty_out(vty
, " (%s)",
9909 &path
->peer
->remote_id
, buf1
,
9915 * Note when vrfid of nexthop is different from that of prefix
9917 if (path
->extra
&& path
->extra
->bgp_orig
) {
9918 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9923 if (path
->extra
->bgp_orig
->inst_type
9924 == BGP_INSTANCE_TYPE_DEFAULT
)
9925 vn
= VRF_DEFAULT_NAME
;
9927 vn
= path
->extra
->bgp_orig
->name
;
9929 json_object_string_add(json_path
, "nhVrfName", vn
);
9931 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9932 json_object_int_add(json_path
, "nhVrfId", -1);
9934 json_object_int_add(json_path
, "nhVrfId",
9935 (int)nexthop_vrfid
);
9938 if (nexthop_vrfid
== VRF_UNKNOWN
)
9939 vty_out(vty
, " vrf ?");
9943 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9944 vty_out(vty
, " vrf %s(%u)",
9945 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9952 json_object_boolean_true_add(json_path
,
9953 "announceNexthopSelf");
9955 vty_out(vty
, " announce-nh-self");
9962 /* display the link-local nexthop */
9963 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9965 json_nexthop_ll
= json_object_new_object();
9966 json_object_string_add(
9967 json_nexthop_ll
, "ip",
9968 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9969 buf
, INET6_ADDRSTRLEN
));
9971 if (path
->peer
->hostname
)
9972 json_object_string_add(json_nexthop_ll
,
9974 path
->peer
->hostname
);
9976 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9977 json_object_string_add(json_nexthop_ll
, "scope",
9980 json_object_boolean_true_add(json_nexthop_ll
,
9983 if (!attr
->mp_nexthop_prefer_global
)
9984 json_object_boolean_true_add(json_nexthop_ll
,
9987 json_object_boolean_true_add(
9988 json_nexthop_global
, "used");
9990 vty_out(vty
, " (%s) %s\n",
9991 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9992 buf
, INET6_ADDRSTRLEN
),
9993 attr
->mp_nexthop_prefer_global
9998 /* If we do not have a link-local nexthop then we must flag the
10002 json_object_boolean_true_add(json_nexthop_global
,
10006 if (safi
== SAFI_EVPN
&&
10007 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10008 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10011 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10012 * Int/Ext/Local, Atomic, best */
10014 json_object_string_add(json_path
, "origin",
10015 bgp_origin_long_str
[attr
->origin
]);
10017 vty_out(vty
, " Origin %s",
10018 bgp_origin_long_str
[attr
->origin
]);
10020 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10022 json_object_int_add(json_path
, "metric", attr
->med
);
10024 vty_out(vty
, ", metric %u", attr
->med
);
10027 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10029 json_object_int_add(json_path
, "locPrf",
10032 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10035 if (attr
->weight
!= 0) {
10037 json_object_int_add(json_path
, "weight", attr
->weight
);
10039 vty_out(vty
, ", weight %u", attr
->weight
);
10042 if (attr
->tag
!= 0) {
10044 json_object_int_add(json_path
, "tag", attr
->tag
);
10046 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10049 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10051 json_object_boolean_false_add(json_path
, "valid");
10053 vty_out(vty
, ", invalid");
10054 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10056 json_object_boolean_true_add(json_path
, "valid");
10058 vty_out(vty
, ", valid");
10061 if (path
->peer
!= bgp
->peer_self
) {
10062 if (path
->peer
->as
== path
->peer
->local_as
) {
10063 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10065 json_object_string_add(
10067 "confed-internal");
10069 vty_out(vty
, ", confed-internal");
10072 json_object_string_add(
10073 json_peer
, "type", "internal");
10075 vty_out(vty
, ", internal");
10078 if (bgp_confederation_peers_check(bgp
,
10081 json_object_string_add(
10083 "confed-external");
10085 vty_out(vty
, ", confed-external");
10088 json_object_string_add(
10089 json_peer
, "type", "external");
10091 vty_out(vty
, ", external");
10094 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10096 json_object_boolean_true_add(json_path
, "aggregated");
10097 json_object_boolean_true_add(json_path
, "local");
10099 vty_out(vty
, ", aggregated, local");
10101 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10103 json_object_boolean_true_add(json_path
, "sourced");
10105 vty_out(vty
, ", sourced");
10108 json_object_boolean_true_add(json_path
, "sourced");
10109 json_object_boolean_true_add(json_path
, "local");
10111 vty_out(vty
, ", sourced, local");
10115 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10117 json_object_boolean_true_add(json_path
,
10118 "atomicAggregate");
10120 vty_out(vty
, ", atomic-aggregate");
10123 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10124 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10125 && bgp_path_info_mpath_count(path
))) {
10127 json_object_boolean_true_add(json_path
, "multipath");
10129 vty_out(vty
, ", multipath");
10132 // Mark the bestpath(s)
10133 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10134 first_as
= aspath_get_first_as(attr
->aspath
);
10137 if (!json_bestpath
)
10138 json_bestpath
= json_object_new_object();
10139 json_object_int_add(json_bestpath
, "bestpathFromAs",
10143 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10145 vty_out(vty
, ", bestpath-from-AS Local");
10149 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10151 if (!json_bestpath
)
10152 json_bestpath
= json_object_new_object();
10153 json_object_boolean_true_add(json_bestpath
, "overall");
10154 json_object_string_add(
10155 json_bestpath
, "selectionReason",
10156 bgp_path_selection_reason2str(bn
->reason
));
10158 vty_out(vty
, ", best");
10159 vty_out(vty
, " (%s)",
10160 bgp_path_selection_reason2str(bn
->reason
));
10165 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10168 vty_out(vty
, "\n");
10170 /* Line 4 display Community */
10171 if (attr
->community
) {
10173 if (!attr
->community
->json
)
10174 community_str(attr
->community
, true);
10175 json_object_lock(attr
->community
->json
);
10176 json_object_object_add(json_path
, "community",
10177 attr
->community
->json
);
10179 vty_out(vty
, " Community: %s\n",
10180 attr
->community
->str
);
10184 /* Line 5 display Extended-community */
10185 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10187 json_ext_community
= json_object_new_object();
10188 json_object_string_add(json_ext_community
, "string",
10189 attr
->ecommunity
->str
);
10190 json_object_object_add(json_path
, "extendedCommunity",
10191 json_ext_community
);
10193 vty_out(vty
, " Extended Community: %s\n",
10194 attr
->ecommunity
->str
);
10198 /* Line 6 display Large community */
10199 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10201 if (!attr
->lcommunity
->json
)
10202 lcommunity_str(attr
->lcommunity
, true);
10203 json_object_lock(attr
->lcommunity
->json
);
10204 json_object_object_add(json_path
, "largeCommunity",
10205 attr
->lcommunity
->json
);
10207 vty_out(vty
, " Large Community: %s\n",
10208 attr
->lcommunity
->str
);
10212 /* Line 7 display Originator, Cluster-id */
10213 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10214 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10215 char buf
[BUFSIZ
] = {0};
10217 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10219 json_object_string_add(
10220 json_path
, "originatorId",
10221 inet_ntop(AF_INET
, &attr
->originator_id
,
10222 buf
, sizeof(buf
)));
10224 vty_out(vty
, " Originator: %pI4",
10225 &attr
->originator_id
);
10228 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10229 struct cluster_list
*cluster
=
10230 bgp_attr_get_cluster(attr
);
10234 json_cluster_list
= json_object_new_object();
10235 json_cluster_list_list
=
10236 json_object_new_array();
10238 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10239 json_string
= json_object_new_string(
10242 buf
, sizeof(buf
)));
10243 json_object_array_add(
10244 json_cluster_list_list
,
10249 * struct cluster_list does not have
10250 * "str" variable like aspath and community
10251 * do. Add this someday if someone asks
10253 * json_object_string_add(json_cluster_list,
10254 * "string", cluster->str);
10256 json_object_object_add(json_cluster_list
,
10258 json_cluster_list_list
);
10259 json_object_object_add(json_path
, "clusterList",
10260 json_cluster_list
);
10262 vty_out(vty
, ", Cluster list: ");
10264 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10265 vty_out(vty
, "%pI4 ",
10266 &cluster
->list
[i
]);
10272 vty_out(vty
, "\n");
10275 if (path
->extra
&& path
->extra
->damp_info
)
10276 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10279 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10280 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10281 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10284 json_object_int_add(json_path
, "remoteLabel", label
);
10286 vty_out(vty
, " Remote label: %d\n", label
);
10290 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10291 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10293 json_object_string_add(json_path
, "remoteSid", buf
);
10295 vty_out(vty
, " Remote SID: %s\n", buf
);
10299 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10301 json_object_int_add(json_path
, "labelIndex",
10302 attr
->label_index
);
10304 vty_out(vty
, " Label Index: %d\n",
10305 attr
->label_index
);
10308 /* Line 8 display Addpath IDs */
10309 if (path
->addpath_rx_id
10310 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10312 json_object_int_add(json_path
, "addpathRxId",
10313 path
->addpath_rx_id
);
10315 /* Keep backwards compatibility with the old API
10316 * by putting TX All's ID in the old field
10318 json_object_int_add(
10319 json_path
, "addpathTxId",
10321 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10323 /* ... but create a specific field for each
10326 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10327 json_object_int_add(
10329 bgp_addpath_names(i
)->id_json_name
,
10330 path
->tx_addpath
.addpath_tx_id
[i
]);
10333 vty_out(vty
, " AddPath ID: RX %u, ",
10334 path
->addpath_rx_id
);
10336 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10340 /* If we used addpath to TX a non-bestpath we need to display
10341 * "Advertised to" on a path-by-path basis
10343 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10346 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10348 bgp_addpath_encode_tx(peer
, afi
, safi
);
10349 has_adj
= bgp_adj_out_lookup(
10351 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10352 &path
->tx_addpath
));
10354 if ((addpath_capable
&& has_adj
)
10355 || (!addpath_capable
&& has_adj
10356 && CHECK_FLAG(path
->flags
,
10357 BGP_PATH_SELECTED
))) {
10358 if (json_path
&& !json_adv_to
)
10359 json_adv_to
= json_object_new_object();
10361 route_vty_out_advertised_to(
10363 " Advertised to:", json_adv_to
);
10369 json_object_object_add(
10370 json_path
, "advertisedTo", json_adv_to
);
10374 vty_out(vty
, "\n");
10379 /* Line 9 display Uptime */
10380 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10382 json_last_update
= json_object_new_object();
10383 json_object_int_add(json_last_update
, "epoch", tbuf
);
10384 json_object_string_add(json_last_update
, "string",
10386 json_object_object_add(json_path
, "lastUpdate",
10389 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10391 /* Line 10 display PMSI tunnel attribute, if present */
10392 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10393 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10394 bgp_attr_get_pmsi_tnl_type(attr
),
10395 PMSI_TNLTYPE_STR_DEFAULT
);
10398 json_pmsi
= json_object_new_object();
10399 json_object_string_add(json_pmsi
, "tunnelType", str
);
10400 json_object_int_add(json_pmsi
, "label",
10401 label2vni(&attr
->label
));
10402 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10404 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10405 str
, label2vni(&attr
->label
));
10408 /* Output some debug about internal state of the dest flags */
10410 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10411 json_object_boolean_true_add(json_path
, "processScheduled");
10412 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10413 json_object_boolean_true_add(json_path
, "userCleared");
10414 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10415 json_object_boolean_true_add(json_path
, "labelChanged");
10416 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10417 json_object_boolean_true_add(json_path
, "registeredForLabel");
10418 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10419 json_object_boolean_true_add(json_path
, "selectDefered");
10420 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10421 json_object_boolean_true_add(json_path
, "fibInstalled");
10422 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10423 json_object_boolean_true_add(json_path
, "fibPending");
10426 /* We've constructed the json object for this path, add it to the json
10430 if (json_nexthop_global
|| json_nexthop_ll
) {
10431 json_nexthops
= json_object_new_array();
10433 if (json_nexthop_global
)
10434 json_object_array_add(json_nexthops
,
10435 json_nexthop_global
);
10437 if (json_nexthop_ll
)
10438 json_object_array_add(json_nexthops
,
10441 json_object_object_add(json_path
, "nexthops",
10445 json_object_object_add(json_path
, "peer", json_peer
);
10446 json_object_array_add(json_paths
, json_path
);
10450 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10451 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10452 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10454 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10455 const char *prefix_list_str
, afi_t afi
,
10456 safi_t safi
, enum bgp_show_type type
);
10457 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10458 const char *filter
, afi_t afi
, safi_t safi
,
10459 enum bgp_show_type type
);
10460 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10461 const char *rmap_str
, afi_t afi
, safi_t safi
,
10462 enum bgp_show_type type
);
10463 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10464 const char *com
, int exact
, afi_t afi
,
10466 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10467 const char *prefix
, afi_t afi
, safi_t safi
,
10468 enum bgp_show_type type
);
10469 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10470 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10472 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10473 const char *comstr
, int exact
, afi_t afi
,
10474 safi_t safi
, uint8_t show_flags
);
10477 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10478 struct bgp_table
*table
, enum bgp_show_type type
,
10479 void *output_arg
, char *rd
, int is_last
,
10480 unsigned long *output_cum
, unsigned long *total_cum
,
10481 unsigned long *json_header_depth
, uint8_t show_flags
)
10483 struct bgp_path_info
*pi
;
10484 struct bgp_dest
*dest
;
10487 unsigned long output_count
= 0;
10488 unsigned long total_count
= 0;
10490 json_object
*json_paths
= NULL
;
10492 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10493 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10494 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10496 if (output_cum
&& *output_cum
!= 0)
10499 if (use_json
&& !*json_header_depth
) {
10501 *json_header_depth
= 1;
10503 vty_out(vty
, "{\n");
10504 *json_header_depth
= 2;
10508 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10509 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10510 " \"localAS\": %u,\n \"routes\": { ",
10511 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10512 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10515 table
->version
, &bgp
->router_id
,
10516 bgp
->default_local_pref
, bgp
->as
);
10518 vty_out(vty
, " \"routeDistinguishers\" : {");
10519 ++*json_header_depth
;
10523 if (use_json
&& rd
) {
10524 vty_out(vty
, " \"%s\" : { ", rd
);
10527 /* Start processing of routes. */
10528 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10529 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10531 pi
= bgp_dest_get_bgp_path_info(dest
);
10537 json_paths
= json_object_new_array();
10541 for (; pi
; pi
= pi
->next
) {
10543 if (type
== bgp_show_type_flap_statistics
10544 || type
== bgp_show_type_flap_neighbor
10545 || type
== bgp_show_type_dampend_paths
10546 || type
== bgp_show_type_damp_neighbor
) {
10547 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10550 if (type
== bgp_show_type_regexp
) {
10551 regex_t
*regex
= output_arg
;
10553 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10557 if (type
== bgp_show_type_prefix_list
) {
10558 struct prefix_list
*plist
= output_arg
;
10560 if (prefix_list_apply(plist
, dest_p
)
10564 if (type
== bgp_show_type_filter_list
) {
10565 struct as_list
*as_list
= output_arg
;
10567 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10568 != AS_FILTER_PERMIT
)
10571 if (type
== bgp_show_type_route_map
) {
10572 struct route_map
*rmap
= output_arg
;
10573 struct bgp_path_info path
;
10574 struct attr dummy_attr
;
10575 route_map_result_t ret
;
10577 dummy_attr
= *pi
->attr
;
10579 path
.peer
= pi
->peer
;
10580 path
.attr
= &dummy_attr
;
10582 ret
= route_map_apply(rmap
, dest_p
, &path
);
10583 if (ret
== RMAP_DENYMATCH
)
10586 if (type
== bgp_show_type_neighbor
10587 || type
== bgp_show_type_flap_neighbor
10588 || type
== bgp_show_type_damp_neighbor
) {
10589 union sockunion
*su
= output_arg
;
10591 if (pi
->peer
== NULL
10592 || pi
->peer
->su_remote
== NULL
10593 || !sockunion_same(pi
->peer
->su_remote
, su
))
10596 if (type
== bgp_show_type_cidr_only
) {
10597 uint32_t destination
;
10599 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10600 if (IN_CLASSC(destination
)
10601 && dest_p
->prefixlen
== 24)
10603 if (IN_CLASSB(destination
)
10604 && dest_p
->prefixlen
== 16)
10606 if (IN_CLASSA(destination
)
10607 && dest_p
->prefixlen
== 8)
10610 if (type
== bgp_show_type_prefix_longer
) {
10612 if (!prefix_match(p
, dest_p
))
10615 if (type
== bgp_show_type_community_all
) {
10616 if (!pi
->attr
->community
)
10619 if (type
== bgp_show_type_community
) {
10620 struct community
*com
= output_arg
;
10622 if (!pi
->attr
->community
10623 || !community_match(pi
->attr
->community
,
10627 if (type
== bgp_show_type_community_exact
) {
10628 struct community
*com
= output_arg
;
10630 if (!pi
->attr
->community
10631 || !community_cmp(pi
->attr
->community
, com
))
10634 if (type
== bgp_show_type_community_list
) {
10635 struct community_list
*list
= output_arg
;
10637 if (!community_list_match(pi
->attr
->community
,
10641 if (type
== bgp_show_type_community_list_exact
) {
10642 struct community_list
*list
= output_arg
;
10644 if (!community_list_exact_match(
10645 pi
->attr
->community
, list
))
10648 if (type
== bgp_show_type_lcommunity
) {
10649 struct lcommunity
*lcom
= output_arg
;
10651 if (!pi
->attr
->lcommunity
10652 || !lcommunity_match(pi
->attr
->lcommunity
,
10657 if (type
== bgp_show_type_lcommunity_exact
) {
10658 struct lcommunity
*lcom
= output_arg
;
10660 if (!pi
->attr
->lcommunity
10661 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10665 if (type
== bgp_show_type_lcommunity_list
) {
10666 struct community_list
*list
= output_arg
;
10668 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10673 == bgp_show_type_lcommunity_list_exact
) {
10674 struct community_list
*list
= output_arg
;
10676 if (!lcommunity_list_exact_match(
10677 pi
->attr
->lcommunity
, list
))
10680 if (type
== bgp_show_type_lcommunity_all
) {
10681 if (!pi
->attr
->lcommunity
)
10684 if (type
== bgp_show_type_dampend_paths
10685 || type
== bgp_show_type_damp_neighbor
) {
10686 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10687 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10691 if (!use_json
&& header
) {
10693 "BGP table version is %" PRIu64
10694 ", local router ID is %pI4, vrf id ",
10695 table
->version
, &bgp
->router_id
);
10696 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10697 vty_out(vty
, "%s", VRFID_NONE_STR
);
10699 vty_out(vty
, "%u", bgp
->vrf_id
);
10700 vty_out(vty
, "\n");
10701 vty_out(vty
, "Default local pref %u, ",
10702 bgp
->default_local_pref
);
10703 vty_out(vty
, "local AS %u\n", bgp
->as
);
10704 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10705 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10706 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10707 if (type
== bgp_show_type_dampend_paths
10708 || type
== bgp_show_type_damp_neighbor
)
10709 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10710 else if (type
== bgp_show_type_flap_statistics
10711 || type
== bgp_show_type_flap_neighbor
)
10712 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10714 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10715 : BGP_SHOW_HEADER
));
10718 if (rd
!= NULL
&& !display
&& !output_count
) {
10721 "Route Distinguisher: %s\n",
10724 if (type
== bgp_show_type_dampend_paths
10725 || type
== bgp_show_type_damp_neighbor
)
10726 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10727 AFI_IP
, safi
, use_json
,
10729 else if (type
== bgp_show_type_flap_statistics
10730 || type
== bgp_show_type_flap_neighbor
)
10731 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10732 AFI_IP
, safi
, use_json
,
10735 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10745 /* encode prefix */
10746 if (dest_p
->family
== AF_FLOWSPEC
) {
10747 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10750 bgp_fs_nlri_get_string(
10752 dest_p
->u
.prefix_flowspec
.ptr
,
10753 dest_p
->u
.prefix_flowspec
.prefixlen
,
10754 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10755 family2afi(dest_p
->u
10756 .prefix_flowspec
.family
));
10758 vty_out(vty
, "\"%s/%d\": ", retstr
,
10759 dest_p
->u
.prefix_flowspec
10762 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10763 dest_p
->u
.prefix_flowspec
10767 vty_out(vty
, "\"%pFX\": ", dest_p
);
10769 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10772 json_object_to_json_string_ext(
10773 json_paths
, JSON_C_TO_STRING_PRETTY
));
10774 json_object_free(json_paths
);
10778 json_object_free(json_paths
);
10782 output_count
+= *output_cum
;
10783 *output_cum
= output_count
;
10786 total_count
+= *total_cum
;
10787 *total_cum
= total_count
;
10791 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10795 for (i
= 0; i
< *json_header_depth
; ++i
)
10796 vty_out(vty
, " } ");
10798 vty_out(vty
, "\n");
10802 /* No route is displayed */
10803 if (output_count
== 0) {
10804 if (type
== bgp_show_type_normal
)
10806 "No BGP prefixes displayed, %ld exist\n",
10810 "\nDisplayed %ld routes and %ld total paths\n",
10811 output_count
, total_count
);
10815 return CMD_SUCCESS
;
10818 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10819 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10820 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10822 struct bgp_dest
*dest
, *next
;
10823 unsigned long output_cum
= 0;
10824 unsigned long total_cum
= 0;
10825 unsigned long json_header_depth
= 0;
10826 struct bgp_table
*itable
;
10828 uint8_t show_flags
= 0;
10830 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10833 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10835 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10836 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10838 next
= bgp_route_next(dest
);
10839 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10842 itable
= bgp_dest_get_bgp_table_info(dest
);
10843 if (itable
!= NULL
) {
10844 struct prefix_rd prd
;
10845 char rd
[RD_ADDRSTRLEN
];
10847 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10848 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10849 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10850 rd
, next
== NULL
, &output_cum
,
10851 &total_cum
, &json_header_depth
,
10858 if (output_cum
== 0)
10859 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10863 "\nDisplayed %ld routes and %ld total paths\n",
10864 output_cum
, total_cum
);
10866 return CMD_SUCCESS
;
10868 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10869 enum bgp_show_type type
, void *output_arg
,
10870 uint8_t show_flags
)
10872 struct bgp_table
*table
;
10873 unsigned long json_header_depth
= 0;
10874 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10877 bgp
= bgp_get_default();
10882 vty_out(vty
, "No BGP process is configured\n");
10884 vty_out(vty
, "{}\n");
10885 return CMD_WARNING
;
10888 table
= bgp
->rib
[afi
][safi
];
10889 /* use MPLS and ENCAP specific shows until they are merged */
10890 if (safi
== SAFI_MPLS_VPN
) {
10891 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10892 output_arg
, use_json
);
10895 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10896 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10897 output_arg
, use_json
,
10900 /* labeled-unicast routes live in the unicast table */
10901 else if (safi
== SAFI_LABELED_UNICAST
)
10902 safi
= SAFI_UNICAST
;
10904 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10905 NULL
, NULL
, &json_header_depth
, show_flags
);
10908 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10909 safi_t safi
, uint8_t show_flags
)
10911 struct listnode
*node
, *nnode
;
10914 bool route_output
= false;
10915 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10918 vty_out(vty
, "{\n");
10920 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10921 route_output
= true;
10924 vty_out(vty
, ",\n");
10928 vty_out(vty
, "\"%s\":",
10929 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10933 vty_out(vty
, "\nInstance %s:\n",
10934 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10938 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10943 vty_out(vty
, "}\n");
10944 else if (!route_output
)
10945 vty_out(vty
, "%% BGP instance not found\n");
10948 /* Header of detailed BGP route information */
10949 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10950 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10951 afi_t afi
, safi_t safi
, json_object
*json
)
10953 struct bgp_path_info
*pi
;
10954 const struct prefix
*p
;
10956 struct listnode
*node
, *nnode
;
10957 char buf1
[RD_ADDRSTRLEN
];
10958 char prefix_str
[BUFSIZ
];
10962 int accept_own
= 0;
10963 int route_filter_translated_v4
= 0;
10964 int route_filter_v4
= 0;
10965 int route_filter_translated_v6
= 0;
10966 int route_filter_v6
= 0;
10967 int llgr_stale
= 0;
10969 int accept_own_nexthop
= 0;
10972 int no_advertise
= 0;
10976 int has_valid_label
= 0;
10977 mpls_label_t label
= 0;
10978 json_object
*json_adv_to
= NULL
;
10980 p
= bgp_dest_get_prefix(dest
);
10981 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10983 if (has_valid_label
)
10984 label
= label_pton(&dest
->local_label
);
10986 if (safi
== SAFI_EVPN
) {
10989 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
10990 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10992 prd
? ":" : "", (struct prefix_evpn
*)p
);
10994 json_object_string_add(json
, "rd",
10995 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
10997 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11001 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11002 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11003 ? prefix_rd2str(prd
, buf1
,
11006 safi
== SAFI_MPLS_VPN
? ":" : "", p
);
11009 json_object_string_add(json
, "prefix",
11010 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11013 if (has_valid_label
) {
11015 json_object_int_add(json
, "localLabel", label
);
11017 vty_out(vty
, "Local label: %d\n", label
);
11021 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11022 vty_out(vty
, "not allocated\n");
11024 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11026 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11028 if (bgp_path_suppressed(pi
))
11031 if (pi
->attr
->community
== NULL
)
11034 no_advertise
+= community_include(
11035 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11036 no_export
+= community_include(pi
->attr
->community
,
11037 COMMUNITY_NO_EXPORT
);
11038 local_as
+= community_include(pi
->attr
->community
,
11039 COMMUNITY_LOCAL_AS
);
11040 accept_own
+= community_include(pi
->attr
->community
,
11041 COMMUNITY_ACCEPT_OWN
);
11042 route_filter_translated_v4
+= community_include(
11043 pi
->attr
->community
,
11044 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11045 route_filter_translated_v6
+= community_include(
11046 pi
->attr
->community
,
11047 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11048 route_filter_v4
+= community_include(
11049 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11050 route_filter_v6
+= community_include(
11051 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11052 llgr_stale
+= community_include(pi
->attr
->community
,
11053 COMMUNITY_LLGR_STALE
);
11054 no_llgr
+= community_include(pi
->attr
->community
,
11055 COMMUNITY_NO_LLGR
);
11056 accept_own_nexthop
+=
11057 community_include(pi
->attr
->community
,
11058 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11059 blackhole
+= community_include(pi
->attr
->community
,
11060 COMMUNITY_BLACKHOLE
);
11061 no_peer
+= community_include(pi
->attr
->community
,
11062 COMMUNITY_NO_PEER
);
11067 vty_out(vty
, "Paths: (%d available", count
);
11069 vty_out(vty
, ", best #%d", best
);
11070 if (safi
== SAFI_UNICAST
) {
11071 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11072 vty_out(vty
, ", table %s",
11075 vty_out(vty
, ", vrf %s",
11079 vty_out(vty
, ", no best path");
11083 ", accept own local route exported and imported in different VRF");
11084 else if (route_filter_translated_v4
)
11086 ", mark translated RTs for VPNv4 route filtering");
11087 else if (route_filter_v4
)
11089 ", attach RT as-is for VPNv4 route filtering");
11090 else if (route_filter_translated_v6
)
11092 ", mark translated RTs for VPNv6 route filtering");
11093 else if (route_filter_v6
)
11095 ", attach RT as-is for VPNv6 route filtering");
11096 else if (llgr_stale
)
11098 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11101 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11102 else if (accept_own_nexthop
)
11104 ", accept local nexthop");
11105 else if (blackhole
)
11106 vty_out(vty
, ", inform peer to blackhole prefix");
11107 else if (no_export
)
11108 vty_out(vty
, ", not advertised to EBGP peer");
11109 else if (no_advertise
)
11110 vty_out(vty
, ", not advertised to any peer");
11112 vty_out(vty
, ", not advertised outside local AS");
11115 ", inform EBGP peer not to advertise to their EBGP peers");
11119 ", Advertisements suppressed by an aggregate.");
11120 vty_out(vty
, ")\n");
11123 /* If we are not using addpath then we can display Advertised to and
11125 * show what peers we advertised the bestpath to. If we are using
11127 * though then we must display Advertised to on a path-by-path basis. */
11128 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11129 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11130 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11131 if (json
&& !json_adv_to
)
11132 json_adv_to
= json_object_new_object();
11134 route_vty_out_advertised_to(
11136 " Advertised to non peer-group peers:\n ",
11143 json_object_object_add(json
, "advertisedTo",
11148 vty_out(vty
, " Not advertised to any peer");
11149 vty_out(vty
, "\n");
11154 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11155 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11156 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11157 json_object
*json
, enum bgp_path_type pathtype
,
11160 struct bgp_path_info
*pi
;
11162 char rdbuf
[RD_ADDRSTRLEN
];
11163 json_object
*json_header
= NULL
;
11164 json_object
*json_paths
= NULL
;
11166 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11168 if (json
&& !json_paths
) {
11169 /* Instantiate json_paths only if path is valid */
11170 json_paths
= json_object_new_array();
11172 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11173 json_header
= json_object_new_object();
11175 json_header
= json
;
11179 route_vty_out_detail_header(
11180 vty
, bgp
, bgp_node
, pfx_rd
,
11181 AFI_IP
, safi
, json_header
);
11186 if (pathtype
== BGP_PATH_SHOW_ALL
11187 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11188 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11189 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11190 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11191 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11192 route_vty_out_detail(vty
, bgp
, bgp_node
,
11197 if (json
&& json_paths
) {
11198 json_object_object_add(json_header
, "paths", json_paths
);
11201 json_object_object_add(json
, rdbuf
, json_header
);
11205 /* Display specified route of BGP table. */
11206 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11207 struct bgp_table
*rib
, const char *ip_str
,
11208 afi_t afi
, safi_t safi
,
11209 struct prefix_rd
*prd
, int prefix_check
,
11210 enum bgp_path_type pathtype
, bool use_json
)
11214 struct prefix match
;
11215 struct bgp_dest
*dest
;
11216 struct bgp_dest
*rm
;
11217 struct bgp_table
*table
;
11218 json_object
*json
= NULL
;
11219 json_object
*json_paths
= NULL
;
11221 /* Check IP address argument. */
11222 ret
= str2prefix(ip_str
, &match
);
11224 vty_out(vty
, "address is malformed\n");
11225 return CMD_WARNING
;
11228 match
.family
= afi2family(afi
);
11231 json
= json_object_new_object();
11233 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11234 for (dest
= bgp_table_top(rib
); dest
;
11235 dest
= bgp_route_next(dest
)) {
11236 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11238 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11240 table
= bgp_dest_get_bgp_table_info(dest
);
11244 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11247 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11249 && rm_p
->prefixlen
!= match
.prefixlen
) {
11250 bgp_dest_unlock_node(rm
);
11254 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11255 bgp
, afi
, safi
, json
, pathtype
,
11258 bgp_dest_unlock_node(rm
);
11260 } else if (safi
== SAFI_EVPN
) {
11261 struct bgp_dest
*longest_pfx
;
11262 bool is_exact_pfxlen_match
= false;
11264 for (dest
= bgp_table_top(rib
); dest
;
11265 dest
= bgp_route_next(dest
)) {
11266 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11268 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11270 table
= bgp_dest_get_bgp_table_info(dest
);
11274 longest_pfx
= NULL
;
11275 is_exact_pfxlen_match
= false;
11277 * Search through all the prefixes for a match. The
11278 * pfx's are enumerated in ascending order of pfxlens.
11279 * So, the last pfx match is the longest match. Set
11280 * is_exact_pfxlen_match when we get exact pfxlen match
11282 for (rm
= bgp_table_top(table
); rm
;
11283 rm
= bgp_route_next(rm
)) {
11284 const struct prefix
*rm_p
=
11285 bgp_dest_get_prefix(rm
);
11287 * Get prefixlen of the ip-prefix within type5
11290 if (evpn_type5_prefix_match(rm_p
, &match
)
11294 bgp_evpn_get_type5_prefixlen(
11296 if (type5_pfxlen
== match
.prefixlen
) {
11297 is_exact_pfxlen_match
= true;
11298 bgp_dest_unlock_node(rm
);
11307 if (prefix_check
&& !is_exact_pfxlen_match
)
11311 bgp_dest_lock_node(rm
);
11313 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11314 bgp
, afi
, safi
, json
, pathtype
,
11317 bgp_dest_unlock_node(rm
);
11319 } else if (safi
== SAFI_FLOWSPEC
) {
11321 json_paths
= json_object_new_array();
11323 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11324 &match
, prefix_check
,
11330 json_object_object_add(json
, "paths",
11333 json_object_free(json_paths
);
11336 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
11337 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11339 || dest_p
->prefixlen
== match
.prefixlen
) {
11340 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11341 safi
, json
, pathtype
,
11345 bgp_dest_unlock_node(dest
);
11350 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11351 json
, JSON_C_TO_STRING_PRETTY
|
11352 JSON_C_TO_STRING_NOSLASHESCAPE
));
11353 json_object_free(json
);
11356 vty_out(vty
, "%% Network not in table\n");
11357 return CMD_WARNING
;
11361 return CMD_SUCCESS
;
11364 /* Display specified route of Main RIB */
11365 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11366 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11367 int prefix_check
, enum bgp_path_type pathtype
,
11371 bgp
= bgp_get_default();
11374 vty_out(vty
, "No BGP process is configured\n");
11376 vty_out(vty
, "{}\n");
11377 return CMD_WARNING
;
11381 /* labeled-unicast routes live in the unicast table */
11382 if (safi
== SAFI_LABELED_UNICAST
)
11383 safi
= SAFI_UNICAST
;
11385 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11386 afi
, safi
, prd
, prefix_check
, pathtype
,
11390 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11391 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11392 safi_t safi
, bool uj
)
11394 struct lcommunity
*lcom
;
11399 uint8_t show_flags
= 0;
11403 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11405 b
= buffer_new(1024);
11406 for (i
= 0; i
< argc
; i
++) {
11408 buffer_putc(b
, ' ');
11410 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11412 buffer_putstr(b
, argv
[i
]->arg
);
11416 buffer_putc(b
, '\0');
11418 str
= buffer_getstr(b
);
11421 lcom
= lcommunity_str2com(str
);
11422 XFREE(MTYPE_TMP
, str
);
11424 vty_out(vty
, "%% Large-community malformed\n");
11425 return CMD_WARNING
;
11428 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11429 (exact
? bgp_show_type_lcommunity_exact
11430 : bgp_show_type_lcommunity
),
11433 lcommunity_free(&lcom
);
11437 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11438 const char *lcom
, bool exact
, afi_t afi
,
11439 safi_t safi
, bool uj
)
11441 struct community_list
*list
;
11442 uint8_t show_flags
= 0;
11445 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11448 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11449 LARGE_COMMUNITY_LIST_MASTER
);
11450 if (list
== NULL
) {
11451 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11453 return CMD_WARNING
;
11456 return bgp_show(vty
, bgp
, afi
, safi
,
11457 (exact
? bgp_show_type_lcommunity_list_exact
11458 : bgp_show_type_lcommunity_list
),
11462 DEFUN (show_ip_bgp_large_community_list
,
11463 show_ip_bgp_large_community_list_cmd
,
11464 "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]",
11468 BGP_INSTANCE_HELP_STR
11470 BGP_SAFI_WITH_LABEL_HELP_STR
11471 "Display routes matching the large-community-list\n"
11472 "large-community-list number\n"
11473 "large-community-list name\n"
11474 "Exact match of the large-communities\n"
11477 afi_t afi
= AFI_IP6
;
11478 safi_t safi
= SAFI_UNICAST
;
11480 bool exact_match
= 0;
11481 struct bgp
*bgp
= NULL
;
11482 bool uj
= use_json(argc
, argv
);
11487 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11490 return CMD_WARNING
;
11492 argv_find(argv
, argc
, "large-community-list", &idx
);
11494 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11496 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11499 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11500 exact_match
, afi
, safi
, uj
);
11502 DEFUN (show_ip_bgp_large_community
,
11503 show_ip_bgp_large_community_cmd
,
11504 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11508 BGP_INSTANCE_HELP_STR
11510 BGP_SAFI_WITH_LABEL_HELP_STR
11511 "Display routes matching the large-communities\n"
11512 "List of large-community numbers\n"
11513 "Exact match of the large-communities\n"
11516 afi_t afi
= AFI_IP6
;
11517 safi_t safi
= SAFI_UNICAST
;
11519 bool exact_match
= 0;
11520 struct bgp
*bgp
= NULL
;
11521 bool uj
= use_json(argc
, argv
);
11522 uint8_t show_flags
= 0;
11526 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11529 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11532 return CMD_WARNING
;
11534 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11535 if (argv_find(argv
, argc
, "exact-match", &idx
))
11537 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11538 exact_match
, afi
, safi
, uj
);
11540 return bgp_show(vty
, bgp
, afi
, safi
,
11541 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
11544 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11545 safi_t safi
, struct json_object
*json_array
);
11546 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11547 safi_t safi
, struct json_object
*json
);
11550 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11551 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11552 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11553 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11555 bool uj
= use_json(argc
, argv
);
11556 struct bgp
*bgp
= NULL
;
11557 safi_t safi
= SAFI_UNICAST
;
11558 afi_t afi
= AFI_IP6
;
11560 struct json_object
*json_all
= NULL
;
11561 struct json_object
*json_afi_safi
= NULL
;
11563 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11566 return CMD_WARNING
;
11569 json_all
= json_object_new_object();
11571 FOREACH_AFI_SAFI (afi
, safi
) {
11573 * So limit output to those afi/safi pairs that
11574 * actually have something interesting in them
11576 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11581 json_afi_safi
= json_object_new_array();
11582 json_object_object_add(
11584 get_afi_safi_str(afi
, safi
, true),
11587 json_afi_safi
= NULL
;
11590 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11595 json_object_to_json_string_ext(
11596 json_all
, JSON_C_TO_STRING_PRETTY
));
11597 json_object_free(json_all
);
11600 return CMD_SUCCESS
;
11603 /* BGP route print out function without JSON */
11604 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11605 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11606 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11610 BGP_INSTANCE_HELP_STR
11613 "BGP RIB advertisement statistics\n"
11616 afi_t afi
= AFI_IP6
;
11617 safi_t safi
= SAFI_UNICAST
;
11618 struct bgp
*bgp
= NULL
;
11620 bool uj
= use_json(argc
, argv
);
11621 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11623 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11626 return CMD_WARNING
;
11629 json_afi_safi
= json_object_new_array();
11631 json_afi_safi
= NULL
;
11633 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11636 json
= json_object_new_object();
11637 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11639 vty_out(vty
, "%s", json_object_to_json_string_ext(
11640 json
, JSON_C_TO_STRING_PRETTY
));
11641 json_object_free(json
);
11646 /* BGP route print out function without JSON */
11647 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11648 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11649 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11651 statistics [json]",
11652 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11653 BGP_SAFI_WITH_LABEL_HELP_STR
11654 "BGP RIB advertisement statistics\n" JSON_STR
)
11656 afi_t afi
= AFI_IP6
;
11657 safi_t safi
= SAFI_UNICAST
;
11658 struct bgp
*bgp
= NULL
;
11660 bool uj
= use_json(argc
, argv
);
11661 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11663 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11666 return CMD_WARNING
;
11669 json_afi_safi
= json_object_new_array();
11671 json_afi_safi
= NULL
;
11673 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11676 json
= json_object_new_object();
11677 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11680 json_object_to_json_string_ext(
11681 json
, JSON_C_TO_STRING_PRETTY
));
11682 json_object_free(json
);
11687 /* BGP route print out function without JSON */
11688 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11689 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11690 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11692 <[all$all] dampening <parameters>\
11696 |community-list <(1-500)|WORD> [exact-match]\
11697 |A.B.C.D/M longer-prefixes\
11698 |X:X::X:X/M longer-prefixes\
11700 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11701 BGP_SAFI_WITH_LABEL_HELP_STR
11702 "Display the entries for all address families\n"
11703 "Display detailed information about dampening\n"
11704 "Display detail of configured dampening parameters\n"
11705 "Display routes matching the route-map\n"
11706 "A route-map to match on\n"
11707 "Display routes conforming to the prefix-list\n"
11708 "Prefix-list name\n"
11709 "Display routes conforming to the filter-list\n"
11710 "Regular expression access list name\n"
11711 "Display routes matching the community-list\n"
11712 "community-list number\n"
11713 "community-list name\n"
11714 "Exact match of the communities\n"
11716 "Display route and more specific routes\n"
11718 "Display route and more specific routes\n")
11720 afi_t afi
= AFI_IP6
;
11721 safi_t safi
= SAFI_UNICAST
;
11722 int exact_match
= 0;
11723 struct bgp
*bgp
= NULL
;
11725 uint8_t show_flags
= 0;
11727 /* [<ipv4|ipv6> [all]] */
11729 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11730 if (argv_find(argv
, argc
, "ipv4", &idx
))
11731 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11733 if (argv_find(argv
, argc
, "ipv6", &idx
))
11734 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11737 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11740 return CMD_WARNING
;
11742 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11743 if (argv_find(argv
, argc
, "parameters", &idx
))
11744 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11748 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11749 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11750 safi
, bgp_show_type_prefix_list
);
11752 if (argv_find(argv
, argc
, "filter-list", &idx
))
11753 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11754 safi
, bgp_show_type_filter_list
);
11756 if (argv_find(argv
, argc
, "route-map", &idx
))
11757 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11758 safi
, bgp_show_type_route_map
);
11760 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11761 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11762 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11764 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11765 exact_match
, afi
, safi
);
11767 /* prefix-longer */
11768 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11769 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11770 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11772 bgp_show_type_prefix_longer
);
11774 return CMD_WARNING
;
11777 /* BGP route print out function with JSON */
11778 DEFPY (show_ip_bgp_json
,
11779 show_ip_bgp_json_cmd
,
11780 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11783 |dampening <flap-statistics|dampened-paths>\
11784 |community [AA:NN|local-AS|no-advertise|no-export\
11785 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11786 |accept-own|accept-own-nexthop|route-filter-v6\
11787 |route-filter-v4|route-filter-translated-v6\
11788 |route-filter-translated-v4] [exact-match]\
11789 ] [json$uj | wide$wide]",
11793 BGP_INSTANCE_HELP_STR
11795 BGP_SAFI_WITH_LABEL_HELP_STR
11796 "Display the entries for all address families\n"
11797 "Display only routes with non-natural netmasks\n"
11798 "Display detailed information about dampening\n"
11799 "Display flap statistics of routes\n"
11800 "Display paths suppressed due to dampening\n"
11801 "Display routes matching the communities\n"
11803 "Do not send outside local AS (well-known community)\n"
11804 "Do not advertise to any peer (well-known community)\n"
11805 "Do not export to next AS (well-known community)\n"
11806 "Graceful shutdown (well-known community)\n"
11807 "Do not export to any peer (well-known community)\n"
11808 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11809 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11810 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11811 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11812 "Should accept VPN route with local nexthop (well-known community)\n"
11813 "RT VPNv6 route filtering (well-known community)\n"
11814 "RT VPNv4 route filtering (well-known community)\n"
11815 "RT translated VPNv6 route filtering (well-known community)\n"
11816 "RT translated VPNv4 route filtering (well-known community)\n"
11817 "Exact match of the communities\n"
11819 "Increase table width for longer prefixes\n")
11821 afi_t afi
= AFI_IP6
;
11822 safi_t safi
= SAFI_UNICAST
;
11823 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11824 struct bgp
*bgp
= NULL
;
11826 int exact_match
= 0;
11827 char *community
= NULL
;
11829 uint8_t show_flags
= 0;
11834 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11837 /* [<ipv4|ipv6> [all]] */
11839 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11841 if (argv_find(argv
, argc
, "ipv4", &idx
))
11842 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11844 if (argv_find(argv
, argc
, "ipv6", &idx
))
11845 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11849 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11851 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11854 return CMD_WARNING
;
11856 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11857 sh_type
= bgp_show_type_cidr_only
;
11859 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11860 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11861 sh_type
= bgp_show_type_dampend_paths
;
11862 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11863 sh_type
= bgp_show_type_flap_statistics
;
11866 if (argv_find(argv
, argc
, "community", &idx
)) {
11867 char *maybecomm
= NULL
;
11869 if (idx
+ 1 < argc
) {
11870 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11871 maybecomm
= argv
[idx
+ 1]->arg
;
11873 maybecomm
= argv
[idx
+ 1]->text
;
11876 if (maybecomm
&& !strmatch(maybecomm
, "json")
11877 && !strmatch(maybecomm
, "exact-match"))
11878 community
= maybecomm
;
11880 if (argv_find(argv
, argc
, "exact-match", &idx
))
11884 sh_type
= bgp_show_type_community_all
;
11888 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11890 return bgp_show_community(vty
, bgp
, community
,
11891 exact_match
, afi
, safi
,
11894 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11897 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11901 vty_out(vty
, "{\n");
11903 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11904 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11905 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11908 FOREACH_SAFI (safi
) {
11909 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11916 vty_out(vty
, ",\n");
11917 vty_out(vty
, "\"%s\":{\n",
11918 get_afi_safi_str(afi
, safi
,
11922 "\nFor address family: %s\n",
11923 get_afi_safi_str(afi
, safi
,
11927 bgp_show_community(vty
, bgp
, community
,
11931 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11934 vty_out(vty
, "}\n");
11937 /* show <ip> bgp all: for each AFI and SAFI*/
11938 FOREACH_AFI_SAFI (afi
, safi
) {
11939 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11946 vty_out(vty
, ",\n");
11948 vty_out(vty
, "\"%s\":{\n",
11949 get_afi_safi_str(afi
, safi
,
11953 "\nFor address family: %s\n",
11954 get_afi_safi_str(afi
, safi
,
11958 bgp_show_community(vty
, bgp
, community
,
11962 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11965 vty_out(vty
, "}\n");
11969 vty_out(vty
, "}\n");
11971 return CMD_SUCCESS
;
11974 DEFUN (show_ip_bgp_route
,
11975 show_ip_bgp_route_cmd
,
11976 "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]",
11980 BGP_INSTANCE_HELP_STR
11982 BGP_SAFI_WITH_LABEL_HELP_STR
11983 "Network in the BGP routing table to display\n"
11985 "Network in the BGP routing table to display\n"
11987 "Display only the bestpath\n"
11988 "Display only multipaths\n"
11991 int prefix_check
= 0;
11993 afi_t afi
= AFI_IP6
;
11994 safi_t safi
= SAFI_UNICAST
;
11995 char *prefix
= NULL
;
11996 struct bgp
*bgp
= NULL
;
11997 enum bgp_path_type path_type
;
11998 bool uj
= use_json(argc
, argv
);
12002 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12005 return CMD_WARNING
;
12009 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12010 return CMD_WARNING
;
12013 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12014 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12015 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12017 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12018 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12021 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12022 && afi
!= AFI_IP6
) {
12024 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12025 return CMD_WARNING
;
12027 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12028 && afi
!= AFI_IP
) {
12030 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12031 return CMD_WARNING
;
12034 prefix
= argv
[idx
]->arg
;
12036 /* [<bestpath|multipath>] */
12037 if (argv_find(argv
, argc
, "bestpath", &idx
))
12038 path_type
= BGP_PATH_SHOW_BESTPATH
;
12039 else if (argv_find(argv
, argc
, "multipath", &idx
))
12040 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12042 path_type
= BGP_PATH_SHOW_ALL
;
12044 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12048 DEFUN (show_ip_bgp_regexp
,
12049 show_ip_bgp_regexp_cmd
,
12050 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12054 BGP_INSTANCE_HELP_STR
12056 BGP_SAFI_WITH_LABEL_HELP_STR
12057 "Display routes matching the AS path regular expression\n"
12058 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12061 afi_t afi
= AFI_IP6
;
12062 safi_t safi
= SAFI_UNICAST
;
12063 struct bgp
*bgp
= NULL
;
12064 bool uj
= use_json(argc
, argv
);
12065 char *regstr
= NULL
;
12068 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12071 return CMD_WARNING
;
12073 // get index of regex
12074 if (argv_find(argv
, argc
, "REGEX", &idx
))
12075 regstr
= argv
[idx
]->arg
;
12078 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12079 bgp_show_type_regexp
, uj
);
12082 DEFPY (show_ip_bgp_instance_all
,
12083 show_ip_bgp_instance_all_cmd
,
12084 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12088 BGP_INSTANCE_ALL_HELP_STR
12090 BGP_SAFI_WITH_LABEL_HELP_STR
12092 "Increase table width for longer prefixes\n")
12094 afi_t afi
= AFI_IP
;
12095 safi_t safi
= SAFI_UNICAST
;
12096 struct bgp
*bgp
= NULL
;
12098 uint8_t show_flags
= 0;
12102 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12106 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12108 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12111 return CMD_WARNING
;
12113 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12114 return CMD_SUCCESS
;
12117 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12118 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12123 uint8_t show_flags
= 0;
12126 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12128 if (!config_bgp_aspath_validate(regstr
)) {
12129 vty_out(vty
, "Invalid character in REGEX %s\n",
12131 return CMD_WARNING_CONFIG_FAILED
;
12134 regex
= bgp_regcomp(regstr
);
12136 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12137 return CMD_WARNING
;
12140 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
12141 bgp_regex_free(regex
);
12145 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12146 const char *prefix_list_str
, afi_t afi
,
12147 safi_t safi
, enum bgp_show_type type
)
12149 struct prefix_list
*plist
;
12150 uint8_t show_flags
= 0;
12152 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12153 if (plist
== NULL
) {
12154 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12156 return CMD_WARNING
;
12159 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
12162 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12163 const char *filter
, afi_t afi
, safi_t safi
,
12164 enum bgp_show_type type
)
12166 struct as_list
*as_list
;
12167 uint8_t show_flags
= 0;
12169 as_list
= as_list_lookup(filter
);
12170 if (as_list
== NULL
) {
12171 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12173 return CMD_WARNING
;
12176 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
12179 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12180 const char *rmap_str
, afi_t afi
, safi_t safi
,
12181 enum bgp_show_type type
)
12183 struct route_map
*rmap
;
12184 uint8_t show_flags
= 0;
12186 rmap
= route_map_lookup_by_name(rmap_str
);
12188 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12189 return CMD_WARNING
;
12192 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
12195 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12196 const char *comstr
, int exact
, afi_t afi
,
12197 safi_t safi
, uint8_t show_flags
)
12199 struct community
*com
;
12202 com
= community_str2com(comstr
);
12204 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12205 return CMD_WARNING
;
12208 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12209 (exact
? bgp_show_type_community_exact
12210 : bgp_show_type_community
),
12212 community_free(&com
);
12217 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12218 const char *com
, int exact
, afi_t afi
,
12221 struct community_list
*list
;
12222 uint8_t show_flags
= 0;
12224 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12225 if (list
== NULL
) {
12226 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12227 return CMD_WARNING
;
12230 return bgp_show(vty
, bgp
, afi
, safi
,
12231 (exact
? bgp_show_type_community_list_exact
12232 : bgp_show_type_community_list
),
12236 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12237 const char *prefix
, afi_t afi
, safi_t safi
,
12238 enum bgp_show_type type
)
12242 uint8_t show_flags
= 0;
12246 ret
= str2prefix(prefix
, p
);
12248 vty_out(vty
, "%% Malformed Prefix\n");
12249 return CMD_WARNING
;
12252 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
12258 BGP_STATS_MAXBITLEN
= 0,
12260 BGP_STATS_PREFIXES
,
12262 BGP_STATS_UNAGGREGATEABLE
,
12263 BGP_STATS_MAX_AGGREGATEABLE
,
12264 BGP_STATS_AGGREGATES
,
12266 BGP_STATS_ASPATH_COUNT
,
12267 BGP_STATS_ASPATH_MAXHOPS
,
12268 BGP_STATS_ASPATH_TOTHOPS
,
12269 BGP_STATS_ASPATH_MAXSIZE
,
12270 BGP_STATS_ASPATH_TOTSIZE
,
12271 BGP_STATS_ASN_HIGHEST
,
12275 #define TABLE_STATS_IDX_VTY 0
12276 #define TABLE_STATS_IDX_JSON 1
12278 static const char *table_stats_strs
[][2] = {
12279 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12280 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12281 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12282 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12283 "unaggregateablePrefixes"},
12284 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12285 "maximumAggregateablePrefixes"},
12286 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12287 "bgpAggregateAdvertisements"},
12288 [BGP_STATS_SPACE
] = {"Address space advertised",
12289 "addressSpaceAdvertised"},
12290 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12291 "advertisementsWithPaths"},
12292 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12294 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12296 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12297 "averageAsPathLengthHops"},
12298 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12299 "averageAsPathSizeBytes"},
12300 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12301 [BGP_STATS_MAX
] = {NULL
, NULL
}
12304 struct bgp_table_stats
{
12305 struct bgp_table
*table
;
12306 unsigned long long counts
[BGP_STATS_MAX
];
12307 double total_space
;
12310 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12311 struct bgp_table_stats
*ts
, unsigned int space
)
12313 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12314 struct bgp_path_info
*pi
;
12315 const struct prefix
*rn_p
;
12317 if (!bgp_dest_has_bgp_path_info_data(dest
))
12320 rn_p
= bgp_dest_get_prefix(dest
);
12321 ts
->counts
[BGP_STATS_PREFIXES
]++;
12322 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12324 /* check if the prefix is included by any other announcements */
12325 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12326 pdest
= bgp_dest_parent_nolock(pdest
);
12328 if (pdest
== NULL
|| pdest
== top
) {
12329 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12330 /* announced address space */
12332 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12333 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12334 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12337 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12338 ts
->counts
[BGP_STATS_RIB
]++;
12340 if (CHECK_FLAG(pi
->attr
->flag
,
12341 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12342 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12344 /* as-path stats */
12345 if (pi
->attr
->aspath
) {
12346 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12347 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12348 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12350 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12352 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12353 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12355 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12356 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12358 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12359 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12360 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12361 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12366 static int bgp_table_stats_walker(struct thread
*t
)
12368 struct bgp_dest
*dest
, *ndest
;
12369 struct bgp_dest
*top
;
12370 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12371 unsigned int space
= 0;
12373 if (!(top
= bgp_table_top(ts
->table
)))
12376 switch (ts
->table
->afi
) {
12378 space
= IPV4_MAX_BITLEN
;
12381 space
= IPV6_MAX_BITLEN
;
12387 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12389 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12390 if (ts
->table
->safi
== SAFI_MPLS_VPN
12391 || ts
->table
->safi
== SAFI_ENCAP
12392 || ts
->table
->safi
== SAFI_EVPN
) {
12393 struct bgp_table
*table
;
12395 table
= bgp_dest_get_bgp_table_info(dest
);
12399 top
= bgp_table_top(table
);
12400 for (ndest
= bgp_table_top(table
); ndest
;
12401 ndest
= bgp_route_next(ndest
))
12402 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12404 bgp_table_stats_rn(dest
, top
, ts
, space
);
12411 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12412 struct json_object
*json_array
)
12414 struct listnode
*node
, *nnode
;
12417 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12418 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12421 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12422 safi_t safi
, struct json_object
*json_array
)
12424 struct bgp_table_stats ts
;
12426 int ret
= CMD_SUCCESS
;
12428 struct json_object
*json
= NULL
;
12431 json
= json_object_new_object();
12433 if (!bgp
->rib
[afi
][safi
]) {
12434 char warning_msg
[50];
12436 snprintf(warning_msg
, sizeof(warning_msg
),
12437 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12441 vty_out(vty
, "%s\n", warning_msg
);
12443 json_object_string_add(json
, "warning", warning_msg
);
12446 goto end_table_stats
;
12450 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12451 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12453 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12455 /* labeled-unicast routes live in the unicast table */
12456 if (safi
== SAFI_LABELED_UNICAST
)
12457 safi
= SAFI_UNICAST
;
12459 memset(&ts
, 0, sizeof(ts
));
12460 ts
.table
= bgp
->rib
[afi
][safi
];
12461 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12463 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12464 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12465 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12469 case BGP_STATS_ASPATH_TOTHOPS
:
12470 case BGP_STATS_ASPATH_TOTSIZE
:
12473 temp_buf
, sizeof(temp_buf
), "%12.2f",
12475 ? (float)ts
.counts
[i
]
12477 [BGP_STATS_ASPATH_COUNT
]
12479 vty_out(vty
, "%-30s: %s",
12480 table_stats_strs
[i
]
12481 [TABLE_STATS_IDX_VTY
],
12484 json_object_double_add(
12486 table_stats_strs
[i
]
12487 [TABLE_STATS_IDX_JSON
],
12489 ? (double)ts
.counts
[i
]
12490 / (double)ts
.counts
12491 [BGP_STATS_ASPATH_COUNT
]
12495 case BGP_STATS_TOTPLEN
:
12498 temp_buf
, sizeof(temp_buf
), "%12.2f",
12500 ? (float)ts
.counts
[i
]
12502 [BGP_STATS_PREFIXES
]
12504 vty_out(vty
, "%-30s: %s",
12505 table_stats_strs
[i
]
12506 [TABLE_STATS_IDX_VTY
],
12509 json_object_double_add(
12511 table_stats_strs
[i
]
12512 [TABLE_STATS_IDX_JSON
],
12514 ? (double)ts
.counts
[i
]
12515 / (double)ts
.counts
12516 [BGP_STATS_PREFIXES
]
12520 case BGP_STATS_SPACE
:
12522 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12524 vty_out(vty
, "%-30s: %s\n",
12525 table_stats_strs
[i
]
12526 [TABLE_STATS_IDX_VTY
],
12529 json_object_double_add(
12531 table_stats_strs
[i
]
12532 [TABLE_STATS_IDX_JSON
],
12533 (double)ts
.total_space
);
12535 if (afi
== AFI_IP6
) {
12537 snprintf(temp_buf
, sizeof(temp_buf
),
12540 * pow(2.0, -128 + 32));
12541 vty_out(vty
, "%30s: %s\n",
12542 "/32 equivalent %s\n",
12545 json_object_double_add(
12546 json
, "/32equivalent",
12547 (double)(ts
.total_space
12552 snprintf(temp_buf
, sizeof(temp_buf
),
12555 * pow(2.0, -128 + 48));
12556 vty_out(vty
, "%30s: %s\n",
12557 "/48 equivalent %s\n",
12560 json_object_double_add(
12561 json
, "/48equivalent",
12562 (double)(ts
.total_space
12568 snprintf(temp_buf
, sizeof(temp_buf
),
12570 ts
.total_space
* 100.
12572 vty_out(vty
, "%30s: %s\n",
12573 "% announced ", temp_buf
);
12575 json_object_double_add(
12576 json
, "%announced",
12577 (double)(ts
.total_space
* 100.
12581 snprintf(temp_buf
, sizeof(temp_buf
),
12584 * pow(2.0, -32 + 8));
12585 vty_out(vty
, "%30s: %s\n",
12586 "/8 equivalent ", temp_buf
);
12588 json_object_double_add(
12589 json
, "/8equivalent",
12590 (double)(ts
.total_space
12591 * pow(2.0, -32 + 8)));
12594 snprintf(temp_buf
, sizeof(temp_buf
),
12597 * pow(2.0, -32 + 24));
12598 vty_out(vty
, "%30s: %s\n",
12599 "/24 equivalent ", temp_buf
);
12601 json_object_double_add(
12602 json
, "/24equivalent",
12603 (double)(ts
.total_space
12604 * pow(2.0, -32 + 24)));
12610 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12612 vty_out(vty
, "%-30s: %s",
12613 table_stats_strs
[i
]
12614 [TABLE_STATS_IDX_VTY
],
12617 json_object_int_add(
12619 table_stats_strs
[i
]
12620 [TABLE_STATS_IDX_JSON
],
12625 vty_out(vty
, "\n");
12629 json_object_array_add(json_array
, json
);
12633 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12634 safi_t safi
, struct json_object
*json_array
)
12637 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12638 return CMD_SUCCESS
;
12641 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12653 PCOUNT_BPATH_SELECTED
,
12654 PCOUNT_PFCNT
, /* the figure we display to users */
12658 static const char *const pcount_strs
[] = {
12659 [PCOUNT_ADJ_IN
] = "Adj-in",
12660 [PCOUNT_DAMPED
] = "Damped",
12661 [PCOUNT_REMOVED
] = "Removed",
12662 [PCOUNT_HISTORY
] = "History",
12663 [PCOUNT_STALE
] = "Stale",
12664 [PCOUNT_VALID
] = "Valid",
12665 [PCOUNT_ALL
] = "All RIB",
12666 [PCOUNT_COUNTED
] = "PfxCt counted",
12667 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12668 [PCOUNT_PFCNT
] = "Useable",
12669 [PCOUNT_MAX
] = NULL
,
12672 struct peer_pcounts
{
12673 unsigned int count
[PCOUNT_MAX
];
12674 const struct peer
*peer
;
12675 const struct bgp_table
*table
;
12679 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12681 const struct bgp_adj_in
*ain
;
12682 const struct bgp_path_info
*pi
;
12683 const struct peer
*peer
= pc
->peer
;
12685 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12686 if (ain
->peer
== peer
)
12687 pc
->count
[PCOUNT_ADJ_IN
]++;
12689 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12691 if (pi
->peer
!= peer
)
12694 pc
->count
[PCOUNT_ALL
]++;
12696 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12697 pc
->count
[PCOUNT_DAMPED
]++;
12698 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12699 pc
->count
[PCOUNT_HISTORY
]++;
12700 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12701 pc
->count
[PCOUNT_REMOVED
]++;
12702 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12703 pc
->count
[PCOUNT_STALE
]++;
12704 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12705 pc
->count
[PCOUNT_VALID
]++;
12706 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12707 pc
->count
[PCOUNT_PFCNT
]++;
12708 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12709 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12711 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12712 pc
->count
[PCOUNT_COUNTED
]++;
12713 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12715 EC_LIB_DEVELOPMENT
,
12716 "Attempting to count but flags say it is unusable");
12718 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12720 EC_LIB_DEVELOPMENT
,
12721 "Not counted but flags say we should");
12726 static int bgp_peer_count_walker(struct thread
*t
)
12728 struct bgp_dest
*rn
, *rm
;
12729 const struct bgp_table
*table
;
12730 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12732 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12733 || pc
->safi
== SAFI_EVPN
) {
12734 /* Special handling for 2-level routing tables. */
12735 for (rn
= bgp_table_top(pc
->table
); rn
;
12736 rn
= bgp_route_next(rn
)) {
12737 table
= bgp_dest_get_bgp_table_info(rn
);
12739 for (rm
= bgp_table_top(table
); rm
;
12740 rm
= bgp_route_next(rm
))
12741 bgp_peer_count_proc(rm
, pc
);
12744 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
12745 bgp_peer_count_proc(rn
, pc
);
12750 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12751 safi_t safi
, bool use_json
)
12753 struct peer_pcounts pcounts
= {.peer
= peer
};
12755 json_object
*json
= NULL
;
12756 json_object
*json_loop
= NULL
;
12759 json
= json_object_new_object();
12760 json_loop
= json_object_new_object();
12763 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
12764 || !peer
->bgp
->rib
[afi
][safi
]) {
12766 json_object_string_add(
12768 "No such neighbor or address family");
12769 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12770 json_object_free(json
);
12771 json_object_free(json_loop
);
12773 vty_out(vty
, "%% No such neighbor or address family\n");
12775 return CMD_WARNING
;
12778 memset(&pcounts
, 0, sizeof(pcounts
));
12779 pcounts
.peer
= peer
;
12780 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
12781 pcounts
.safi
= safi
;
12783 /* in-place call via thread subsystem so as to record execution time
12784 * stats for the thread-walk (i.e. ensure this can't be blamed on
12785 * on just vty_read()).
12787 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
12790 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
12791 json_object_string_add(json
, "multiProtocol",
12792 get_afi_safi_str(afi
, safi
, true));
12793 json_object_int_add(json
, "pfxCounter",
12794 peer
->pcount
[afi
][safi
]);
12796 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12797 json_object_int_add(json_loop
, pcount_strs
[i
],
12800 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12802 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12803 json_object_string_add(json
, "pfxctDriftFor",
12805 json_object_string_add(
12806 json
, "recommended",
12807 "Please report this bug, with the above command output");
12809 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12810 json
, JSON_C_TO_STRING_PRETTY
));
12811 json_object_free(json
);
12815 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12816 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12817 peer
->hostname
, peer
->host
,
12818 get_afi_safi_str(afi
, safi
, false));
12820 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12821 get_afi_safi_str(afi
, safi
, false));
12824 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12825 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12827 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12828 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12831 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12832 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12834 "Please report this bug, with the above command output\n");
12838 return CMD_SUCCESS
;
12841 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12842 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12843 "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]",
12847 BGP_INSTANCE_HELP_STR
12850 "Detailed information on TCP and BGP neighbor connections\n"
12851 "Neighbor to display information about\n"
12852 "Neighbor to display information about\n"
12853 "Neighbor on BGP configured interface\n"
12854 "Display detailed prefix count information\n"
12857 afi_t afi
= AFI_IP6
;
12858 safi_t safi
= SAFI_UNICAST
;
12861 struct bgp
*bgp
= NULL
;
12862 bool uj
= use_json(argc
, argv
);
12867 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12870 return CMD_WARNING
;
12872 argv_find(argv
, argc
, "neighbors", &idx
);
12873 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12875 return CMD_WARNING
;
12877 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12880 #ifdef KEEP_OLD_VPN_COMMANDS
12881 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12882 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12883 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12888 "Display information about all VPNv4 NLRIs\n"
12889 "Detailed information on TCP and BGP neighbor connections\n"
12890 "Neighbor to display information about\n"
12891 "Neighbor to display information about\n"
12892 "Neighbor on BGP configured interface\n"
12893 "Display detailed prefix count information\n"
12898 bool uj
= use_json(argc
, argv
);
12900 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12902 return CMD_WARNING
;
12904 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12907 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12908 show_ip_bgp_vpn_all_route_prefix_cmd
,
12909 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12914 "Display information about all VPNv4 NLRIs\n"
12915 "Network in the BGP routing table to display\n"
12916 "Network in the BGP routing table to display\n"
12920 char *network
= NULL
;
12921 struct bgp
*bgp
= bgp_get_default();
12923 vty_out(vty
, "Can't find default instance\n");
12924 return CMD_WARNING
;
12927 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12928 network
= argv
[idx
]->arg
;
12929 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12930 network
= argv
[idx
]->arg
;
12932 vty_out(vty
, "Unable to figure out Network\n");
12933 return CMD_WARNING
;
12936 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12937 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12939 #endif /* KEEP_OLD_VPN_COMMANDS */
12941 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12942 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12943 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12948 "Network in the BGP routing table to display\n"
12949 "Network in the BGP routing table to display\n"
12950 "Network in the BGP routing table to display\n"
12951 "Network in the BGP routing table to display\n"
12955 char *network
= NULL
;
12956 int prefix_check
= 0;
12958 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12959 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12960 network
= argv
[idx
]->arg
;
12961 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12962 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12963 network
= argv
[idx
]->arg
;
12966 vty_out(vty
, "Unable to figure out Network\n");
12967 return CMD_WARNING
;
12969 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12970 prefix_check
, BGP_PATH_SHOW_ALL
,
12971 use_json(argc
, argv
));
12974 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12975 struct bgp_table
*table
, int *header1
,
12976 int *header2
, json_object
*json
,
12977 json_object
*json_scode
,
12978 json_object
*json_ocode
, bool wide
)
12980 uint64_t version
= table
? table
->version
: 0;
12981 char buf
[BUFSIZ
] = {0};
12985 json_object_int_add(json
, "bgpTableVersion", version
);
12986 json_object_string_add(json
, "bgpLocalRouterId",
12988 &bgp
->router_id
, buf
,
12990 json_object_int_add(json
, "defaultLocPrf",
12991 bgp
->default_local_pref
);
12992 json_object_int_add(json
, "localAS", bgp
->as
);
12993 json_object_object_add(json
, "bgpStatusCodes",
12995 json_object_object_add(json
, "bgpOriginCodes",
12999 "BGP table version is %" PRIu64
13000 ", local router ID is %pI4, vrf id ",
13001 version
, &bgp
->router_id
);
13002 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13003 vty_out(vty
, "%s", VRFID_NONE_STR
);
13005 vty_out(vty
, "%u", bgp
->vrf_id
);
13006 vty_out(vty
, "\n");
13007 vty_out(vty
, "Default local pref %u, ",
13008 bgp
->default_local_pref
);
13009 vty_out(vty
, "local AS %u\n", bgp
->as
);
13010 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13011 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13012 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13018 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13019 : BGP_SHOW_HEADER
));
13025 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13026 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13027 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13028 json_object
*json_scode
, json_object
*json_ocode
,
13029 uint8_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13030 unsigned long *output_count
, unsigned long *filtered_count
)
13032 struct bgp_adj_in
*ain
;
13033 struct bgp_adj_out
*adj
;
13034 struct bgp_dest
*dest
;
13038 struct update_subgroup
*subgrp
;
13039 struct peer_af
*paf
;
13040 bool route_filtered
;
13041 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13042 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13043 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13044 || (safi
== SAFI_EVPN
))
13052 json_object_string_add(json
, "alert", "no BGP");
13053 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13054 json_object_free(json
);
13056 vty_out(vty
, "%% No bgp\n");
13060 subgrp
= peer_subgroup(peer
, afi
, safi
);
13062 if (type
== bgp_show_adj_route_advertised
&& subgrp
13063 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13064 char buf
[BUFSIZ
] = {0};
13067 json_object_int_add(json
, "bgpTableVersion",
13069 json_object_string_add(json
, "bgpLocalRouterId",
13071 &bgp
->router_id
, buf
,
13073 json_object_int_add(json
, "defaultLocPrf",
13074 bgp
->default_local_pref
);
13075 json_object_int_add(json
, "localAS", bgp
->as
);
13076 json_object_object_add(json
, "bgpStatusCodes",
13078 json_object_object_add(json
, "bgpOriginCodes",
13080 json_object_string_add(
13081 json
, "bgpOriginatingDefaultNetwork",
13082 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13085 "BGP table version is %" PRIu64
13086 ", local router ID is %pI4, vrf id ",
13087 table
->version
, &bgp
->router_id
);
13088 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13089 vty_out(vty
, "%s", VRFID_NONE_STR
);
13091 vty_out(vty
, "%u", bgp
->vrf_id
);
13092 vty_out(vty
, "\n");
13093 vty_out(vty
, "Default local pref %u, ",
13094 bgp
->default_local_pref
);
13095 vty_out(vty
, "local AS %u\n", bgp
->as
);
13096 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13097 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13098 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13100 vty_out(vty
, "Originating default network %s\n\n",
13101 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13106 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13107 if (type
== bgp_show_adj_route_received
13108 || type
== bgp_show_adj_route_filtered
) {
13109 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13110 if (ain
->peer
!= peer
)
13113 show_adj_route_header(vty
, bgp
, table
, header1
,
13114 header2
, json
, json_scode
,
13117 if ((safi
== SAFI_MPLS_VPN
)
13118 || (safi
== SAFI_ENCAP
)
13119 || (safi
== SAFI_EVPN
)) {
13121 json_object_string_add(
13122 json_ar
, "rd", rd_str
);
13123 else if (show_rd
&& rd_str
) {
13125 "Route Distinguisher: %s\n",
13132 route_filtered
= false;
13134 /* Filter prefix using distribute list,
13135 * filter list or prefix list
13137 const struct prefix
*rn_p
=
13138 bgp_dest_get_prefix(dest
);
13139 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13142 route_filtered
= true;
13144 /* Filter prefix using route-map */
13145 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13146 safi
, rmap_name
, NULL
,
13149 if (type
== bgp_show_adj_route_filtered
&&
13150 !route_filtered
&& ret
!= RMAP_DENY
) {
13151 bgp_attr_undup(&attr
, ain
->attr
);
13155 if (type
== bgp_show_adj_route_received
13156 && (route_filtered
|| ret
== RMAP_DENY
))
13157 (*filtered_count
)++;
13159 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
13160 use_json
, json_ar
, wide
);
13161 bgp_attr_undup(&attr
, ain
->attr
);
13164 } else if (type
== bgp_show_adj_route_advertised
) {
13165 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13166 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13167 if (paf
->peer
!= peer
|| !adj
->attr
)
13170 show_adj_route_header(vty
, bgp
, table
,
13175 const struct prefix
*rn_p
=
13176 bgp_dest_get_prefix(dest
);
13179 ret
= bgp_output_modifier(
13180 peer
, rn_p
, &attr
, afi
, safi
,
13183 if (ret
!= RMAP_DENY
) {
13184 if ((safi
== SAFI_MPLS_VPN
)
13185 || (safi
== SAFI_ENCAP
)
13186 || (safi
== SAFI_EVPN
)) {
13188 json_object_string_add(
13195 "Route Distinguisher: %s\n",
13201 vty
, rn_p
, &attr
, safi
,
13206 (*filtered_count
)++;
13209 bgp_attr_undup(&attr
, adj
->attr
);
13211 } else if (type
== bgp_show_adj_route_bestpath
) {
13212 struct bgp_path_info
*pi
;
13214 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13215 json
, json_scode
, json_ocode
,
13218 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13220 if (pi
->peer
!= peer
)
13223 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13226 route_vty_out_tmp(vty
,
13227 bgp_dest_get_prefix(dest
),
13228 pi
->attr
, safi
, use_json
,
13236 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13237 safi_t safi
, enum bgp_show_adj_route_type type
,
13238 const char *rmap_name
, uint8_t show_flags
)
13241 struct bgp_table
*table
;
13242 json_object
*json
= NULL
;
13243 json_object
*json_scode
= NULL
;
13244 json_object
*json_ocode
= NULL
;
13245 json_object
*json_ar
= NULL
;
13246 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13248 /* Init BGP headers here so they're only displayed once
13249 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13255 * Initialize variables for each RD
13256 * All prefixes under an RD is aggregated within "json_routes"
13258 char rd_str
[BUFSIZ
] = {0};
13259 json_object
*json_routes
= NULL
;
13262 /* For 2-tier tables, prefix counts need to be
13263 * maintained across multiple runs of show_adj_route()
13265 unsigned long output_count_per_rd
;
13266 unsigned long filtered_count_per_rd
;
13267 unsigned long output_count
= 0;
13268 unsigned long filtered_count
= 0;
13271 json
= json_object_new_object();
13272 json_ar
= json_object_new_object();
13273 json_scode
= json_object_new_object();
13274 json_ocode
= json_object_new_object();
13276 json_object_string_add(json_scode
, "suppressed", "s");
13277 json_object_string_add(json_scode
, "damped", "d");
13278 json_object_string_add(json_scode
, "history", "h");
13279 json_object_string_add(json_scode
, "valid", "*");
13280 json_object_string_add(json_scode
, "best", ">");
13281 json_object_string_add(json_scode
, "multipath", "=");
13282 json_object_string_add(json_scode
, "internal", "i");
13283 json_object_string_add(json_scode
, "ribFailure", "r");
13284 json_object_string_add(json_scode
, "stale", "S");
13285 json_object_string_add(json_scode
, "removed", "R");
13287 json_object_string_add(json_ocode
, "igp", "i");
13288 json_object_string_add(json_ocode
, "egp", "e");
13289 json_object_string_add(json_ocode
, "incomplete", "?");
13292 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13294 json_object_string_add(
13296 "No such neighbor or address family");
13297 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13298 json_object_free(json
);
13300 vty_out(vty
, "%% No such neighbor or address family\n");
13302 return CMD_WARNING
;
13305 if ((type
== bgp_show_adj_route_received
13306 || type
== bgp_show_adj_route_filtered
)
13307 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13308 PEER_FLAG_SOFT_RECONFIG
)) {
13310 json_object_string_add(
13312 "Inbound soft reconfiguration not enabled");
13313 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13314 json_object_free(json
);
13317 "%% Inbound soft reconfiguration not enabled\n");
13319 return CMD_WARNING
;
13324 /* labeled-unicast routes live in the unicast table */
13325 if (safi
== SAFI_LABELED_UNICAST
)
13326 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13328 table
= bgp
->rib
[afi
][safi
];
13330 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13331 || (safi
== SAFI_EVPN
)) {
13333 struct bgp_dest
*dest
;
13335 for (dest
= bgp_table_top(table
); dest
;
13336 dest
= bgp_route_next(dest
)) {
13337 table
= bgp_dest_get_bgp_table_info(dest
);
13341 output_count_per_rd
= 0;
13342 filtered_count_per_rd
= 0;
13345 json_routes
= json_object_new_object();
13347 const struct prefix_rd
*prd
;
13348 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13351 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13353 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13354 rmap_name
, json
, json_routes
, json_scode
,
13355 json_ocode
, show_flags
, &header1
,
13356 &header2
, rd_str
, &output_count_per_rd
,
13357 &filtered_count_per_rd
);
13359 /* Don't include an empty RD in the output! */
13360 if (json_routes
&& (output_count_per_rd
> 0))
13361 json_object_object_add(json_ar
, rd_str
,
13364 output_count
+= output_count_per_rd
;
13365 filtered_count
+= filtered_count_per_rd
;
13368 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13369 json
, json_ar
, json_scode
, json_ocode
,
13370 show_flags
, &header1
, &header2
, rd_str
,
13371 &output_count
, &filtered_count
);
13374 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13375 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13376 json_object_int_add(json
, "filteredPrefixCounter",
13379 vty_out(vty
, "%s\n",
13380 json_object_to_json_string_ext(
13381 json
, JSON_C_TO_STRING_PRETTY
));
13383 if (!output_count
&& !filtered_count
) {
13384 json_object_free(json_scode
);
13385 json_object_free(json_ocode
);
13389 json_object_free(json
);
13391 } else if (output_count
> 0) {
13392 if (filtered_count
> 0)
13394 "\nTotal number of prefixes %ld (%ld filtered)\n",
13395 output_count
, filtered_count
);
13397 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13401 return CMD_SUCCESS
;
13404 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13405 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13406 "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]",
13410 BGP_INSTANCE_HELP_STR
13412 BGP_SAFI_WITH_LABEL_HELP_STR
13413 "Detailed information on TCP and BGP neighbor connections\n"
13414 "Neighbor to display information about\n"
13415 "Neighbor to display information about\n"
13416 "Neighbor on BGP configured interface\n"
13417 "Display the routes selected by best path\n"
13419 "Increase table width for longer prefixes\n")
13421 afi_t afi
= AFI_IP6
;
13422 safi_t safi
= SAFI_UNICAST
;
13423 char *rmap_name
= NULL
;
13424 char *peerstr
= NULL
;
13425 struct bgp
*bgp
= NULL
;
13427 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13429 uint8_t show_flags
= 0;
13432 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13435 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13437 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13441 return CMD_WARNING
;
13443 argv_find(argv
, argc
, "neighbors", &idx
);
13444 peerstr
= argv
[++idx
]->arg
;
13446 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13448 return CMD_WARNING
;
13450 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13454 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13455 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13456 "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]",
13460 BGP_INSTANCE_HELP_STR
13462 BGP_SAFI_WITH_LABEL_HELP_STR
13463 "Display the entries for all address families\n"
13464 "Detailed information on TCP and BGP neighbor connections\n"
13465 "Neighbor to display information about\n"
13466 "Neighbor to display information about\n"
13467 "Neighbor on BGP configured interface\n"
13468 "Display the routes advertised to a BGP neighbor\n"
13469 "Display the received routes from neighbor\n"
13470 "Display the filtered routes received from neighbor\n"
13471 "Route-map to modify the attributes\n"
13472 "Name of the route map\n"
13474 "Increase table width for longer prefixes\n")
13476 afi_t afi
= AFI_IP6
;
13477 safi_t safi
= SAFI_UNICAST
;
13478 char *rmap_name
= NULL
;
13479 char *peerstr
= NULL
;
13480 struct bgp
*bgp
= NULL
;
13482 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13485 uint8_t show_flags
= 0;
13489 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13493 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13494 if (argv_find(argv
, argc
, "ipv4", &idx
))
13495 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13497 if (argv_find(argv
, argc
, "ipv6", &idx
))
13498 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13502 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13504 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13507 return CMD_WARNING
;
13509 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13510 argv_find(argv
, argc
, "neighbors", &idx
);
13511 peerstr
= argv
[++idx
]->arg
;
13513 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13515 return CMD_WARNING
;
13517 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13518 type
= bgp_show_adj_route_advertised
;
13519 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13520 type
= bgp_show_adj_route_received
;
13521 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13522 type
= bgp_show_adj_route_filtered
;
13524 if (argv_find(argv
, argc
, "route-map", &idx
))
13525 rmap_name
= argv
[++idx
]->arg
;
13528 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13531 vty_out(vty
, "{\n");
13533 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13534 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13535 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13537 FOREACH_SAFI (safi
) {
13538 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13545 vty_out(vty
, ",\n");
13546 vty_out(vty
, "\"%s\":",
13547 get_afi_safi_str(afi
, safi
, true));
13549 vty_out(vty
, "\nFor address family: %s\n",
13550 get_afi_safi_str(afi
, safi
, false));
13552 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13556 FOREACH_AFI_SAFI (afi
, safi
) {
13557 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13564 vty_out(vty
, ",\n");
13565 vty_out(vty
, "\"%s\":",
13566 get_afi_safi_str(afi
, safi
, true));
13568 vty_out(vty
, "\nFor address family: %s\n",
13569 get_afi_safi_str(afi
, safi
, false));
13571 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13576 vty_out(vty
, "}\n");
13578 return CMD_SUCCESS
;
13581 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13582 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13583 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13589 "Address Family modifier\n"
13590 "Detailed information on TCP and BGP neighbor connections\n"
13591 "Neighbor to display information about\n"
13592 "Neighbor to display information about\n"
13593 "Neighbor on BGP configured interface\n"
13594 "Display information received from a BGP neighbor\n"
13595 "Display the prefixlist filter\n"
13598 afi_t afi
= AFI_IP6
;
13599 safi_t safi
= SAFI_UNICAST
;
13600 char *peerstr
= NULL
;
13603 union sockunion su
;
13609 /* show [ip] bgp */
13610 if (argv_find(argv
, argc
, "ip", &idx
))
13612 /* [<ipv4|ipv6> [unicast]] */
13613 if (argv_find(argv
, argc
, "ipv4", &idx
))
13615 if (argv_find(argv
, argc
, "ipv6", &idx
))
13617 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13618 argv_find(argv
, argc
, "neighbors", &idx
);
13619 peerstr
= argv
[++idx
]->arg
;
13621 bool uj
= use_json(argc
, argv
);
13623 ret
= str2sockunion(peerstr
, &su
);
13625 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13628 vty_out(vty
, "{}\n");
13631 "%% Malformed address or name: %s\n",
13633 return CMD_WARNING
;
13636 peer
= peer_lookup(NULL
, &su
);
13639 vty_out(vty
, "{}\n");
13641 vty_out(vty
, "No peer\n");
13642 return CMD_WARNING
;
13646 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13647 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13650 vty_out(vty
, "Address Family: %s\n",
13651 get_afi_safi_str(afi
, safi
, false));
13652 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13655 vty_out(vty
, "{}\n");
13657 vty_out(vty
, "No functional output\n");
13660 return CMD_SUCCESS
;
13663 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13664 afi_t afi
, safi_t safi
,
13665 enum bgp_show_type type
, bool use_json
)
13667 uint8_t show_flags
= 0;
13670 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13672 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13674 json_object
*json_no
= NULL
;
13675 json_no
= json_object_new_object();
13676 json_object_string_add(
13677 json_no
, "warning",
13678 "No such neighbor or address family");
13679 vty_out(vty
, "%s\n",
13680 json_object_to_json_string(json_no
));
13681 json_object_free(json_no
);
13683 vty_out(vty
, "%% No such neighbor or address family\n");
13684 return CMD_WARNING
;
13687 /* labeled-unicast routes live in the unicast table */
13688 if (safi
== SAFI_LABELED_UNICAST
)
13689 safi
= SAFI_UNICAST
;
13691 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
13694 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13695 show_ip_bgp_flowspec_routes_detailed_cmd
,
13696 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13700 BGP_INSTANCE_HELP_STR
13703 "Detailed information on flowspec entries\n"
13706 afi_t afi
= AFI_IP
;
13707 safi_t safi
= SAFI_UNICAST
;
13708 struct bgp
*bgp
= NULL
;
13710 bool uj
= use_json(argc
, argv
);
13711 uint8_t show_flags
= 0;
13715 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13718 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13721 return CMD_WARNING
;
13723 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13727 DEFUN (show_ip_bgp_neighbor_routes
,
13728 show_ip_bgp_neighbor_routes_cmd
,
13729 "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]",
13733 BGP_INSTANCE_HELP_STR
13735 BGP_SAFI_WITH_LABEL_HELP_STR
13736 "Detailed information on TCP and BGP neighbor connections\n"
13737 "Neighbor to display information about\n"
13738 "Neighbor to display information about\n"
13739 "Neighbor on BGP configured interface\n"
13740 "Display flap statistics of the routes learned from neighbor\n"
13741 "Display the dampened routes received from neighbor\n"
13742 "Display routes learned from neighbor\n"
13745 char *peerstr
= NULL
;
13746 struct bgp
*bgp
= NULL
;
13747 afi_t afi
= AFI_IP6
;
13748 safi_t safi
= SAFI_UNICAST
;
13750 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
13752 bool uj
= use_json(argc
, argv
);
13757 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13760 return CMD_WARNING
;
13762 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13763 argv_find(argv
, argc
, "neighbors", &idx
);
13764 peerstr
= argv
[++idx
]->arg
;
13766 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13768 return CMD_WARNING
;
13770 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
13771 sh_type
= bgp_show_type_flap_neighbor
;
13772 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
13773 sh_type
= bgp_show_type_damp_neighbor
;
13774 else if (argv_find(argv
, argc
, "routes", &idx
))
13775 sh_type
= bgp_show_type_neighbor
;
13777 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
13780 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
13782 struct bgp_distance
{
13783 /* Distance value for the IP source prefix. */
13786 /* Name of the access-list to be matched. */
13790 DEFUN (show_bgp_afi_vpn_rd_route
,
13791 show_bgp_afi_vpn_rd_route_cmd
,
13792 "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]",
13796 "Address Family modifier\n"
13797 "Display information for a route distinguisher\n"
13798 "Route Distinguisher\n"
13799 "Network in the BGP routing table to display\n"
13800 "Network in the BGP routing table to display\n"
13804 struct prefix_rd prd
;
13805 afi_t afi
= AFI_MAX
;
13808 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
13809 vty_out(vty
, "%% Malformed Address Family\n");
13810 return CMD_WARNING
;
13813 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
13815 vty_out(vty
, "%% Malformed Route Distinguisher\n");
13816 return CMD_WARNING
;
13819 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
13820 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
13823 static struct bgp_distance
*bgp_distance_new(void)
13825 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
13828 static void bgp_distance_free(struct bgp_distance
*bdistance
)
13830 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
13833 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
13834 const char *access_list_str
, afi_t afi
, safi_t safi
,
13835 char *errmsg
, size_t errmsg_len
)
13839 struct bgp_dest
*dest
;
13840 struct bgp_distance
*bdistance
;
13842 ret
= str2prefix(ip_str
, &p
);
13844 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13845 return CMD_WARNING_CONFIG_FAILED
;
13848 /* Get BGP distance node. */
13849 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
13850 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13852 bgp_dest_unlock_node(dest
);
13854 bdistance
= bgp_distance_new();
13855 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
13858 /* Set distance value. */
13859 bdistance
->distance
= distance
;
13861 /* Reset access-list configuration. */
13862 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13863 if (access_list_str
)
13864 bdistance
->access_list
=
13865 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
13867 return CMD_SUCCESS
;
13870 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
13871 const char *access_list_str
, afi_t afi
, safi_t safi
,
13872 char *errmsg
, size_t errmsg_len
)
13876 struct bgp_dest
*dest
;
13877 struct bgp_distance
*bdistance
;
13879 ret
= str2prefix(ip_str
, &p
);
13881 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13882 return CMD_WARNING_CONFIG_FAILED
;
13885 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13887 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
13888 return CMD_WARNING_CONFIG_FAILED
;
13891 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13893 if (bdistance
->distance
!= distance
) {
13894 snprintf(errmsg
, errmsg_len
,
13895 "Distance does not match configured\n");
13896 return CMD_WARNING_CONFIG_FAILED
;
13899 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13900 bgp_distance_free(bdistance
);
13902 bgp_dest_set_bgp_path_info(dest
, NULL
);
13903 bgp_dest_unlock_node(dest
);
13904 bgp_dest_unlock_node(dest
);
13906 return CMD_SUCCESS
;
13909 /* Apply BGP information to distance method. */
13910 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13911 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13913 struct bgp_dest
*dest
;
13914 struct prefix q
= {0};
13916 struct bgp_distance
*bdistance
;
13917 struct access_list
*alist
;
13918 struct bgp_static
*bgp_static
;
13923 peer
= pinfo
->peer
;
13925 if (pinfo
->attr
->distance
)
13926 return pinfo
->attr
->distance
;
13928 /* Check source address.
13929 * Note: for aggregate route, peer can have unspec af type.
13931 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
13932 && !sockunion2hostprefix(&peer
->su
, &q
))
13935 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13937 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13938 bgp_dest_unlock_node(dest
);
13940 if (bdistance
->access_list
) {
13941 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13943 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13944 return bdistance
->distance
;
13946 return bdistance
->distance
;
13949 /* Backdoor check. */
13950 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
13952 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13953 bgp_dest_unlock_node(dest
);
13955 if (bgp_static
->backdoor
) {
13956 if (bgp
->distance_local
[afi
][safi
])
13957 return bgp
->distance_local
[afi
][safi
];
13959 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13963 if (peer
->sort
== BGP_PEER_EBGP
) {
13964 if (bgp
->distance_ebgp
[afi
][safi
])
13965 return bgp
->distance_ebgp
[afi
][safi
];
13966 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
13967 } else if (peer
->sort
== BGP_PEER_IBGP
) {
13968 if (bgp
->distance_ibgp
[afi
][safi
])
13969 return bgp
->distance_ibgp
[afi
][safi
];
13970 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13972 if (bgp
->distance_local
[afi
][safi
])
13973 return bgp
->distance_local
[afi
][safi
];
13974 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13978 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13979 * we should tell ZEBRA update the routes for a specific
13980 * AFI/SAFI to reflect changes in RIB.
13982 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
13983 safi_t update_safi
)
13988 FOREACH_AFI_SAFI (afi
, safi
) {
13989 if (!bgp_fibupd_safi(safi
))
13992 if (afi
!= update_afi
&& safi
!= update_safi
)
13995 if (BGP_DEBUG(zebra
, ZEBRA
))
13997 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13998 __func__
, afi
, safi
);
13999 bgp_zebra_announce_table(bgp
, afi
, safi
);
14003 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
14004 "distance bgp (1-255) (1-255) (1-255)",
14005 "Define an administrative distance\n"
14007 "Distance for routes external to the AS\n"
14008 "Distance for routes internal to the AS\n"
14009 "Distance for local routes\n")
14011 int idx_number
= 2;
14012 int idx_number_2
= 3;
14013 int idx_number_3
= 4;
14016 char xpath
[XPATH_MAXLEN
];
14018 afi
= bgp_node_afi(vty
);
14019 safi
= bgp_node_safi(vty
);
14022 xpath
, sizeof(xpath
),
14023 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14024 yang_afi_safi_value2identity(afi
, safi
),
14025 bgp_afi_safi_get_container_str(afi
, safi
));
14026 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
14028 xpath
, sizeof(xpath
),
14029 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14030 yang_afi_safi_value2identity(afi
, safi
),
14031 bgp_afi_safi_get_container_str(afi
, safi
));
14032 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14033 argv
[idx_number_2
]->arg
);
14035 xpath
, sizeof(xpath
),
14036 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14037 yang_afi_safi_value2identity(afi
, safi
),
14038 bgp_afi_safi_get_container_str(afi
, safi
));
14040 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14041 argv
[idx_number_3
]->arg
);
14043 return nb_cli_apply_changes(vty
, NULL
);
14046 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
14047 "no distance bgp [(1-255) (1-255) (1-255)]",
14049 "Define an administrative distance\n"
14051 "Distance for routes external to the AS\n"
14052 "Distance for routes internal to the AS\n"
14053 "Distance for local routes\n")
14057 char xpath
[XPATH_MAXLEN
];
14059 afi
= bgp_node_afi(vty
);
14060 safi
= bgp_node_safi(vty
);
14063 xpath
, sizeof(xpath
),
14064 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14065 yang_afi_safi_value2identity(afi
, safi
),
14066 bgp_afi_safi_get_container_str(afi
, safi
));
14067 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14069 xpath
, sizeof(xpath
),
14070 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14071 yang_afi_safi_value2identity(afi
, safi
),
14072 bgp_afi_safi_get_container_str(afi
, safi
));
14073 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14075 xpath
, sizeof(xpath
),
14076 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14077 yang_afi_safi_value2identity(afi
, safi
),
14078 bgp_afi_safi_get_container_str(afi
, safi
));
14080 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14082 return nb_cli_apply_changes(vty
, NULL
);
14085 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
14086 struct lyd_node
*dnode
,
14087 bool show_defaults
)
14089 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
14091 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14092 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14093 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14095 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14099 DEFPY_YANG(bgp_distance_source
,
14100 bgp_distance_source_cmd
,
14101 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14103 "Define an administrative distance\n"
14105 "IPv4 source prefix\n"
14106 "IPv6 source prefix\n"
14107 "Access list name\n")
14111 char xpath
[XPATH_MAXLEN
];
14113 afi
= bgp_node_afi(vty
);
14114 safi
= bgp_node_safi(vty
);
14117 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14118 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14121 nb_cli_enqueue_change(vty
,
14122 "./access-list-policy-export",
14123 NB_OP_CREATE
, acl
);
14125 nb_cli_enqueue_change(vty
,
14126 "./access-list-policy-export",
14127 NB_OP_DESTROY
, NULL
);
14129 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14133 xpath
, sizeof(xpath
),
14134 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14135 yang_afi_safi_value2identity(afi
, safi
),
14136 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14138 return nb_cli_apply_changes(vty
, xpath
);
14141 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14142 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14144 vty_out(vty
, " distance %d %s %s\n",
14145 yang_dnode_get_uint8(dnode
, "./distance"),
14146 yang_dnode_get_string(dnode
, "./prefix"),
14147 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14148 ? yang_dnode_get_string(dnode
,
14149 "./access-list-policy-export")
14154 bgp_dampening
, bgp_dampening_cmd
,
14155 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14157 "BGP Specific commands\n"
14158 "Enable route-flap dampening\n"
14159 "Half-life time for the penalty\n"
14160 "Value to start reusing a route\n"
14161 "Value to start suppressing a route\n"
14162 "Maximum duration to suppress a stable route\n")
14166 char xpath
[XPATH_MAXLEN
];
14168 afi
= bgp_node_afi(vty
);
14169 safi
= bgp_node_safi(vty
);
14172 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14174 nb_cli_enqueue_change(vty
, "./reach-decay",
14175 NB_OP_MODIFY
, halflife_str
);
14176 nb_cli_enqueue_change(vty
, "./reuse-above",
14177 NB_OP_MODIFY
, reuse_str
);
14178 nb_cli_enqueue_change(vty
, "./suppress-above",
14179 NB_OP_MODIFY
, suppress_str
);
14180 nb_cli_enqueue_change(vty
, "./unreach-decay",
14181 NB_OP_MODIFY
, max_suppress_str
);
14183 nb_cli_enqueue_change(vty
, "./reach-decay",
14184 NB_OP_MODIFY
, halflife_str
);
14187 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14191 xpath
, sizeof(xpath
),
14192 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14193 yang_afi_safi_value2identity(afi
, safi
),
14194 bgp_afi_safi_get_container_str(afi
, safi
));
14196 return nb_cli_apply_changes(vty
, xpath
);
14199 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14200 struct lyd_node
*dnode
,
14201 bool show_defaults
)
14203 if (!yang_dnode_get_bool(dnode
, "./enable"))
14206 int half
= DEFAULT_HALF_LIFE
* 60;
14207 int reuse
= DEFAULT_REUSE
;
14208 int suppress
= DEFAULT_SUPPRESS
;
14211 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14212 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14213 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14214 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14216 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14217 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14218 vty_out(vty
, " bgp dampening\n");
14219 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14220 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14221 vty_out(vty
, " bgp dampening %u\n", half
);
14223 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14227 /* Display specified route of BGP table. */
14228 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14229 const char *ip_str
, afi_t afi
, safi_t safi
,
14230 struct prefix_rd
*prd
, int prefix_check
)
14233 struct prefix match
;
14234 struct bgp_dest
*dest
;
14235 struct bgp_dest
*rm
;
14236 struct bgp_path_info
*pi
;
14237 struct bgp_path_info
*pi_temp
;
14239 struct bgp_table
*table
;
14241 /* BGP structure lookup. */
14243 bgp
= bgp_lookup_by_name(view_name
);
14245 vty_out(vty
, "%% Can't find BGP instance %s\n",
14247 return CMD_WARNING
;
14250 bgp
= bgp_get_default();
14252 vty_out(vty
, "%% No BGP process is configured\n");
14253 return CMD_WARNING
;
14257 /* Check IP address argument. */
14258 ret
= str2prefix(ip_str
, &match
);
14260 vty_out(vty
, "%% address is malformed\n");
14261 return CMD_WARNING
;
14264 match
.family
= afi2family(afi
);
14266 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14267 || (safi
== SAFI_EVPN
)) {
14268 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14269 dest
= bgp_route_next(dest
)) {
14270 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14272 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14274 table
= bgp_dest_get_bgp_table_info(dest
);
14277 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
14280 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14283 || rm_p
->prefixlen
== match
.prefixlen
) {
14284 pi
= bgp_dest_get_bgp_path_info(rm
);
14286 if (pi
->extra
&& pi
->extra
->damp_info
) {
14287 pi_temp
= pi
->next
;
14288 bgp_damp_info_free(
14289 &pi
->extra
->damp_info
,
14290 &bgp
->damp
[afi
][safi
],
14298 bgp_dest_unlock_node(rm
);
14301 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
14303 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14306 || dest_p
->prefixlen
== match
.prefixlen
) {
14307 pi
= bgp_dest_get_bgp_path_info(dest
);
14309 if (pi
->extra
&& pi
->extra
->damp_info
) {
14310 pi_temp
= pi
->next
;
14311 struct bgp_damp_info
*bdi
=
14312 pi
->extra
->damp_info
;
14313 if (bdi
->lastrecord
14314 == BGP_RECORD_UPDATE
) {
14315 bgp_aggregate_increment(
14326 bgp_damp_info_free(
14327 &pi
->extra
->damp_info
,
14328 &bgp
->damp
[afi
][safi
],
14336 bgp_dest_unlock_node(dest
);
14340 return CMD_SUCCESS
;
14343 DEFUN (clear_ip_bgp_dampening
,
14344 clear_ip_bgp_dampening_cmd
,
14345 "clear ip bgp dampening",
14349 "Clear route flap dampening information\n")
14351 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14352 bgp_damp_info_clean(bgp
, &bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14354 return CMD_SUCCESS
;
14357 DEFUN (clear_ip_bgp_dampening_prefix
,
14358 clear_ip_bgp_dampening_prefix_cmd
,
14359 "clear ip bgp dampening A.B.C.D/M",
14363 "Clear route flap dampening information\n"
14366 int idx_ipv4_prefixlen
= 4;
14367 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14368 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14371 DEFUN (clear_ip_bgp_dampening_address
,
14372 clear_ip_bgp_dampening_address_cmd
,
14373 "clear ip bgp dampening A.B.C.D",
14377 "Clear route flap dampening information\n"
14378 "Network to clear damping information\n")
14381 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14382 SAFI_UNICAST
, NULL
, 0);
14385 DEFUN (clear_ip_bgp_dampening_address_mask
,
14386 clear_ip_bgp_dampening_address_mask_cmd
,
14387 "clear ip bgp dampening A.B.C.D A.B.C.D",
14391 "Clear route flap dampening information\n"
14392 "Network to clear damping information\n"
14396 int idx_ipv4_2
= 5;
14398 char prefix_str
[BUFSIZ
];
14400 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14403 vty_out(vty
, "%% Inconsistent address and mask\n");
14404 return CMD_WARNING
;
14407 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14411 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14413 struct vty
*vty
= arg
;
14414 struct peer
*peer
= bucket
->data
;
14415 char buf
[SU_ADDRSTRLEN
];
14417 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14418 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14421 DEFUN (show_bgp_listeners
,
14422 show_bgp_listeners_cmd
,
14423 "show bgp listeners",
14426 "Display Listen Sockets and who created them\n")
14428 bgp_dump_listener_info(vty
);
14430 return CMD_SUCCESS
;
14433 DEFUN (show_bgp_peerhash
,
14434 show_bgp_peerhash_cmd
,
14435 "show bgp peerhash",
14438 "Display information about the BGP peerhash\n")
14440 struct list
*instances
= bm
->bgp
;
14441 struct listnode
*node
;
14444 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14445 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14446 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14450 return CMD_SUCCESS
;
14453 /* also used for encap safi */
14454 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14455 afi_t afi
, safi_t safi
)
14457 struct bgp_dest
*pdest
;
14458 struct bgp_dest
*dest
;
14459 struct bgp_table
*table
;
14460 const struct prefix
*p
;
14461 const struct prefix_rd
*prd
;
14462 struct bgp_static
*bgp_static
;
14463 mpls_label_t label
;
14464 char rdbuf
[RD_ADDRSTRLEN
];
14466 /* Network configuration. */
14467 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14468 pdest
= bgp_route_next(pdest
)) {
14469 table
= bgp_dest_get_bgp_table_info(pdest
);
14473 for (dest
= bgp_table_top(table
); dest
;
14474 dest
= bgp_route_next(dest
)) {
14475 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14476 if (bgp_static
== NULL
)
14479 p
= bgp_dest_get_prefix(dest
);
14480 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14483 /* "network" configuration display. */
14484 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14485 label
= decode_label(&bgp_static
->label
);
14487 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14488 if (safi
== SAFI_MPLS_VPN
)
14489 vty_out(vty
, " label %u", label
);
14491 if (bgp_static
->rmap
.name
)
14492 vty_out(vty
, " route-map %s",
14493 bgp_static
->rmap
.name
);
14495 if (bgp_static
->backdoor
)
14496 vty_out(vty
, " backdoor");
14498 vty_out(vty
, "\n");
14503 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14504 afi_t afi
, safi_t safi
)
14506 struct bgp_dest
*pdest
;
14507 struct bgp_dest
*dest
;
14508 struct bgp_table
*table
;
14509 const struct prefix
*p
;
14510 const struct prefix_rd
*prd
;
14511 struct bgp_static
*bgp_static
;
14512 char buf
[PREFIX_STRLEN
* 2];
14513 char buf2
[SU_ADDRSTRLEN
];
14514 char rdbuf
[RD_ADDRSTRLEN
];
14515 char esi_buf
[ESI_BYTES
];
14517 /* Network configuration. */
14518 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14519 pdest
= bgp_route_next(pdest
)) {
14520 table
= bgp_dest_get_bgp_table_info(pdest
);
14524 for (dest
= bgp_table_top(table
); dest
;
14525 dest
= bgp_route_next(dest
)) {
14526 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14527 if (bgp_static
== NULL
)
14530 char *macrouter
= NULL
;
14532 if (bgp_static
->router_mac
)
14533 macrouter
= prefix_mac2str(
14534 bgp_static
->router_mac
, NULL
, 0);
14535 if (bgp_static
->eth_s_id
)
14536 esi_to_str(bgp_static
->eth_s_id
,
14537 esi_buf
, sizeof(esi_buf
));
14538 p
= bgp_dest_get_prefix(dest
);
14539 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14541 /* "network" configuration display. */
14542 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14543 if (p
->u
.prefix_evpn
.route_type
== 5) {
14544 char local_buf
[PREFIX_STRLEN
];
14545 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14546 struct prefix_evpn
*)p
)
14550 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14551 local_buf
, PREFIX_STRLEN
);
14552 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14553 p
->u
.prefix_evpn
.prefix_addr
14554 .ip_prefix_length
);
14556 prefix2str(p
, buf
, sizeof(buf
));
14559 if (bgp_static
->gatewayIp
.family
== AF_INET
14560 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14561 inet_ntop(bgp_static
->gatewayIp
.family
,
14562 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14565 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14567 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14568 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14571 XFREE(MTYPE_TMP
, macrouter
);
14576 /* Configuration of static route announcement and aggregate
14578 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14581 struct bgp_dest
*dest
;
14582 const struct prefix
*p
;
14583 struct bgp_static
*bgp_static
;
14584 struct bgp_aggregate
*bgp_aggregate
;
14586 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14587 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14591 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14592 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14596 /* Network configuration. */
14597 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14598 dest
= bgp_route_next(dest
)) {
14599 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14600 if (bgp_static
== NULL
)
14603 p
= bgp_dest_get_prefix(dest
);
14605 vty_out(vty
, " network %pFX", p
);
14607 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14608 vty_out(vty
, " label-index %u",
14609 bgp_static
->label_index
);
14611 if (bgp_static
->rmap
.name
)
14612 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14614 if (bgp_static
->backdoor
)
14615 vty_out(vty
, " backdoor");
14617 vty_out(vty
, "\n");
14620 /* Aggregate-address configuration. */
14621 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14622 dest
= bgp_route_next(dest
)) {
14623 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14624 if (bgp_aggregate
== NULL
)
14627 p
= bgp_dest_get_prefix(dest
);
14629 vty_out(vty
, " aggregate-address %pFX", p
);
14631 if (bgp_aggregate
->as_set
)
14632 vty_out(vty
, " as-set");
14634 if (bgp_aggregate
->summary_only
)
14635 vty_out(vty
, " summary-only");
14637 if (bgp_aggregate
->rmap
.name
)
14638 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14640 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14641 vty_out(vty
, " origin %s",
14642 bgp_origin2str(bgp_aggregate
->origin
));
14644 if (bgp_aggregate
->match_med
)
14645 vty_out(vty
, " matching-MED-only");
14647 if (bgp_aggregate
->suppress_map_name
)
14648 vty_out(vty
, " suppress-map %s",
14649 bgp_aggregate
->suppress_map_name
);
14651 vty_out(vty
, "\n");
14655 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14658 struct bgp_dest
*dest
;
14659 struct bgp_distance
*bdistance
;
14661 /* Distance configuration. */
14662 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
14663 && bgp
->distance_local
[afi
][safi
]
14664 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
14665 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
14666 || bgp
->distance_local
[afi
][safi
]
14667 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
14668 vty_out(vty
, " distance bgp %d %d %d\n",
14669 bgp
->distance_ebgp
[afi
][safi
],
14670 bgp
->distance_ibgp
[afi
][safi
],
14671 bgp
->distance_local
[afi
][safi
]);
14674 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14675 dest
= bgp_route_next(dest
)) {
14676 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14677 if (bdistance
!= NULL
)
14678 vty_out(vty
, " distance %d %pBD %s\n",
14679 bdistance
->distance
, dest
,
14680 bdistance
->access_list
? bdistance
->access_list
14685 /* Allocate routing table structure and install commands. */
14686 void bgp_route_init(void)
14691 /* Init BGP distance table. */
14692 FOREACH_AFI_SAFI (afi
, safi
)
14693 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14695 /* IPv4 BGP commands. */
14696 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14697 install_element(BGP_NODE
, &bgp_network_cmd
);
14698 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14700 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14702 /* IPv4 unicast configuration. */
14703 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14704 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14705 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14707 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14709 /* IPv4 multicast configuration. */
14710 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14711 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14712 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14713 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14715 /* IPv4 labeled-unicast configuration. */
14716 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14717 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14719 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14720 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14721 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14722 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14723 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14724 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14725 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14726 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14728 install_element(VIEW_NODE
,
14729 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14730 install_element(VIEW_NODE
,
14731 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
14732 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
14733 install_element(VIEW_NODE
,
14734 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
14735 #ifdef KEEP_OLD_VPN_COMMANDS
14736 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
14737 #endif /* KEEP_OLD_VPN_COMMANDS */
14738 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
14739 install_element(VIEW_NODE
,
14740 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
14742 /* BGP dampening clear commands */
14743 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
14744 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
14746 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
14747 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
14750 install_element(ENABLE_NODE
,
14751 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
14752 #ifdef KEEP_OLD_VPN_COMMANDS
14753 install_element(ENABLE_NODE
,
14754 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
14755 #endif /* KEEP_OLD_VPN_COMMANDS */
14757 /* New config IPv6 BGP commands. */
14758 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
14759 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
14760 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
14762 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
14764 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
14766 /* IPv6 labeled unicast address family. */
14767 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
14768 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
14770 install_element(BGP_NODE
, &bgp_distance_cmd
);
14771 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
14772 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
14773 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
14774 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
14775 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
14776 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
14777 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
14778 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
14779 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
14780 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
14781 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
14782 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
14783 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
14784 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
14786 /* BGP dampening */
14787 install_element(BGP_NODE
, &bgp_dampening_cmd
);
14788 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
14789 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
14790 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
14791 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
14792 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
14793 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
14795 /* Large Communities */
14796 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
14797 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
14799 /* show bgp ipv4 flowspec detailed */
14800 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
14802 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
14803 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
14806 void bgp_route_finish(void)
14811 FOREACH_AFI_SAFI (afi
, safi
) {
14812 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
14813 bgp_distance_table
[afi
][safi
] = NULL
;