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 DEFINE_HOOK(bgp_rpki_prefix_status
,
101 (struct peer
*peer
, struct attr
*attr
,
102 const struct prefix
*prefix
),
103 (peer
, attr
, prefix
));
105 /* Extern from bgp_dump.c */
106 extern const char *bgp_origin_str
[];
107 extern const char *bgp_origin_long_str
[];
110 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
111 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
112 static const struct message bgp_pmsi_tnltype_str
[] = {
113 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
114 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
115 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
116 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
117 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
118 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
119 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
120 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
124 #define VRFID_NONE_STR "-"
126 DEFINE_HOOK(bgp_process
,
127 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
128 struct peer
*peer
, bool withdraw
),
129 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
131 /** Test if path is suppressed. */
132 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
134 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
137 return listcount(pi
->extra
->aggr_suppressors
) > 0;
140 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
141 safi_t safi
, const struct prefix
*p
,
142 struct prefix_rd
*prd
)
144 struct bgp_dest
*dest
;
145 struct bgp_dest
*pdest
= NULL
;
149 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
150 || (safi
== SAFI_EVPN
)) {
151 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
153 if (!bgp_dest_has_bgp_path_info_data(pdest
))
154 bgp_dest_set_bgp_table_info(
155 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
157 bgp_dest_unlock_node(pdest
);
158 table
= bgp_dest_get_bgp_table_info(pdest
);
161 dest
= bgp_node_get(table
, p
);
163 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
164 || (safi
== SAFI_EVPN
))
170 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
171 safi_t safi
, const struct prefix
*p
,
172 struct prefix_rd
*prd
)
174 struct bgp_dest
*dest
;
175 struct bgp_dest
*pdest
= NULL
;
180 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
181 || (safi
== SAFI_EVPN
)) {
182 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
186 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
187 bgp_dest_unlock_node(pdest
);
191 table
= bgp_dest_get_bgp_table_info(pdest
);
194 dest
= bgp_node_lookup(table
, p
);
199 /* Allocate bgp_path_info_extra */
200 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
202 struct bgp_path_info_extra
*new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
204 sizeof(struct bgp_path_info_extra
));
205 new->label
[0] = MPLS_INVALID_LABEL
;
207 new->bgp_fs_pbr
= NULL
;
208 new->bgp_fs_iprule
= NULL
;
212 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
214 struct bgp_path_info_extra
*e
;
216 if (!extra
|| !*extra
)
223 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
226 /* FIXME: since multiple e may have the same e->parent
227 * and e->parent->net is holding a refcount for each
228 * of them, we need to do some fudging here.
230 * WARNING: if bpi->net->lock drops to 0, bpi may be
231 * freed as well (because bpi->net was holding the
232 * last reference to bpi) => write after free!
236 bpi
= bgp_path_info_lock(bpi
);
237 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
238 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
241 bgp_path_info_unlock(bpi
);
243 bgp_path_info_unlock(e
->parent
);
248 bgp_unlock(e
->bgp_orig
);
250 if (e
->aggr_suppressors
)
251 list_delete(&e
->aggr_suppressors
);
254 bgp_evpn_path_es_info_free(e
->es_info
);
256 if ((*extra
)->bgp_fs_iprule
)
257 list_delete(&((*extra
)->bgp_fs_iprule
));
258 if ((*extra
)->bgp_fs_pbr
)
259 list_delete(&((*extra
)->bgp_fs_pbr
));
260 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
263 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
264 * allocated if required.
266 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
269 pi
->extra
= bgp_path_info_extra_new();
273 /* Free bgp route information. */
274 static void bgp_path_info_free(struct bgp_path_info
*path
)
276 bgp_attr_unintern(&path
->attr
);
278 bgp_unlink_nexthop(path
);
279 bgp_path_info_extra_free(&path
->extra
);
280 bgp_path_info_mpath_free(&path
->mpath
);
282 bgp_addpath_free_info_data(&path
->tx_addpath
,
283 &path
->net
->tx_addpath
);
285 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
287 XFREE(MTYPE_BGP_ROUTE
, path
);
290 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
296 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
298 assert(path
&& path
->lock
> 0);
301 if (path
->lock
== 0) {
303 zlog_debug ("%s: unlocked and freeing", __func__
);
304 zlog_backtrace (LOG_DEBUG
);
306 bgp_path_info_free(path
);
313 zlog_debug ("%s: unlocked to 1", __func__
);
314 zlog_backtrace (LOG_DEBUG
);
321 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
322 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
325 struct bgp_path_info
*old_pi
, *nextpi
;
326 bool set_flag
= false;
327 struct bgp
*bgp
= NULL
;
328 struct bgp_table
*table
= NULL
;
332 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
333 * then the route selection is deferred
335 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
338 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
339 if (BGP_DEBUG(update
, UPDATE_OUT
))
341 "Route %pBD is in workqueue and being processed, not deferred.",
347 table
= bgp_dest_table(dest
);
354 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
355 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
356 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
359 /* Route selection is deferred if there is a stale path which
360 * which indicates peer is in restart mode
362 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
363 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
366 /* If the peer is graceful restart capable and peer is
367 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
370 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
371 && BGP_PEER_RESTARTING_MODE(peer
)
373 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
381 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
384 if (set_flag
&& table
) {
385 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
386 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
387 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
388 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
389 if (BGP_DEBUG(update
, UPDATE_OUT
))
390 zlog_debug("DEFER route %pBD, dest %p", dest
,
398 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
400 struct bgp_path_info
*top
;
402 top
= bgp_dest_get_bgp_path_info(dest
);
408 bgp_dest_set_bgp_path_info(dest
, pi
);
410 bgp_path_info_lock(pi
);
411 bgp_dest_lock_node(dest
);
412 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
413 bgp_dest_set_defer_flag(dest
, false);
414 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
417 /* Do the actual removal of info from RIB, for use by bgp_process
418 completion callback *only* */
419 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
422 pi
->next
->prev
= pi
->prev
;
424 pi
->prev
->next
= pi
->next
;
426 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
428 bgp_path_info_mpath_dequeue(pi
);
429 bgp_path_info_unlock(pi
);
430 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
431 bgp_dest_unlock_node(dest
);
434 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
436 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
437 /* set of previous already took care of pcount */
438 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
441 /* undo the effects of a previous call to bgp_path_info_delete; typically
442 called when a route is deleted and then quickly re-added before the
443 deletion has been processed */
444 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
446 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
447 /* unset of previous already took care of pcount */
448 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
451 /* Adjust pcount as required */
452 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
454 struct bgp_table
*table
;
456 assert(dest
&& bgp_dest_table(dest
));
457 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
459 table
= bgp_dest_table(dest
);
461 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
464 if (!BGP_PATH_COUNTABLE(pi
)
465 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
467 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
469 /* slight hack, but more robust against errors. */
470 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
471 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
473 flog_err(EC_LIB_DEVELOPMENT
,
474 "Asked to decrement 0 prefix count for peer");
475 } else if (BGP_PATH_COUNTABLE(pi
)
476 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
477 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
478 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
482 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
483 struct bgp_path_info
*pi2
)
485 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
488 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
489 * This is here primarily to keep prefix-count in check.
491 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
494 SET_FLAG(pi
->flags
, flag
);
496 /* early bath if we know it's not a flag that changes countability state
498 if (!CHECK_FLAG(flag
,
499 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
502 bgp_pcount_adjust(dest
, pi
);
505 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
508 UNSET_FLAG(pi
->flags
, flag
);
510 /* early bath if we know it's not a flag that changes countability state
512 if (!CHECK_FLAG(flag
,
513 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
516 bgp_pcount_adjust(dest
, pi
);
519 /* Get MED value. If MED value is missing and "bgp bestpath
520 missing-as-worst" is specified, treat it as the worst value. */
521 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
523 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
526 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
533 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
536 if (pi
->addpath_rx_id
)
537 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
538 pi
->peer
->host
, pi
->addpath_rx_id
);
540 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
543 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
545 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
546 struct bgp_path_info
*exist
, int *paths_eq
,
547 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
548 char *pfx_buf
, afi_t afi
, safi_t safi
,
549 enum bgp_path_selection_reason
*reason
)
551 struct attr
*newattr
, *existattr
;
552 bgp_peer_sort_t new_sort
;
553 bgp_peer_sort_t exist_sort
;
559 uint32_t exist_weight
;
560 uint32_t newm
, existm
;
561 struct in_addr new_id
;
562 struct in_addr exist_id
;
565 int internal_as_route
;
568 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
569 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
571 uint32_t exist_mm_seq
;
578 bool new_origin
, exist_origin
;
584 *reason
= bgp_path_selection_none
;
586 zlog_debug("%s: new is NULL", pfx_buf
);
591 bgp_path_info_path_with_addpath_rx_str(new, new_buf
,
595 *reason
= bgp_path_selection_first
;
597 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
603 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
,
605 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
606 pfx_buf
, new_buf
, new->flags
, exist_buf
,
611 existattr
= exist
->attr
;
613 /* For EVPN routes, we cannot just go by local vs remote, we have to
614 * look at the MAC mobility sequence number, if present.
616 if (safi
== SAFI_EVPN
) {
617 /* This is an error condition described in RFC 7432 Section
619 * states that in this scenario "the PE MUST alert the operator"
621 * does not state what other action to take. In order to provide
623 * consistency in this scenario we are going to prefer the path
627 if (newattr
->sticky
!= existattr
->sticky
) {
630 bgp_dest_get_prefix(new->net
), pfx_buf
,
631 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
632 bgp_path_info_path_with_addpath_rx_str(
633 new, new_buf
, sizeof(new_buf
));
634 bgp_path_info_path_with_addpath_rx_str(
635 exist
, exist_buf
, sizeof(exist_buf
));
638 if (newattr
->sticky
&& !existattr
->sticky
) {
639 *reason
= bgp_path_selection_evpn_sticky_mac
;
642 "%s: %s wins over %s due to sticky MAC flag",
643 pfx_buf
, new_buf
, exist_buf
);
647 if (!newattr
->sticky
&& existattr
->sticky
) {
648 *reason
= bgp_path_selection_evpn_sticky_mac
;
651 "%s: %s loses to %s due to sticky MAC flag",
652 pfx_buf
, new_buf
, exist_buf
);
657 new_esi
= bgp_evpn_attr_get_esi(newattr
);
658 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
659 if (bgp_evpn_is_esi_valid(new_esi
) &&
660 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
666 /* If both paths have the same non-zero ES and
667 * one path is local it wins.
668 * PS: Note the local path wins even if the remote
669 * has the higher MM seq. The local path's
670 * MM seq will be fixed up to match the highest
671 * rem seq, subsequently.
674 char esi_buf
[ESI_STR_LEN
];
676 if (bgp_evpn_is_path_local(bgp
, new)) {
677 *reason
= bgp_path_selection_evpn_local_path
;
680 "%s: %s wins over %s as ES %s is same and local",
681 pfx_buf
, new_buf
, exist_buf
,
682 esi_to_str(new_esi
, esi_buf
,
686 if (bgp_evpn_is_path_local(bgp
, exist
)) {
687 *reason
= bgp_path_selection_evpn_local_path
;
690 "%s: %s loses to %s as ES %s is same and local",
691 pfx_buf
, new_buf
, exist_buf
,
692 esi_to_str(new_esi
, esi_buf
,
698 new_mm_seq
= mac_mobility_seqnum(newattr
);
699 exist_mm_seq
= mac_mobility_seqnum(existattr
);
701 if (new_mm_seq
> exist_mm_seq
) {
702 *reason
= bgp_path_selection_evpn_seq
;
705 "%s: %s wins over %s due to MM seq %u > %u",
706 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
711 if (new_mm_seq
< exist_mm_seq
) {
712 *reason
= bgp_path_selection_evpn_seq
;
715 "%s: %s loses to %s due to MM seq %u < %u",
716 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
721 /* if the sequence numbers and ESI are the same and one path
722 * is non-proxy it wins (over proxy)
724 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
725 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
726 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
727 old_proxy
!= new_proxy
) {
729 *reason
= bgp_path_selection_evpn_non_proxy
;
732 "%s: %s wins over %s, same seq/es and non-proxy",
733 pfx_buf
, new_buf
, exist_buf
);
737 *reason
= bgp_path_selection_evpn_non_proxy
;
740 "%s: %s loses to %s, same seq/es and non-proxy",
741 pfx_buf
, new_buf
, exist_buf
);
746 * if sequence numbers are the same path with the lowest IP
749 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
751 *reason
= bgp_path_selection_evpn_lower_ip
;
754 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
755 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
756 &new->attr
->nexthop
);
760 *reason
= bgp_path_selection_evpn_lower_ip
;
763 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
764 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
765 &new->attr
->nexthop
);
770 /* 1. Weight check. */
771 new_weight
= newattr
->weight
;
772 exist_weight
= existattr
->weight
;
774 if (new_weight
> exist_weight
) {
775 *reason
= bgp_path_selection_weight
;
777 zlog_debug("%s: %s wins over %s due to weight %d > %d",
778 pfx_buf
, new_buf
, exist_buf
, new_weight
,
783 if (new_weight
< exist_weight
) {
784 *reason
= bgp_path_selection_weight
;
786 zlog_debug("%s: %s loses to %s due to weight %d < %d",
787 pfx_buf
, new_buf
, exist_buf
, new_weight
,
792 /* 2. Local preference check. */
793 new_pref
= exist_pref
= bgp
->default_local_pref
;
795 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
796 new_pref
= newattr
->local_pref
;
797 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
798 exist_pref
= existattr
->local_pref
;
800 if (new_pref
> exist_pref
) {
801 *reason
= bgp_path_selection_local_pref
;
804 "%s: %s wins over %s due to localpref %d > %d",
805 pfx_buf
, new_buf
, exist_buf
, new_pref
,
810 if (new_pref
< exist_pref
) {
811 *reason
= bgp_path_selection_local_pref
;
814 "%s: %s loses to %s due to localpref %d < %d",
815 pfx_buf
, new_buf
, exist_buf
, new_pref
,
820 /* 3. Local route check. We prefer:
822 * - BGP_ROUTE_AGGREGATE
823 * - BGP_ROUTE_REDISTRIBUTE
825 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
826 new->sub_type
== BGP_ROUTE_IMPORTED
);
827 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
828 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
830 if (new_origin
&& !exist_origin
) {
831 *reason
= bgp_path_selection_local_route
;
834 "%s: %s wins over %s due to preferred BGP_ROUTE type",
835 pfx_buf
, new_buf
, exist_buf
);
839 if (!new_origin
&& exist_origin
) {
840 *reason
= bgp_path_selection_local_route
;
843 "%s: %s loses to %s due to preferred BGP_ROUTE type",
844 pfx_buf
, new_buf
, exist_buf
);
848 /* 4. AS path length check. */
849 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
850 int exist_hops
= aspath_count_hops(existattr
->aspath
);
851 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
853 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
856 aspath_hops
= aspath_count_hops(newattr
->aspath
);
857 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
859 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
860 *reason
= bgp_path_selection_confed_as_path
;
863 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
864 pfx_buf
, new_buf
, exist_buf
,
866 (exist_hops
+ exist_confeds
));
870 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
871 *reason
= bgp_path_selection_confed_as_path
;
874 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
875 pfx_buf
, new_buf
, exist_buf
,
877 (exist_hops
+ exist_confeds
));
881 int newhops
= aspath_count_hops(newattr
->aspath
);
883 if (newhops
< exist_hops
) {
884 *reason
= bgp_path_selection_as_path
;
887 "%s: %s wins over %s due to aspath hopcount %d < %d",
888 pfx_buf
, new_buf
, exist_buf
,
889 newhops
, exist_hops
);
893 if (newhops
> exist_hops
) {
894 *reason
= bgp_path_selection_as_path
;
897 "%s: %s loses to %s due to aspath hopcount %d > %d",
898 pfx_buf
, new_buf
, exist_buf
,
899 newhops
, exist_hops
);
905 /* 5. Origin check. */
906 if (newattr
->origin
< existattr
->origin
) {
907 *reason
= bgp_path_selection_origin
;
909 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
910 pfx_buf
, new_buf
, exist_buf
,
911 bgp_origin_long_str
[newattr
->origin
],
912 bgp_origin_long_str
[existattr
->origin
]);
916 if (newattr
->origin
> existattr
->origin
) {
917 *reason
= bgp_path_selection_origin
;
919 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
920 pfx_buf
, new_buf
, exist_buf
,
921 bgp_origin_long_str
[newattr
->origin
],
922 bgp_origin_long_str
[existattr
->origin
]);
927 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
928 && aspath_count_hops(existattr
->aspath
) == 0);
929 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
930 && aspath_count_confeds(existattr
->aspath
) > 0
931 && aspath_count_hops(newattr
->aspath
) == 0
932 && aspath_count_hops(existattr
->aspath
) == 0);
934 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
935 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
936 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
937 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
938 || internal_as_route
) {
939 new_med
= bgp_med_value(new->attr
, bgp
);
940 exist_med
= bgp_med_value(exist
->attr
, bgp
);
942 if (new_med
< exist_med
) {
943 *reason
= bgp_path_selection_med
;
946 "%s: %s wins over %s due to MED %d < %d",
947 pfx_buf
, new_buf
, exist_buf
, new_med
,
952 if (new_med
> exist_med
) {
953 *reason
= bgp_path_selection_med
;
956 "%s: %s loses to %s due to MED %d > %d",
957 pfx_buf
, new_buf
, exist_buf
, new_med
,
963 /* 7. Peer type check. */
964 new_sort
= new->peer
->sort
;
965 exist_sort
= exist
->peer
->sort
;
967 if (new_sort
== BGP_PEER_EBGP
968 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
969 *reason
= bgp_path_selection_peer
;
972 "%s: %s wins over %s due to eBGP peer > iBGP peer",
973 pfx_buf
, new_buf
, exist_buf
);
977 if (exist_sort
== BGP_PEER_EBGP
978 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
979 *reason
= bgp_path_selection_peer
;
982 "%s: %s loses to %s due to iBGP peer < eBGP peer",
983 pfx_buf
, new_buf
, exist_buf
);
987 /* 8. IGP metric check. */
991 newm
= new->extra
->igpmetric
;
993 existm
= exist
->extra
->igpmetric
;
998 "%s: %s wins over %s due to IGP metric %u < %u",
999 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1003 if (newm
> existm
) {
1006 "%s: %s loses to %s due to IGP metric %u > %u",
1007 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1011 /* 9. Same IGP metric. Compare the cluster list length as
1012 representative of IGP hops metric. Rewrite the metric value
1013 pair (newm, existm) with the cluster list length. Prefer the
1014 path with smaller cluster list length. */
1015 if (newm
== existm
) {
1016 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1017 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1018 && (mpath_cfg
== NULL
1020 mpath_cfg
->ibgp_flags
,
1021 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1022 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1023 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1025 if (newm
< existm
) {
1028 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1029 pfx_buf
, new_buf
, exist_buf
,
1034 if (newm
> existm
) {
1037 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1038 pfx_buf
, new_buf
, exist_buf
,
1045 /* 10. confed-external vs. confed-internal */
1046 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1047 if (new_sort
== BGP_PEER_CONFED
1048 && exist_sort
== BGP_PEER_IBGP
) {
1049 *reason
= bgp_path_selection_confed
;
1052 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1053 pfx_buf
, new_buf
, exist_buf
);
1057 if (exist_sort
== BGP_PEER_CONFED
1058 && new_sort
== BGP_PEER_IBGP
) {
1059 *reason
= bgp_path_selection_confed
;
1062 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1063 pfx_buf
, new_buf
, exist_buf
);
1068 /* 11. Maximum path check. */
1069 if (newm
== existm
) {
1070 /* If one path has a label but the other does not, do not treat
1071 * them as equals for multipath
1073 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1075 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1078 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1079 pfx_buf
, new_buf
, exist_buf
);
1080 } else if (CHECK_FLAG(bgp
->flags
,
1081 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1084 * For the two paths, all comparison steps till IGP
1086 * have succeeded - including AS_PATH hop count. Since
1088 * bestpath as-path multipath-relax' knob is on, we
1090 * an exact match of AS_PATH. Thus, mark the paths are
1092 * That will trigger both these paths to get into the
1100 "%s: %s and %s are equal via multipath-relax",
1101 pfx_buf
, new_buf
, exist_buf
);
1102 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1103 if (aspath_cmp(new->attr
->aspath
,
1104 exist
->attr
->aspath
)) {
1109 "%s: %s and %s are equal via matching aspaths",
1110 pfx_buf
, new_buf
, exist_buf
);
1112 } else if (new->peer
->as
== exist
->peer
->as
) {
1117 "%s: %s and %s are equal via same remote-as",
1118 pfx_buf
, new_buf
, exist_buf
);
1122 * TODO: If unequal cost ibgp multipath is enabled we can
1123 * mark the paths as equal here instead of returning
1128 "%s: %s wins over %s after IGP metric comparison",
1129 pfx_buf
, new_buf
, exist_buf
);
1132 "%s: %s loses to %s after IGP metric comparison",
1133 pfx_buf
, new_buf
, exist_buf
);
1135 *reason
= bgp_path_selection_igp_metric
;
1139 /* 12. If both paths are external, prefer the path that was received
1140 first (the oldest one). This step minimizes route-flap, since a
1141 newer path won't displace an older one, even if it was the
1142 preferred route based on the additional decision criteria below. */
1143 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1144 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1145 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1146 *reason
= bgp_path_selection_older
;
1149 "%s: %s wins over %s due to oldest external",
1150 pfx_buf
, new_buf
, exist_buf
);
1154 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1155 *reason
= bgp_path_selection_older
;
1158 "%s: %s loses to %s due to oldest external",
1159 pfx_buf
, new_buf
, exist_buf
);
1164 /* 13. Router-ID comparision. */
1165 /* If one of the paths is "stale", the corresponding peer router-id will
1166 * be 0 and would always win over the other path. If originator id is
1167 * used for the comparision, it will decide which path is better.
1169 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1170 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1172 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1173 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1174 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1176 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1178 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1179 *reason
= bgp_path_selection_router_id
;
1182 "%s: %s wins over %s due to Router-ID comparison",
1183 pfx_buf
, new_buf
, exist_buf
);
1187 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1188 *reason
= bgp_path_selection_router_id
;
1191 "%s: %s loses to %s due to Router-ID comparison",
1192 pfx_buf
, new_buf
, exist_buf
);
1196 /* 14. Cluster length comparision. */
1197 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1198 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1200 if (new_cluster
< exist_cluster
) {
1201 *reason
= bgp_path_selection_cluster_length
;
1204 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1205 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1210 if (new_cluster
> exist_cluster
) {
1211 *reason
= bgp_path_selection_cluster_length
;
1214 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1215 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1220 /* 15. Neighbor address comparision. */
1221 /* Do this only if neither path is "stale" as stale paths do not have
1222 * valid peer information (as the connection may or may not be up).
1224 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1225 *reason
= bgp_path_selection_stale
;
1228 "%s: %s wins over %s due to latter path being STALE",
1229 pfx_buf
, new_buf
, exist_buf
);
1233 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1234 *reason
= bgp_path_selection_stale
;
1237 "%s: %s loses to %s due to former path being STALE",
1238 pfx_buf
, new_buf
, exist_buf
);
1242 /* locally configured routes to advertise do not have su_remote */
1243 if (new->peer
->su_remote
== NULL
) {
1244 *reason
= bgp_path_selection_local_configured
;
1247 if (exist
->peer
->su_remote
== NULL
) {
1248 *reason
= bgp_path_selection_local_configured
;
1252 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1255 *reason
= bgp_path_selection_neighbor_ip
;
1258 "%s: %s loses to %s due to Neighor IP comparison",
1259 pfx_buf
, new_buf
, exist_buf
);
1264 *reason
= bgp_path_selection_neighbor_ip
;
1267 "%s: %s wins over %s due to Neighor IP comparison",
1268 pfx_buf
, new_buf
, exist_buf
);
1272 *reason
= bgp_path_selection_default
;
1274 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1275 pfx_buf
, new_buf
, exist_buf
);
1281 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1282 struct bgp_path_info
*exist
, int *paths_eq
)
1284 enum bgp_path_selection_reason reason
;
1285 char pfx_buf
[PREFIX2STR_BUFFER
];
1287 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1288 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1291 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1292 * is preferred, or 0 if they are the same (usually will only occur if
1293 * multipath is enabled
1294 * This version is compatible with */
1295 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1296 struct bgp_path_info
*exist
, char *pfx_buf
,
1297 afi_t afi
, safi_t safi
,
1298 enum bgp_path_selection_reason
*reason
)
1302 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1316 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1317 const struct prefix
*p
,
1318 struct attr
*attr
, afi_t afi
,
1321 struct bgp_filter
*filter
;
1322 enum filter_type ret
= FILTER_PERMIT
;
1324 filter
= &peer
->filter
[afi
][safi
];
1326 #define FILTER_EXIST_WARN(F, f, filter) \
1327 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1328 zlog_debug("%s: Could not find configured input %s-list %s!", \
1329 peer->host, #f, F##_IN_NAME(filter));
1331 if (DISTRIBUTE_IN_NAME(filter
)) {
1332 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1334 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1341 if (PREFIX_LIST_IN_NAME(filter
)) {
1342 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1344 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1351 if (FILTER_LIST_IN_NAME(filter
)) {
1352 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1354 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1355 == AS_FILTER_DENY
) {
1362 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1363 char pfxprint
[PREFIX2STR_BUFFER
];
1365 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1366 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1367 ret
== FILTER_PERMIT
? "permit" : "deny");
1371 #undef FILTER_EXIST_WARN
1374 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1375 const struct prefix
*p
,
1376 struct attr
*attr
, afi_t afi
,
1379 struct bgp_filter
*filter
;
1380 enum filter_type ret
= FILTER_PERMIT
;
1382 filter
= &peer
->filter
[afi
][safi
];
1384 #define FILTER_EXIST_WARN(F, f, filter) \
1385 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1386 zlog_debug("%s: Could not find configured output %s-list %s!", \
1387 peer->host, #f, F##_OUT_NAME(filter));
1389 if (DISTRIBUTE_OUT_NAME(filter
)) {
1390 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1392 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1399 if (PREFIX_LIST_OUT_NAME(filter
)) {
1400 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1402 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1409 if (FILTER_LIST_OUT_NAME(filter
)) {
1410 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1412 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1413 == AS_FILTER_DENY
) {
1419 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1420 char pfxprint
[PREFIX2STR_BUFFER
];
1422 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1423 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1424 ret
== FILTER_PERMIT
? "permit" : "deny");
1429 #undef FILTER_EXIST_WARN
1432 /* If community attribute includes no_export then return 1. */
1433 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1435 if (attr
->community
) {
1436 /* NO_ADVERTISE check. */
1437 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1440 /* NO_EXPORT check. */
1441 if (peer
->sort
== BGP_PEER_EBGP
1442 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1445 /* NO_EXPORT_SUBCONFED check. */
1446 if (peer
->sort
== BGP_PEER_EBGP
1447 || peer
->sort
== BGP_PEER_CONFED
)
1448 if (community_include(attr
->community
,
1449 COMMUNITY_NO_EXPORT_SUBCONFED
))
1455 /* Route reflection loop check. */
1456 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1458 struct in_addr cluster_id
;
1459 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1462 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1463 cluster_id
= peer
->bgp
->cluster_id
;
1465 cluster_id
= peer
->bgp
->router_id
;
1467 if (cluster_loop_check(cluster
, cluster_id
))
1473 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1474 struct attr
*attr
, afi_t afi
, safi_t safi
,
1475 const char *rmap_name
, mpls_label_t
*label
,
1476 uint32_t num_labels
, struct bgp_dest
*dest
)
1478 struct bgp_filter
*filter
;
1479 struct bgp_path_info rmap_path
= { 0 };
1480 struct bgp_path_info_extra extra
= { 0 };
1481 route_map_result_t ret
;
1482 struct route_map
*rmap
= NULL
;
1484 filter
= &peer
->filter
[afi
][safi
];
1486 /* Apply default weight value. */
1487 if (peer
->weight
[afi
][safi
])
1488 attr
->weight
= peer
->weight
[afi
][safi
];
1491 rmap
= route_map_lookup_by_name(rmap_name
);
1496 if (ROUTE_MAP_IN_NAME(filter
)) {
1497 rmap
= ROUTE_MAP_IN(filter
);
1504 /* Route map apply. */
1506 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1507 /* Duplicate current value to new strucutre for modification. */
1508 rmap_path
.peer
= peer
;
1509 rmap_path
.attr
= attr
;
1510 rmap_path
.extra
= &extra
;
1511 rmap_path
.net
= dest
;
1513 extra
.num_labels
= num_labels
;
1514 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1515 memcpy(extra
.label
, label
,
1516 num_labels
* sizeof(mpls_label_t
));
1518 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1520 /* Apply BGP route map to the attribute. */
1521 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1523 peer
->rmap_type
= 0;
1525 if (ret
== RMAP_DENYMATCH
)
1531 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1532 struct attr
*attr
, afi_t afi
, safi_t safi
,
1533 const char *rmap_name
)
1535 struct bgp_path_info rmap_path
;
1536 route_map_result_t ret
;
1537 struct route_map
*rmap
= NULL
;
1541 * So if we get to this point and have no rmap_name
1542 * we want to just show the output as it currently
1548 /* Apply default weight value. */
1549 if (peer
->weight
[afi
][safi
])
1550 attr
->weight
= peer
->weight
[afi
][safi
];
1552 rmap
= route_map_lookup_by_name(rmap_name
);
1555 * If we have a route map name and we do not find
1556 * the routemap that means we have an implicit
1562 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1563 /* Route map apply. */
1564 /* Duplicate current value to new strucutre for modification. */
1565 rmap_path
.peer
= peer
;
1566 rmap_path
.attr
= attr
;
1568 rmap_type
= peer
->rmap_type
;
1569 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1571 /* Apply BGP route map to the attribute. */
1572 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1574 peer
->rmap_type
= rmap_type
;
1576 if (ret
== RMAP_DENYMATCH
)
1578 * caller has multiple error paths with bgp_attr_flush()
1585 /* If this is an EBGP peer with remove-private-AS */
1586 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1587 struct peer
*peer
, struct attr
*attr
)
1589 if (peer
->sort
== BGP_PEER_EBGP
1590 && (peer_af_flag_check(peer
, afi
, safi
,
1591 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1592 || peer_af_flag_check(peer
, afi
, safi
,
1593 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1594 || peer_af_flag_check(peer
, afi
, safi
,
1595 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1596 || peer_af_flag_check(peer
, afi
, safi
,
1597 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1598 // Take action on the entire aspath
1599 if (peer_af_flag_check(peer
, afi
, safi
,
1600 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1601 || peer_af_flag_check(peer
, afi
, safi
,
1602 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1603 if (peer_af_flag_check(
1605 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1606 attr
->aspath
= aspath_replace_private_asns(
1607 attr
->aspath
, bgp
->as
, peer
->as
);
1609 // The entire aspath consists of private ASNs so create
1611 else if (aspath_private_as_check(attr
->aspath
))
1612 attr
->aspath
= aspath_empty_get();
1614 // There are some public and some private ASNs, remove
1617 attr
->aspath
= aspath_remove_private_asns(
1618 attr
->aspath
, peer
->as
);
1621 // 'all' was not specified so the entire aspath must be private
1623 // for us to do anything
1624 else if (aspath_private_as_check(attr
->aspath
)) {
1625 if (peer_af_flag_check(
1627 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1628 attr
->aspath
= aspath_replace_private_asns(
1629 attr
->aspath
, bgp
->as
, peer
->as
);
1631 attr
->aspath
= aspath_empty_get();
1636 /* If this is an EBGP peer with as-override */
1637 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1638 struct peer
*peer
, struct attr
*attr
)
1640 if (peer
->sort
== BGP_PEER_EBGP
1641 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1642 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1643 attr
->aspath
= aspath_replace_specific_asn(
1644 attr
->aspath
, peer
->as
, bgp
->as
);
1648 void bgp_attr_add_gshut_community(struct attr
*attr
)
1650 struct community
*old
;
1651 struct community
*new;
1652 struct community
*merge
;
1653 struct community
*gshut
;
1655 old
= attr
->community
;
1656 gshut
= community_str2com("graceful-shutdown");
1661 merge
= community_merge(community_dup(old
), gshut
);
1663 if (old
->refcnt
== 0)
1664 community_free(&old
);
1666 new = community_uniq_sort(merge
);
1667 community_free(&merge
);
1669 new = community_dup(gshut
);
1672 community_free(&gshut
);
1673 attr
->community
= new;
1674 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1676 /* When we add the graceful-shutdown community we must also
1677 * lower the local-preference */
1678 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1679 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1683 /* Notify BGP Conditional advertisement scanner process. */
1684 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1686 struct peer
*temp_peer
;
1687 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1688 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1689 afi_t afi
= SUBGRP_AFI(subgrp
);
1690 safi_t safi
= SUBGRP_SAFI(subgrp
);
1691 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1692 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1694 if (!ADVERTISE_MAP_NAME(filter
))
1697 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1698 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1701 if (peer
!= temp_peer
)
1704 temp_peer
->advmap_table_change
= true;
1710 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1712 if (family
== AF_INET
) {
1713 attr
->nexthop
.s_addr
= INADDR_ANY
;
1714 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1716 if (family
== AF_INET6
)
1717 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1718 if (family
== AF_EVPN
)
1719 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1722 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1723 struct update_subgroup
*subgrp
,
1724 const struct prefix
*p
, struct attr
*attr
,
1725 bool skip_rmap_check
)
1727 struct bgp_filter
*filter
;
1730 struct peer
*onlypeer
;
1732 struct attr
*piattr
;
1733 route_map_result_t ret
;
1738 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1739 bool nh_reset
= false;
1742 if (DISABLE_BGP_ANNOUNCE
)
1745 afi
= SUBGRP_AFI(subgrp
);
1746 safi
= SUBGRP_SAFI(subgrp
);
1747 peer
= SUBGRP_PEER(subgrp
);
1749 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1750 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1753 filter
= &peer
->filter
[afi
][safi
];
1754 bgp
= SUBGRP_INST(subgrp
);
1755 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1758 #ifdef ENABLE_BGP_VNC
1759 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1760 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1761 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1764 * direct and direct_ext type routes originate internally even
1765 * though they can have peer pointers that reference other
1768 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1774 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1775 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1776 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1777 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1779 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1784 /* With addpath we may be asked to TX all kinds of paths so make sure
1786 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1787 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1788 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1792 /* If this is not the bestpath then check to see if there is an enabled
1794 * feature that requires us to advertise it */
1795 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1796 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1801 /* Aggregate-address suppress check. */
1802 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1806 * If we are doing VRF 2 VRF leaking via the import
1807 * statement, we want to prevent the route going
1808 * off box as that the RT and RD created are localy
1809 * significant and globaly useless.
1811 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1812 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1815 /* If it's labeled safi, make sure the route has a valid label. */
1816 if (safi
== SAFI_LABELED_UNICAST
) {
1817 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1818 if (!bgp_is_valid_label(&label
)) {
1819 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1820 zlog_debug("u%" PRIu64
":s%" PRIu64
1821 " %pFX is filtered - no label (%p)",
1822 subgrp
->update_group
->id
, subgrp
->id
,
1828 /* Do not send back route to sender. */
1829 if (onlypeer
&& from
== onlypeer
) {
1833 /* Do not send the default route in the BGP table if the neighbor is
1834 * configured for default-originate */
1835 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1836 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1837 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1839 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1843 /* Transparency check. */
1844 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1845 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1850 /* If community is not disabled check the no-export and local. */
1851 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1852 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1853 zlog_debug("%s: community filter check fail for %pFX",
1858 /* If the attribute has originator-id and it is same as remote
1860 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1861 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1862 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1864 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1869 /* ORF prefix-list filter check */
1870 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1871 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1872 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1873 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1874 if (peer
->orf_plist
[afi
][safi
]) {
1875 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1877 if (bgp_debug_update(NULL
, p
,
1878 subgrp
->update_group
, 0))
1880 "%s [Update:SEND] %pFX is filtered via ORF",
1886 /* Output filter check. */
1887 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1888 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1889 zlog_debug("%s [Update:SEND] %pFX is filtered",
1894 /* AS path loop check. */
1895 if (onlypeer
&& onlypeer
->as_path_loop_detection
1896 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1897 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1899 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1900 onlypeer
->host
, onlypeer
->as
);
1904 /* If we're a CONFED we need to loop check the CONFED ID too */
1905 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1906 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1907 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1909 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1910 peer
->host
, bgp
->confed_id
);
1915 /* Route-Reflect check. */
1916 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1921 /* IBGP reflection check. */
1922 if (reflect
&& !samepeer_safe
) {
1923 /* A route from a Client peer. */
1924 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1925 PEER_FLAG_REFLECTOR_CLIENT
)) {
1926 /* Reflect to all the Non-Client peers and also to the
1927 Client peers other than the originator. Originator
1929 is already done. So there is noting to do. */
1930 /* no bgp client-to-client reflection check. */
1931 if (CHECK_FLAG(bgp
->flags
,
1932 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1933 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1934 PEER_FLAG_REFLECTOR_CLIENT
))
1937 /* A route from a Non-client peer. Reflect to all other
1939 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1940 PEER_FLAG_REFLECTOR_CLIENT
))
1945 /* For modify attribute, copy it to temporary structure. */
1948 /* If local-preference is not set. */
1949 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1950 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1951 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1952 attr
->local_pref
= bgp
->default_local_pref
;
1955 /* If originator-id is not set and the route is to be reflected,
1956 set the originator id */
1958 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1959 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1960 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1963 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1965 if (peer
->sort
== BGP_PEER_EBGP
1966 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1967 if (from
!= bgp
->peer_self
&& !transparent
1968 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1969 PEER_FLAG_MED_UNCHANGED
))
1971 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1974 /* Since the nexthop attribute can vary per peer, it is not explicitly
1976 * in announce check, only certain flags and length (or number of
1978 * -- for IPv6/MP_REACH) are set here in order to guide the update
1980 * code in setting the nexthop(s) on a per peer basis in
1982 * Typically, the source nexthop in the attribute is preserved but in
1984 * scenarios where we know it will always be overwritten, we reset the
1985 * nexthop to "0" in an attempt to achieve better Update packing. An
1986 * example of this is when a prefix from each of 2 IBGP peers needs to
1988 * announced to an EBGP peer (and they have the same attributes barring
1992 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1994 #define NEXTHOP_IS_V6 \
1995 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1996 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1997 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1998 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2000 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2002 * the peer (group) is configured to receive link-local nexthop
2004 * and it is available in the prefix OR we're not reflecting the route,
2005 * link-local nexthop address is valid and
2006 * the peer (group) to whom we're going to announce is on a shared
2008 * and this is either a self-originated route or the peer is EBGP.
2009 * By checking if nexthop LL address is valid we are sure that
2010 * we do not announce LL address as `::`.
2012 if (NEXTHOP_IS_V6
) {
2013 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2014 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2015 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2016 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2018 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2019 && peer
->shared_network
2020 && (from
== bgp
->peer_self
2021 || peer
->sort
== BGP_PEER_EBGP
))) {
2022 attr
->mp_nexthop_len
=
2023 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2026 /* Clear off link-local nexthop in source, whenever it is not
2028 * ensure more prefixes share the same attribute for
2031 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2032 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2033 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2036 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2037 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2039 /* Route map & unsuppress-map apply. */
2040 if (!skip_rmap_check
2041 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2042 struct bgp_path_info rmap_path
= {0};
2043 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2044 struct attr dummy_attr
= {0};
2046 /* Fill temp path_info */
2047 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2050 /* don't confuse inbound and outbound setting */
2051 RESET_FLAG(attr
->rmap_change_flags
);
2054 * The route reflector is not allowed to modify the attributes
2055 * of the reflected IBGP routes unless explicitly allowed.
2057 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2058 && !CHECK_FLAG(bgp
->flags
,
2059 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2061 rmap_path
.attr
= &dummy_attr
;
2064 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2066 if (bgp_path_suppressed(pi
))
2067 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2070 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2073 peer
->rmap_type
= 0;
2075 if (ret
== RMAP_DENYMATCH
) {
2076 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2078 "%s [Update:SEND] %pFX is filtered by route-map",
2081 bgp_attr_flush(attr
);
2086 /* RFC 8212 to prevent route leaks.
2087 * This specification intends to improve this situation by requiring the
2088 * explicit configuration of both BGP Import and Export Policies for any
2089 * External BGP (EBGP) session such as customers, peers, or
2090 * confederation boundaries for all enabled address families. Through
2091 * codification of the aforementioned requirement, operators will
2092 * benefit from consistent behavior across different BGP
2095 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2096 if (!bgp_outbound_policy_exists(peer
, filter
))
2099 /* draft-ietf-idr-deprecate-as-set-confed-set
2100 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2101 * Eventually, This document (if approved) updates RFC 4271
2102 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2103 * and obsoletes RFC 6472.
2105 if (peer
->bgp
->reject_as_sets
)
2106 if (aspath_check_as_sets(attr
->aspath
))
2109 /* Codification of AS 0 Processing */
2110 if (aspath_check_as_zero(attr
->aspath
))
2113 if (bgp_in_graceful_shutdown(bgp
)) {
2114 if (peer
->sort
== BGP_PEER_IBGP
2115 || peer
->sort
== BGP_PEER_CONFED
) {
2116 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2117 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2119 bgp_attr_add_gshut_community(attr
);
2123 /* After route-map has been applied, we check to see if the nexthop to
2124 * be carried in the attribute (that is used for the announcement) can
2125 * be cleared off or not. We do this in all cases where we would be
2126 * setting the nexthop to "ourselves". For IPv6, we only need to
2128 * the global nexthop here; the link-local nexthop would have been
2130 * already, and if not, it is required by the update formation code.
2131 * Also see earlier comments in this function.
2134 * If route-map has performed some operation on the nexthop or the peer
2135 * configuration says to pass it unchanged, we cannot reset the nexthop
2136 * here, so only attempt to do it if these aren't true. Note that the
2137 * route-map handler itself might have cleared the nexthop, if for
2139 * it is configured as 'peer-address'.
2141 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2142 piattr
->rmap_change_flags
)
2144 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2145 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2146 /* We can reset the nexthop, if setting (or forcing) it to
2148 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2149 PEER_FLAG_NEXTHOP_SELF
)
2150 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2151 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2153 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2154 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2155 subgroup_announce_reset_nhop(
2156 (peer_cap_enhe(peer
, afi
, safi
)
2162 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2163 /* Can also reset the nexthop if announcing to EBGP, but
2165 * no peer in the subgroup is on a shared subnet.
2166 * Note: 3rd party nexthop currently implemented for
2169 if ((p
->family
== AF_INET
) &&
2170 (!bgp_subgrp_multiaccess_check_v4(
2173 subgroup_announce_reset_nhop(
2174 (peer_cap_enhe(peer
, afi
, safi
)
2181 if ((p
->family
== AF_INET6
) &&
2182 (!bgp_subgrp_multiaccess_check_v6(
2183 piattr
->mp_nexthop_global
,
2185 subgroup_announce_reset_nhop(
2186 (peer_cap_enhe(peer
, afi
, safi
)
2195 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2197 * This flag is used for leaked vpn-vrf routes
2199 int family
= p
->family
;
2201 if (peer_cap_enhe(peer
, afi
, safi
))
2204 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2206 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2207 __func__
, family2str(family
));
2208 subgroup_announce_reset_nhop(family
, attr
);
2213 /* If IPv6/MP and nexthop does not have any override and happens
2215 * be a link-local address, reset it so that we don't pass along
2217 * source's link-local IPv6 address to recipients who may not be
2219 * the same interface.
2221 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2222 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2223 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2229 * When the next hop is set to ourselves, if all multipaths have
2230 * link-bandwidth announce the cumulative bandwidth as that makes
2231 * the most sense. However, don't modify if the link-bandwidth has
2232 * been explicitly set by user policy.
2235 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2236 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2237 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2238 attr
->ecommunity
= ecommunity_replace_linkbw(
2239 bgp
->as
, attr
->ecommunity
, cum_bw
);
2244 static int bgp_route_select_timer_expire(struct thread
*thread
)
2246 struct afi_safi_info
*info
;
2251 info
= THREAD_ARG(thread
);
2256 if (BGP_DEBUG(update
, UPDATE_OUT
))
2257 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2260 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2262 XFREE(MTYPE_TMP
, info
);
2264 /* Best path selection */
2265 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2268 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2269 struct bgp_maxpaths_cfg
*mpath_cfg
,
2270 struct bgp_path_info_pair
*result
, afi_t afi
,
2273 struct bgp_path_info
*new_select
;
2274 struct bgp_path_info
*old_select
;
2275 struct bgp_path_info
*pi
;
2276 struct bgp_path_info
*pi1
;
2277 struct bgp_path_info
*pi2
;
2278 struct bgp_path_info
*nextpi
= NULL
;
2279 int paths_eq
, do_mpath
, debug
;
2280 struct list mp_list
;
2281 char pfx_buf
[PREFIX2STR_BUFFER
];
2282 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2284 bgp_mp_list_init(&mp_list
);
2286 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2288 debug
= bgp_debug_bestpath(dest
);
2291 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2293 dest
->reason
= bgp_path_selection_none
;
2294 /* bgp deterministic-med */
2296 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2298 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2299 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2301 bgp_path_info_unset_flag(dest
, pi1
,
2302 BGP_PATH_DMED_SELECTED
);
2304 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2306 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2308 if (BGP_PATH_HOLDDOWN(pi1
))
2310 if (pi1
->peer
!= bgp
->peer_self
)
2311 if (pi1
->peer
->status
!= Established
)
2316 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2317 if (CHECK_FLAG(pi2
->flags
,
2318 BGP_PATH_DMED_CHECK
))
2320 if (BGP_PATH_HOLDDOWN(pi2
))
2322 if (pi2
->peer
!= bgp
->peer_self
2325 PEER_STATUS_NSF_WAIT
))
2326 if (pi2
->peer
->status
2330 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2332 && !aspath_cmp_left_confed(
2337 if (bgp_path_info_cmp(
2338 bgp
, pi2
, new_select
,
2339 &paths_eq
, mpath_cfg
, debug
,
2342 bgp_path_info_unset_flag(
2344 BGP_PATH_DMED_SELECTED
);
2348 bgp_path_info_set_flag(
2349 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2352 bgp_path_info_set_flag(dest
, new_select
,
2353 BGP_PATH_DMED_CHECK
);
2354 bgp_path_info_set_flag(dest
, new_select
,
2355 BGP_PATH_DMED_SELECTED
);
2358 bgp_path_info_path_with_addpath_rx_str(
2359 new_select
, path_buf
, sizeof(path_buf
));
2361 "%pBD: %s is the bestpath from AS %u",
2363 aspath_get_first_as(
2364 new_select
->attr
->aspath
));
2369 /* Check old selected route and new selected route. */
2372 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2373 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2374 enum bgp_path_selection_reason reason
;
2376 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2379 if (BGP_PATH_HOLDDOWN(pi
)) {
2380 /* reap REMOVED routes, if needs be
2381 * selected route must stay for a while longer though
2383 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2384 && (pi
!= old_select
))
2385 bgp_path_info_reap(dest
, pi
);
2388 zlog_debug("%s: pi %p in holddown", __func__
,
2394 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2395 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2396 if (pi
->peer
->status
!= Established
) {
2400 "%s: pi %p non self peer %s not estab state",
2401 __func__
, pi
, pi
->peer
->host
);
2406 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2407 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2408 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2410 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2414 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2416 reason
= dest
->reason
;
2417 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2418 debug
, pfx_buf
, afi
, safi
,
2420 if (new_select
== NULL
&&
2421 reason
!= bgp_path_selection_none
)
2422 dest
->reason
= reason
;
2427 /* Now that we know which path is the bestpath see if any of the other
2429 * qualify as multipaths
2433 bgp_path_info_path_with_addpath_rx_str(
2434 new_select
, path_buf
, sizeof(path_buf
));
2436 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2438 "%pBD: After path selection, newbest is %s oldbest was %s",
2440 old_select
? old_select
->peer
->host
: "NONE");
2443 if (do_mpath
&& new_select
) {
2444 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2445 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2448 bgp_path_info_path_with_addpath_rx_str(
2449 pi
, path_buf
, sizeof(path_buf
));
2451 if (pi
== new_select
) {
2454 "%pBD: %s is the bestpath, add to the multipath list",
2456 bgp_mp_list_add(&mp_list
, pi
);
2460 if (BGP_PATH_HOLDDOWN(pi
))
2463 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2464 && !CHECK_FLAG(pi
->peer
->sflags
,
2465 PEER_STATUS_NSF_WAIT
))
2466 if (pi
->peer
->status
!= Established
)
2469 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2472 "%pBD: %s has the same nexthop as the bestpath, skip it",
2477 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2478 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2484 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2486 bgp_mp_list_add(&mp_list
, pi
);
2491 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2493 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2494 bgp_mp_list_clear(&mp_list
);
2496 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2498 result
->old
= old_select
;
2499 result
->new = new_select
;
2505 * A new route/change in bestpath of an existing route. Evaluate the path
2506 * for advertisement to the subgroup.
2508 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2509 struct bgp_path_info
*selected
,
2510 struct bgp_dest
*dest
,
2511 uint32_t addpath_tx_id
)
2513 const struct prefix
*p
;
2514 struct peer
*onlypeer
;
2521 p
= bgp_dest_get_prefix(dest
);
2522 afi
= SUBGRP_AFI(subgrp
);
2523 safi
= SUBGRP_SAFI(subgrp
);
2524 bgp
= SUBGRP_INST(subgrp
);
2525 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2528 if (BGP_DEBUG(update
, UPDATE_OUT
))
2529 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2531 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2532 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2533 PEER_STATUS_ORF_WAIT_REFRESH
))
2536 memset(&attr
, 0, sizeof(struct attr
));
2537 /* It's initialized in bgp_announce_check() */
2539 /* Announcement to the subgroup. If the route is filtered withdraw it.
2540 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2541 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2544 advertise
= bgp_check_advertise(bgp
, dest
);
2547 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2549 /* Route is selected, if the route is already installed
2550 * in FIB, then it is advertised
2553 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2556 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2560 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2562 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2567 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2568 * This is called at the end of route processing.
2570 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2572 struct bgp_path_info
*pi
;
2574 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2575 if (BGP_PATH_HOLDDOWN(pi
))
2577 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2578 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2583 * Has the route changed from the RIB's perspective? This is invoked only
2584 * if the route selection returns the same best route as earlier - to
2585 * determine if we need to update zebra or not.
2587 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2589 struct bgp_path_info
*mpinfo
;
2591 /* If this is multipath, check all selected paths for any nexthop
2592 * change or attribute change. Some attribute changes (e.g., community)
2593 * aren't of relevance to the RIB, but we'll update zebra to ensure
2594 * we handle the case of BGP nexthop change. This is the behavior
2595 * when the best path has an attribute change anyway.
2597 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2598 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2599 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2603 * If this is multipath, check all selected paths for any nexthop change
2605 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2606 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2607 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2608 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2612 /* Nothing has changed from the RIB's perspective. */
2616 struct bgp_process_queue
{
2618 STAILQ_HEAD(, bgp_dest
) pqueue
;
2619 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2621 unsigned int queued
;
2624 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2625 safi_t safi
, struct bgp_dest
*dest
,
2626 struct bgp_path_info
*new_select
,
2627 struct bgp_path_info
*old_select
)
2629 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2631 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2634 if (advertise_type5_routes(bgp
, afi
) && new_select
2635 && is_route_injectable_into_evpn(new_select
)) {
2637 /* apply the route-map */
2638 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2639 route_map_result_t ret
;
2640 struct bgp_path_info rmap_path
;
2641 struct bgp_path_info_extra rmap_path_extra
;
2642 struct attr dummy_attr
;
2644 dummy_attr
= *new_select
->attr
;
2646 /* Fill temp path_info */
2647 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2648 new_select
, new_select
->peer
,
2651 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2653 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2656 if (ret
== RMAP_DENYMATCH
) {
2657 bgp_attr_flush(&dummy_attr
);
2658 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2661 bgp_evpn_advertise_type5_route(
2662 bgp
, p
, &dummy_attr
, afi
, safi
);
2664 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2667 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2668 && is_route_injectable_into_evpn(old_select
))
2669 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2673 * old_select = The old best path
2674 * new_select = the new best path
2676 * if (!old_select && new_select)
2677 * We are sending new information on.
2679 * if (old_select && new_select) {
2680 * if (new_select != old_select)
2681 * We have a new best path send a change
2683 * We've received a update with new attributes that needs
2687 * if (old_select && !new_select)
2688 * We have no eligible route that we can announce or the rn
2691 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2692 afi_t afi
, safi_t safi
)
2694 struct bgp_path_info
*new_select
;
2695 struct bgp_path_info
*old_select
;
2696 struct bgp_path_info_pair old_and_new
;
2699 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2701 debug
= bgp_debug_bestpath(dest
);
2704 "%s: bgp delete in progress, ignoring event, p=%pBD",
2708 /* Is it end of initial update? (after startup) */
2710 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2711 sizeof(bgp
->update_delay_zebra_resume_time
));
2713 bgp
->main_zebra_update_hold
= 0;
2714 FOREACH_AFI_SAFI (afi
, safi
) {
2715 if (bgp_fibupd_safi(safi
))
2716 bgp_zebra_announce_table(bgp
, afi
, safi
);
2718 bgp
->main_peers_update_hold
= 0;
2720 bgp_start_routeadv(bgp
);
2724 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2726 debug
= bgp_debug_bestpath(dest
);
2728 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2729 afi2str(afi
), safi2str(safi
));
2731 /* The best path calculation for the route is deferred if
2732 * BGP_NODE_SELECT_DEFER is set
2734 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2735 if (BGP_DEBUG(update
, UPDATE_OUT
))
2736 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2740 /* Best path selection. */
2741 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2743 old_select
= old_and_new
.old
;
2744 new_select
= old_and_new
.new;
2746 /* Do we need to allocate or free labels?
2747 * Right now, since we only deal with per-prefix labels, it is not
2748 * necessary to do this upon changes to best path. Exceptions:
2749 * - label index has changed -> recalculate resulting label
2750 * - path_info sub_type changed -> switch to/from implicit-null
2751 * - no valid label (due to removed static label binding) -> get new one
2753 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2756 || bgp_label_index_differs(new_select
, old_select
)
2757 || new_select
->sub_type
!= old_select
->sub_type
2758 || !bgp_is_valid_label(&dest
->local_label
)) {
2759 /* Enforced penultimate hop popping:
2760 * implicit-null for local routes, aggregate
2761 * and redistributed routes
2763 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2764 || new_select
->sub_type
2765 == BGP_ROUTE_AGGREGATE
2766 || new_select
->sub_type
2767 == BGP_ROUTE_REDISTRIBUTE
) {
2770 BGP_NODE_REGISTERED_FOR_LABEL
)
2773 BGP_NODE_LABEL_REQUESTED
))
2774 bgp_unregister_for_label(dest
);
2775 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2776 &dest
->local_label
);
2777 bgp_set_valid_label(&dest
->local_label
);
2779 bgp_register_for_label(dest
,
2782 } else if (CHECK_FLAG(dest
->flags
,
2783 BGP_NODE_REGISTERED_FOR_LABEL
)
2784 || CHECK_FLAG(dest
->flags
,
2785 BGP_NODE_LABEL_REQUESTED
)) {
2786 bgp_unregister_for_label(dest
);
2788 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2789 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2790 bgp_unregister_for_label(dest
);
2795 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2796 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2797 old_select
, new_select
);
2799 /* If best route remains the same and this is not due to user-initiated
2800 * clear, see exactly what needs to be done.
2802 if (old_select
&& old_select
== new_select
2803 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2804 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2805 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2806 if (bgp_zebra_has_route_changed(old_select
)) {
2807 #ifdef ENABLE_BGP_VNC
2808 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2809 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2811 if (bgp_fibupd_safi(safi
)
2812 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2814 if (new_select
->type
== ZEBRA_ROUTE_BGP
2815 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2816 || new_select
->sub_type
2817 == BGP_ROUTE_IMPORTED
))
2819 bgp_zebra_announce(dest
, p
, old_select
,
2824 /* If there is a change of interest to peers, reannounce the
2826 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2827 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2828 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2829 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2831 /* unicast routes must also be annouced to
2832 * labeled-unicast update-groups */
2833 if (safi
== SAFI_UNICAST
)
2834 group_announce_route(bgp
, afi
,
2835 SAFI_LABELED_UNICAST
, dest
,
2838 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2839 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2842 /* advertise/withdraw type-5 routes */
2843 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2844 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2845 bgp_process_evpn_route_injection(
2846 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2848 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2849 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2850 bgp_zebra_clear_route_change_flags(dest
);
2851 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2855 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2857 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2859 /* bestpath has changed; bump version */
2860 if (old_select
|| new_select
) {
2861 bgp_bump_version(dest
);
2863 if (!bgp
->t_rmap_def_originate_eval
) {
2867 update_group_refresh_default_originate_route_map
,
2868 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2869 &bgp
->t_rmap_def_originate_eval
);
2874 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2877 zlog_debug("%s: setting SELECTED flag", __func__
);
2878 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2879 bgp_path_info_unset_flag(dest
, new_select
,
2880 BGP_PATH_ATTR_CHANGED
);
2881 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2882 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2885 #ifdef ENABLE_BGP_VNC
2886 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2887 if (old_select
!= new_select
) {
2889 vnc_import_bgp_exterior_del_route(bgp
, p
,
2891 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2894 vnc_import_bgp_exterior_add_route(bgp
, p
,
2896 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2902 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2904 /* unicast routes must also be annouced to labeled-unicast update-groups
2906 if (safi
== SAFI_UNICAST
)
2907 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2911 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2912 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2913 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2914 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2915 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2916 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2918 /* if this is an evpn imported type-5 prefix,
2919 * we need to withdraw the route first to clear
2920 * the nh neigh and the RMAC entry.
2923 is_route_parent_evpn(old_select
))
2924 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2926 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2928 /* Withdraw the route from the kernel. */
2929 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2930 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2931 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2932 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2934 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2938 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2941 /* Clear any route change flags. */
2942 bgp_zebra_clear_route_change_flags(dest
);
2944 /* Reap old select bgp_path_info, if it has been removed */
2945 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2946 bgp_path_info_reap(dest
, old_select
);
2948 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2952 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2953 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2955 struct bgp_dest
*dest
;
2957 struct afi_safi_info
*thread_info
;
2959 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
2960 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
2962 thread_info
= THREAD_ARG(t
);
2963 XFREE(MTYPE_TMP
, thread_info
);
2964 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2967 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2968 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2969 get_afi_safi_str(afi
, safi
, false),
2970 bgp
->gr_info
[afi
][safi
].gr_deferred
);
2973 /* Process the route list */
2974 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
2975 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
2976 dest
= bgp_route_next(dest
)) {
2977 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
2980 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2981 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
2982 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2984 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
2985 bgp_dest_unlock_node(dest
);
2990 /* Send EOR message when all routes are processed */
2991 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
2992 bgp_send_delayed_eor(bgp
);
2993 /* Send route processing complete message to RIB */
2994 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2995 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2999 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3001 thread_info
->afi
= afi
;
3002 thread_info
->safi
= safi
;
3003 thread_info
->bgp
= bgp
;
3005 /* If there are more routes to be processed, start the
3008 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3009 BGP_ROUTE_SELECT_DELAY
,
3010 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3014 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3016 struct bgp_process_queue
*pqnode
= data
;
3017 struct bgp
*bgp
= pqnode
->bgp
;
3018 struct bgp_table
*table
;
3019 struct bgp_dest
*dest
;
3022 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3023 bgp_process_main_one(bgp
, NULL
, 0, 0);
3024 /* should always have dedicated wq call */
3025 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3029 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3030 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3031 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3032 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3033 table
= bgp_dest_table(dest
);
3034 /* note, new DESTs may be added as part of processing */
3035 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3037 bgp_dest_unlock_node(dest
);
3038 bgp_table_unlock(table
);
3044 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3046 struct bgp_process_queue
*pqnode
= data
;
3048 bgp_unlock(pqnode
->bgp
);
3050 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3053 void bgp_process_queue_init(struct bgp
*bgp
)
3055 if (!bgp
->process_queue
) {
3058 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3059 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3062 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3063 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3064 bgp
->process_queue
->spec
.max_retries
= 0;
3065 bgp
->process_queue
->spec
.hold
= 50;
3066 /* Use a higher yield value of 50ms for main queue processing */
3067 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3070 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3072 struct bgp_process_queue
*pqnode
;
3074 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3075 sizeof(struct bgp_process_queue
));
3077 /* unlocked in bgp_processq_del */
3078 pqnode
->bgp
= bgp_lock(bgp
);
3079 STAILQ_INIT(&pqnode
->pqueue
);
3084 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3086 #define ARBITRARY_PROCESS_QLEN 10000
3087 struct work_queue
*wq
= bgp
->process_queue
;
3088 struct bgp_process_queue
*pqnode
;
3089 int pqnode_reuse
= 0;
3091 /* already scheduled for processing? */
3092 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3095 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3098 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3099 if (BGP_DEBUG(update
, UPDATE_OUT
))
3100 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3108 /* Add route nodes to an existing work queue item until reaching the
3109 limit only if is from the same BGP view and it's not an EOIU marker
3111 if (work_queue_item_count(wq
)) {
3112 struct work_queue_item
*item
= work_queue_last_item(wq
);
3113 pqnode
= item
->data
;
3115 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3116 || pqnode
->bgp
!= bgp
3117 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3118 pqnode
= bgp_processq_alloc(bgp
);
3122 pqnode
= bgp_processq_alloc(bgp
);
3123 /* all unlocked in bgp_process_wq */
3124 bgp_table_lock(bgp_dest_table(dest
));
3126 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3127 bgp_dest_lock_node(dest
);
3129 /* can't be enqueued twice */
3130 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3131 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3135 work_queue_add(wq
, pqnode
);
3140 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3142 struct bgp_process_queue
*pqnode
;
3144 if (bgp
->process_queue
== NULL
)
3147 pqnode
= bgp_processq_alloc(bgp
);
3149 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3150 work_queue_add(bgp
->process_queue
, pqnode
);
3153 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3157 peer
= THREAD_ARG(thread
);
3158 peer
->t_pmax_restart
= NULL
;
3160 if (bgp_debug_neighbor_events(peer
))
3162 "%s Maximum-prefix restart timer expired, restore peering",
3165 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3166 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3171 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3175 bool filtered
= false;
3176 struct bgp_dest
*dest
;
3177 struct bgp_adj_in
*ain
;
3178 struct attr attr
= {};
3179 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3181 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3182 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3183 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3187 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3191 if (bgp_input_modifier(
3192 peer
, rn_p
, &attr
, afi
, safi
,
3193 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3201 bgp_attr_undup(&attr
, ain
->attr
);
3208 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3212 iana_safi_t pkt_safi
;
3213 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3214 PEER_FLAG_MAX_PREFIX_FORCE
))
3215 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3216 + peer
->pcount
[afi
][safi
]
3217 : peer
->pcount
[afi
][safi
];
3219 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3222 if (pcount
> peer
->pmax
[afi
][safi
]) {
3223 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3224 PEER_STATUS_PREFIX_LIMIT
)
3229 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3230 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3231 peer
->pmax
[afi
][safi
]);
3232 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3234 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3235 PEER_FLAG_MAX_PREFIX_WARNING
))
3238 /* Convert AFI, SAFI to values for packet. */
3239 pkt_afi
= afi_int2iana(afi
);
3240 pkt_safi
= safi_int2iana(safi
);
3244 ndata
[0] = (pkt_afi
>> 8);
3246 ndata
[2] = pkt_safi
;
3247 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3248 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3249 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3250 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3252 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3253 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3254 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3258 /* Dynamic peers will just close their connection. */
3259 if (peer_dynamic_neighbor(peer
))
3262 /* restart timer start */
3263 if (peer
->pmax_restart
[afi
][safi
]) {
3264 peer
->v_pmax_restart
=
3265 peer
->pmax_restart
[afi
][safi
] * 60;
3267 if (bgp_debug_neighbor_events(peer
))
3269 "%s Maximum-prefix restart timer started for %d secs",
3270 peer
->host
, peer
->v_pmax_restart
);
3272 BGP_TIMER_ON(peer
->t_pmax_restart
,
3273 bgp_maximum_prefix_restart_timer
,
3274 peer
->v_pmax_restart
);
3279 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3280 PEER_STATUS_PREFIX_LIMIT
);
3283 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3284 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3285 PEER_STATUS_PREFIX_THRESHOLD
)
3290 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3291 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3292 peer
->pmax
[afi
][safi
]);
3293 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3294 PEER_STATUS_PREFIX_THRESHOLD
);
3296 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3297 PEER_STATUS_PREFIX_THRESHOLD
);
3301 /* Unconditionally remove the route from the RIB, without taking
3302 * damping into consideration (eg, because the session went down)
3304 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3305 struct peer
*peer
, afi_t afi
, safi_t safi
)
3308 struct bgp
*bgp
= NULL
;
3309 bool delete_route
= false;
3311 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3314 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3315 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3317 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3320 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3321 delete_route
= true;
3322 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3323 delete_route
= true;
3325 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3326 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3327 bgp
= pi
->peer
->bgp
;
3328 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3333 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3334 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3337 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3338 struct peer
*peer
, afi_t afi
, safi_t safi
,
3339 struct prefix_rd
*prd
)
3341 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3343 /* apply dampening, if result is suppressed, we'll be retaining
3344 * the bgp_path_info in the RIB for historical reference.
3346 if (peer
->sort
== BGP_PEER_EBGP
) {
3347 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3348 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3349 == BGP_DAMP_SUPPRESSED
) {
3350 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3357 #ifdef ENABLE_BGP_VNC
3358 if (safi
== SAFI_MPLS_VPN
) {
3359 struct bgp_dest
*pdest
= NULL
;
3360 struct bgp_table
*table
= NULL
;
3362 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3363 (struct prefix
*)prd
);
3364 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3365 table
= bgp_dest_get_bgp_table_info(pdest
);
3367 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3368 peer
->bgp
, prd
, table
, p
, pi
);
3370 bgp_dest_unlock_node(pdest
);
3372 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3373 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3375 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3376 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3381 /* If this is an EVPN route, process for un-import. */
3382 if (safi
== SAFI_EVPN
)
3383 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3385 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3388 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3389 struct peer
*peer
, struct attr
*attr
,
3390 struct bgp_dest
*dest
)
3392 struct bgp_path_info
*new;
3394 /* Make new BGP info. */
3395 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3397 new->instance
= instance
;
3398 new->sub_type
= sub_type
;
3401 new->uptime
= bgp_clock();
3406 static void overlay_index_update(struct attr
*attr
,
3407 union gw_addr
*gw_ip
)
3411 if (gw_ip
== NULL
) {
3412 struct bgp_route_evpn eo
;
3414 memset(&eo
, 0, sizeof(eo
));
3415 bgp_attr_set_evpn_overlay(attr
, &eo
);
3417 struct bgp_route_evpn eo
= {.gw_ip
= *gw_ip
};
3419 bgp_attr_set_evpn_overlay(attr
, &eo
);
3423 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3424 union gw_addr
*gw_ip
)
3426 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3427 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3433 if (afi
!= AFI_L2VPN
)
3436 path_gw_ip
= eo
->gw_ip
;
3438 if (gw_ip
== NULL
) {
3439 memset(&temp
, 0, sizeof(temp
));
3440 path_gw_ip_remote
= &temp
.ip
;
3442 path_gw_ip_remote
= gw_ip
;
3444 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3447 /* Check if received nexthop is valid or not. */
3448 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3449 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3450 struct bgp_dest
*dest
)
3453 bool is_bgp_static_route
=
3454 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3458 * Only validated for unicast and multicast currently.
3459 * Also valid for EVPN where the nexthop is an IP address.
3460 * If we are a bgp static route being checked then there is
3461 * no need to check to see if the nexthop is martian as
3462 * that it should be ok.
3464 if (is_bgp_static_route
||
3465 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3468 /* If NEXT_HOP is present, validate it. */
3469 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3470 if (attr
->nexthop
.s_addr
== INADDR_ANY
3471 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3472 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3476 /* If MP_NEXTHOP is present, validate it. */
3477 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3478 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3479 * it is not an IPv6 link-local address.
3481 * If we receive an UPDATE with nexthop length set to 32 bytes
3482 * we shouldn't discard an UPDATE if it's set to (::).
3483 * The link-local (2st) is validated along the code path later.
3485 if (attr
->mp_nexthop_len
) {
3486 switch (attr
->mp_nexthop_len
) {
3487 case BGP_ATTR_NHLEN_IPV4
:
3488 case BGP_ATTR_NHLEN_VPNV4
:
3489 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3491 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3492 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3496 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3497 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3498 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3499 &attr
->mp_nexthop_global
)
3500 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3501 || IN6_IS_ADDR_MULTICAST(
3502 &attr
->mp_nexthop_global
)
3503 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3506 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3507 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3508 || IN6_IS_ADDR_MULTICAST(
3509 &attr
->mp_nexthop_global
)
3510 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3523 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3525 struct community
*old
;
3526 struct community
*new;
3527 struct community
*merge
;
3528 struct community
*no_export
;
3530 old
= attr
->community
;
3531 no_export
= community_str2com("no-export");
3536 merge
= community_merge(community_dup(old
), no_export
);
3539 community_free(&old
);
3541 new = community_uniq_sort(merge
);
3542 community_free(&merge
);
3544 new = community_dup(no_export
);
3547 community_free(&no_export
);
3549 attr
->community
= new;
3550 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3553 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3554 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3555 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3556 uint32_t num_labels
, int soft_reconfig
,
3557 struct bgp_route_evpn
*evpn
)
3560 int aspath_loop_count
= 0;
3561 struct bgp_dest
*dest
;
3563 struct attr new_attr
;
3564 struct attr
*attr_new
;
3565 struct bgp_path_info
*pi
;
3566 struct bgp_path_info
*new;
3567 struct bgp_path_info_extra
*extra
;
3569 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3571 int do_loop_check
= 1;
3572 int has_valid_label
= 0;
3574 uint8_t pi_type
= 0;
3575 uint8_t pi_sub_type
= 0;
3577 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3578 char pfxprint
[PREFIX2STR_BUFFER
];
3580 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3581 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3585 #ifdef ENABLE_BGP_VNC
3586 int vnc_implicit_withdraw
= 0;
3590 memset(&new_attr
, 0, sizeof(struct attr
));
3591 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3592 new_attr
.label
= MPLS_INVALID_LABEL
;
3595 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3596 /* TODO: Check to see if we can get rid of "is_valid_label" */
3597 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3598 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3600 has_valid_label
= bgp_is_valid_label(label
);
3602 if (has_valid_label
)
3603 assert(label
!= NULL
);
3605 /* When peer's soft reconfiguration enabled. Record input packet in
3608 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3609 && peer
!= bgp
->peer_self
)
3610 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3612 /* Check previously received route. */
3613 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3614 if (pi
->peer
== peer
&& pi
->type
== type
3615 && pi
->sub_type
== sub_type
3616 && pi
->addpath_rx_id
== addpath_id
)
3619 /* AS path local-as loop check. */
3620 if (peer
->change_local_as
) {
3621 if (peer
->allowas_in
[afi
][safi
])
3622 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3623 else if (!CHECK_FLAG(peer
->flags
,
3624 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3625 aspath_loop_count
= 1;
3627 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3628 > aspath_loop_count
) {
3629 peer
->stat_pfx_aspath_loop
++;
3630 reason
= "as-path contains our own AS A;";
3635 /* If the peer is configured for "allowas-in origin" and the last ASN in
3637 * as-path is our ASN then we do not need to call aspath_loop_check
3639 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3640 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3643 /* AS path loop check. */
3644 if (do_loop_check
) {
3645 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3646 > peer
->allowas_in
[afi
][safi
]
3647 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3648 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3649 > peer
->allowas_in
[afi
][safi
])) {
3650 peer
->stat_pfx_aspath_loop
++;
3651 reason
= "as-path contains our own AS;";
3656 /* Route reflector originator ID check. */
3657 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3658 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3659 peer
->stat_pfx_originator_loop
++;
3660 reason
= "originator is us;";
3664 /* Route reflector cluster ID check. */
3665 if (bgp_cluster_filter(peer
, attr
)) {
3666 peer
->stat_pfx_cluster_loop
++;
3667 reason
= "reflected from the same cluster;";
3671 /* Apply incoming filter. */
3672 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3673 peer
->stat_pfx_filter
++;
3678 /* RFC 8212 to prevent route leaks.
3679 * This specification intends to improve this situation by requiring the
3680 * explicit configuration of both BGP Import and Export Policies for any
3681 * External BGP (EBGP) session such as customers, peers, or
3682 * confederation boundaries for all enabled address families. Through
3683 * codification of the aforementioned requirement, operators will
3684 * benefit from consistent behavior across different BGP
3687 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3688 if (!bgp_inbound_policy_exists(peer
,
3689 &peer
->filter
[afi
][safi
])) {
3690 reason
= "inbound policy missing";
3694 /* draft-ietf-idr-deprecate-as-set-confed-set
3695 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3696 * Eventually, This document (if approved) updates RFC 4271
3697 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3698 * and obsoletes RFC 6472.
3700 if (peer
->bgp
->reject_as_sets
)
3701 if (aspath_check_as_sets(attr
->aspath
)) {
3703 "as-path contains AS_SET or AS_CONFED_SET type;";
3709 /* Apply incoming route-map.
3710 * NB: new_attr may now contain newly allocated values from route-map
3712 * commands, so we need bgp_attr_flush in the error paths, until we
3714 * the attr (which takes over the memory references) */
3715 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3718 peer
->stat_pfx_filter
++;
3719 reason
= "route-map;";
3720 bgp_attr_flush(&new_attr
);
3724 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3725 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3726 /* remove from RIB previous entry */
3727 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3730 if (peer
->sort
== BGP_PEER_EBGP
) {
3733 * A BGP speaker receiving an announcement tagged with the
3734 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3735 * NO_EXPORT community as defined in RFC1997, or a
3736 * similar community, to prevent propagation of the
3737 * prefix outside the local AS. The community to prevent
3738 * propagation SHOULD be chosen according to the operator's
3741 if (new_attr
.community
3742 && community_include(new_attr
.community
,
3743 COMMUNITY_BLACKHOLE
))
3744 bgp_attr_add_no_export_community(&new_attr
);
3746 /* If we receive the graceful-shutdown community from an eBGP
3747 * peer we must lower local-preference */
3748 if (new_attr
.community
3749 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3750 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3751 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3753 /* If graceful-shutdown is configured then add the GSHUT
3754 * community to all paths received from eBGP peers */
3755 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3756 bgp_attr_add_gshut_community(&new_attr
);
3761 pi_sub_type
= pi
->sub_type
;
3764 /* next hop check. */
3765 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3766 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3768 peer
->stat_pfx_nh_invalid
++;
3769 reason
= "martian or self next-hop;";
3770 bgp_attr_flush(&new_attr
);
3774 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3775 peer
->stat_pfx_nh_invalid
++;
3776 reason
= "self mac;";
3780 /* Update Overlay Index */
3781 if (afi
== AFI_L2VPN
) {
3782 overlay_index_update(&new_attr
,
3783 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3786 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3788 * Suppress fib is enabled
3789 * BGP_OPT_NO_FIB is not enabled
3790 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3791 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3793 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3794 && (sub_type
== BGP_ROUTE_NORMAL
)
3795 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3796 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3797 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3799 attr_new
= bgp_attr_intern(&new_attr
);
3801 /* If maximum prefix count is configured and current prefix
3804 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3807 /* If the update is implicit withdraw. */
3809 pi
->uptime
= bgp_clock();
3810 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3812 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3814 /* Same attribute comes in. */
3815 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3817 && (!has_valid_label
3818 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3819 num_labels
* sizeof(mpls_label_t
))
3821 && (overlay_index_equal(
3823 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3824 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3825 && peer
->sort
== BGP_PEER_EBGP
3826 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3827 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3828 bgp_debug_rdpfxpath2str(
3829 afi
, safi
, prd
, p
, label
,
3830 num_labels
, addpath_id
? 1 : 0,
3831 addpath_id
, pfx_buf
,
3833 zlog_debug("%s rcvd %s", peer
->host
,
3837 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3838 != BGP_DAMP_SUPPRESSED
) {
3839 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3841 bgp_process(bgp
, dest
, afi
, safi
);
3843 } else /* Duplicate - odd */
3845 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3846 if (!peer
->rcvd_attr_printed
) {
3848 "%s rcvd UPDATE w/ attr: %s",
3850 peer
->rcvd_attr_str
);
3851 peer
->rcvd_attr_printed
= 1;
3854 bgp_debug_rdpfxpath2str(
3855 afi
, safi
, prd
, p
, label
,
3856 num_labels
, addpath_id
? 1 : 0,
3857 addpath_id
, pfx_buf
,
3860 "%s rcvd %s...duplicate ignored",
3861 peer
->host
, pfx_buf
);
3864 /* graceful restart STALE flag unset. */
3865 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3866 bgp_path_info_unset_flag(
3867 dest
, pi
, BGP_PATH_STALE
);
3868 bgp_dest_set_defer_flag(dest
, false);
3869 bgp_process(bgp
, dest
, afi
, safi
);
3873 bgp_dest_unlock_node(dest
);
3874 bgp_attr_unintern(&attr_new
);
3879 /* Withdraw/Announce before we fully processed the withdraw */
3880 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3881 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3882 bgp_debug_rdpfxpath2str(
3883 afi
, safi
, prd
, p
, label
, num_labels
,
3884 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3887 "%s rcvd %s, flapped quicker than processing",
3888 peer
->host
, pfx_buf
);
3891 bgp_path_info_restore(dest
, pi
);
3894 /* Received Logging. */
3895 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3896 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3897 num_labels
, addpath_id
? 1 : 0,
3898 addpath_id
, pfx_buf
,
3900 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3903 /* graceful restart STALE flag unset. */
3904 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3905 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3906 bgp_dest_set_defer_flag(dest
, false);
3909 /* The attribute is changed. */
3910 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3912 /* implicit withdraw, decrement aggregate and pcount here.
3913 * only if update is accepted, they'll increment below.
3915 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3917 /* Update bgp route dampening information. */
3918 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3919 && peer
->sort
== BGP_PEER_EBGP
) {
3920 /* This is implicit withdraw so we should update
3921 * dampening information.
3923 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3924 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3926 #ifdef ENABLE_BGP_VNC
3927 if (safi
== SAFI_MPLS_VPN
) {
3928 struct bgp_dest
*pdest
= NULL
;
3929 struct bgp_table
*table
= NULL
;
3931 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3932 (struct prefix
*)prd
);
3933 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3934 table
= bgp_dest_get_bgp_table_info(pdest
);
3936 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3937 bgp
, prd
, table
, p
, pi
);
3939 bgp_dest_unlock_node(pdest
);
3941 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3942 && (safi
== SAFI_UNICAST
)) {
3943 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3945 * Implicit withdraw case.
3947 ++vnc_implicit_withdraw
;
3948 vnc_import_bgp_del_route(bgp
, p
, pi
);
3949 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3954 /* Special handling for EVPN update of an existing route. If the
3955 * extended community attribute has changed, we need to
3957 * the route using its existing extended community. It will be
3958 * subsequently processed for import with the new extended
3961 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3964 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3966 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3969 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3970 attr_new
->ecommunity
);
3972 if (bgp_debug_update(peer
, p
, NULL
, 1))
3974 "Change in EXT-COMM, existing %s new %s",
3976 pi
->attr
->ecommunity
),
3978 attr_new
->ecommunity
));
3979 if (safi
== SAFI_EVPN
)
3980 bgp_evpn_unimport_route(
3981 bgp
, afi
, safi
, p
, pi
);
3982 else /* SAFI_MPLS_VPN */
3983 vpn_leak_to_vrf_withdraw(bgp
,
3989 /* Update to new attribute. */
3990 bgp_attr_unintern(&pi
->attr
);
3991 pi
->attr
= attr_new
;
3993 /* Update MPLS label */
3994 if (has_valid_label
) {
3995 extra
= bgp_path_info_extra_get(pi
);
3996 if (extra
->label
!= label
) {
3997 memcpy(&extra
->label
, label
,
3998 num_labels
* sizeof(mpls_label_t
));
3999 extra
->num_labels
= num_labels
;
4001 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4002 bgp_set_valid_label(&extra
->label
[0]);
4005 /* Update SRv6 SID */
4006 if (attr
->srv6_l3vpn
) {
4007 extra
= bgp_path_info_extra_get(pi
);
4008 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4009 sid_copy(&extra
->sid
[0],
4010 &attr
->srv6_l3vpn
->sid
);
4011 extra
->num_sids
= 1;
4013 } else if (attr
->srv6_vpn
) {
4014 extra
= bgp_path_info_extra_get(pi
);
4015 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4016 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4017 extra
->num_sids
= 1;
4021 #ifdef ENABLE_BGP_VNC
4022 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4023 && (safi
== SAFI_UNICAST
)) {
4024 if (vnc_implicit_withdraw
) {
4026 * Add back the route with its new attributes
4028 * The route is still selected, until the route
4030 * queued by bgp_process actually runs. We have
4032 * update to the VNC side immediately to avoid
4034 * configuration changes (e.g., route-map
4036 * trigger re-importation of the entire RIB.
4038 vnc_import_bgp_add_route(bgp
, p
, pi
);
4039 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4044 /* Update bgp route dampening information. */
4045 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4046 && peer
->sort
== BGP_PEER_EBGP
) {
4047 /* Now we do normal update dampening. */
4048 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4049 if (ret
== BGP_DAMP_SUPPRESSED
) {
4050 bgp_dest_unlock_node(dest
);
4055 /* Nexthop reachability check - for unicast and
4056 * labeled-unicast.. */
4057 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4058 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4059 || (safi
== SAFI_EVPN
&&
4060 bgp_evpn_is_prefix_nht_supported(p
))) {
4061 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4062 && peer
->ttl
== BGP_DEFAULT_TTL
4063 && !CHECK_FLAG(peer
->flags
,
4064 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4065 && !CHECK_FLAG(bgp
->flags
,
4066 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4071 struct bgp
*bgp_nexthop
= bgp
;
4073 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4074 bgp_nexthop
= pi
->extra
->bgp_orig
;
4076 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4078 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4079 safi
, pi
, NULL
, connected
)
4080 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4081 bgp_path_info_set_flag(dest
, pi
,
4084 if (BGP_DEBUG(nht
, NHT
)) {
4085 zlog_debug("%s(%pI4): NH unresolved",
4087 (in_addr_t
*)&attr_new
->nexthop
);
4089 bgp_path_info_unset_flag(dest
, pi
,
4093 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4095 #ifdef ENABLE_BGP_VNC
4096 if (safi
== SAFI_MPLS_VPN
) {
4097 struct bgp_dest
*pdest
= NULL
;
4098 struct bgp_table
*table
= NULL
;
4100 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4101 (struct prefix
*)prd
);
4102 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4103 table
= bgp_dest_get_bgp_table_info(pdest
);
4105 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4106 bgp
, prd
, table
, p
, pi
);
4108 bgp_dest_unlock_node(pdest
);
4112 /* If this is an EVPN route and some attribute has changed,
4114 * route for import. If the extended community has changed, we
4116 * have done the un-import earlier and the import would result
4118 * route getting injected into appropriate L2 VNIs. If it is
4120 * some other attribute change, the import will result in
4122 * the attributes for the route in the VNI(s).
4124 if (safi
== SAFI_EVPN
&& !same_attr
&&
4125 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4126 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4128 /* Process change. */
4129 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4131 bgp_process(bgp
, dest
, afi
, safi
);
4132 bgp_dest_unlock_node(dest
);
4134 if (SAFI_UNICAST
== safi
4135 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4136 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4138 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4140 if ((SAFI_MPLS_VPN
== safi
)
4141 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4143 vpn_leak_to_vrf_update(bgp
, pi
);
4146 #ifdef ENABLE_BGP_VNC
4147 if (SAFI_MPLS_VPN
== safi
) {
4148 mpls_label_t label_decoded
= decode_label(label
);
4150 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4151 type
, sub_type
, &label_decoded
);
4153 if (SAFI_ENCAP
== safi
) {
4154 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4155 type
, sub_type
, NULL
);
4160 } // End of implicit withdraw
4162 /* Received Logging. */
4163 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4164 if (!peer
->rcvd_attr_printed
) {
4165 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4166 peer
->rcvd_attr_str
);
4167 peer
->rcvd_attr_printed
= 1;
4170 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4171 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4173 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4176 /* Make new BGP info. */
4177 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4179 /* Update MPLS label */
4180 if (has_valid_label
) {
4181 extra
= bgp_path_info_extra_get(new);
4182 if (extra
->label
!= label
) {
4183 memcpy(&extra
->label
, label
,
4184 num_labels
* sizeof(mpls_label_t
));
4185 extra
->num_labels
= num_labels
;
4187 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4188 bgp_set_valid_label(&extra
->label
[0]);
4191 /* Update SRv6 SID */
4192 if (safi
== SAFI_MPLS_VPN
) {
4193 extra
= bgp_path_info_extra_get(new);
4194 if (attr
->srv6_l3vpn
) {
4195 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4196 extra
->num_sids
= 1;
4197 } else if (attr
->srv6_vpn
) {
4198 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4199 extra
->num_sids
= 1;
4203 /* Update Overlay Index */
4204 if (afi
== AFI_L2VPN
) {
4205 overlay_index_update(new->attr
,
4206 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4208 /* Nexthop reachability check. */
4209 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4210 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4211 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4212 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4213 && peer
->ttl
== BGP_DEFAULT_TTL
4214 && !CHECK_FLAG(peer
->flags
,
4215 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4216 && !CHECK_FLAG(bgp
->flags
,
4217 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4222 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4224 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4226 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4227 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4229 if (BGP_DEBUG(nht
, NHT
)) {
4230 char buf1
[INET6_ADDRSTRLEN
];
4232 (const void *)&attr_new
->nexthop
,
4233 buf1
, INET6_ADDRSTRLEN
);
4234 zlog_debug("%s(%s): NH unresolved", __func__
,
4237 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4240 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4243 new->addpath_rx_id
= addpath_id
;
4245 /* Increment prefix */
4246 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4248 /* Register new BGP information. */
4249 bgp_path_info_add(dest
, new);
4251 /* route_node_get lock */
4252 bgp_dest_unlock_node(dest
);
4254 #ifdef ENABLE_BGP_VNC
4255 if (safi
== SAFI_MPLS_VPN
) {
4256 struct bgp_dest
*pdest
= NULL
;
4257 struct bgp_table
*table
= NULL
;
4259 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4260 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4261 table
= bgp_dest_get_bgp_table_info(pdest
);
4263 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4264 bgp
, prd
, table
, p
, new);
4266 bgp_dest_unlock_node(pdest
);
4270 /* If this is an EVPN route, process for import. */
4271 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4272 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4274 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4276 /* Process change. */
4277 bgp_process(bgp
, dest
, afi
, safi
);
4279 if (SAFI_UNICAST
== safi
4280 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4281 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4282 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4284 if ((SAFI_MPLS_VPN
== safi
)
4285 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4287 vpn_leak_to_vrf_update(bgp
, new);
4289 #ifdef ENABLE_BGP_VNC
4290 if (SAFI_MPLS_VPN
== safi
) {
4291 mpls_label_t label_decoded
= decode_label(label
);
4293 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4294 sub_type
, &label_decoded
);
4296 if (SAFI_ENCAP
== safi
) {
4297 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4304 /* This BGP update is filtered. Log the reason then update BGP
4307 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4309 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4310 if (!peer
->rcvd_attr_printed
) {
4311 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4312 peer
->rcvd_attr_str
);
4313 peer
->rcvd_attr_printed
= 1;
4316 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4317 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4319 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4320 peer
->host
, pfx_buf
, reason
);
4324 /* If this is an EVPN route, un-import it as it is now filtered.
4326 if (safi
== SAFI_EVPN
)
4327 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4329 if (SAFI_UNICAST
== safi
4330 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4331 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4333 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4335 if ((SAFI_MPLS_VPN
== safi
)
4336 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4338 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4341 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4344 bgp_dest_unlock_node(dest
);
4346 #ifdef ENABLE_BGP_VNC
4348 * Filtered update is treated as an implicit withdrawal (see
4350 * a few lines above)
4352 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4353 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4361 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4362 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4363 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4364 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4367 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4368 struct bgp_dest
*dest
;
4369 struct bgp_path_info
*pi
;
4371 #ifdef ENABLE_BGP_VNC
4372 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4373 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4381 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4383 /* If peer is soft reconfiguration enabled. Record input packet for
4384 * further calculation.
4386 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4387 * routes that are filtered. This tanks out Quagga RS pretty badly due
4389 * the iteration over all RS clients.
4390 * Since we need to remove the entry from adj_in anyway, do that first
4392 * if there was no entry, we don't need to do anything more.
4394 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4395 && peer
!= bgp
->peer_self
)
4396 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4397 peer
->stat_pfx_dup_withdraw
++;
4399 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4400 bgp_debug_rdpfxpath2str(
4401 afi
, safi
, prd
, p
, label
, num_labels
,
4402 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4405 "%s withdrawing route %s not in adj-in",
4406 peer
->host
, pfx_buf
);
4408 bgp_dest_unlock_node(dest
);
4412 /* Lookup withdrawn route. */
4413 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4414 if (pi
->peer
== peer
&& pi
->type
== type
4415 && pi
->sub_type
== sub_type
4416 && pi
->addpath_rx_id
== addpath_id
)
4420 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4421 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4422 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4424 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4428 /* Withdraw specified route from routing table. */
4429 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4430 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4431 if (SAFI_UNICAST
== safi
4432 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4433 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4434 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4436 if ((SAFI_MPLS_VPN
== safi
)
4437 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4439 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4441 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4442 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4443 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4445 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4448 /* Unlock bgp_node_get() lock. */
4449 bgp_dest_unlock_node(dest
);
4454 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4457 struct update_subgroup
*subgrp
;
4458 subgrp
= peer_subgroup(peer
, afi
, safi
);
4459 subgroup_default_originate(subgrp
, withdraw
);
4464 * bgp_stop_announce_route_timer
4466 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4468 if (!paf
->t_announce_route
)
4471 thread_cancel(&paf
->t_announce_route
);
4475 * bgp_announce_route_timer_expired
4477 * Callback that is invoked when the route announcement timer for a
4480 static int bgp_announce_route_timer_expired(struct thread
*t
)
4482 struct peer_af
*paf
;
4485 paf
= THREAD_ARG(t
);
4488 if (peer
->status
!= Established
)
4491 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4494 peer_af_announce_route(paf
, 1);
4496 /* Notify BGP conditional advertisement scanner percess */
4497 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4503 * bgp_announce_route
4505 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4507 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4509 struct peer_af
*paf
;
4510 struct update_subgroup
*subgrp
;
4512 paf
= peer_af_find(peer
, afi
, safi
);
4515 subgrp
= PAF_SUBGRP(paf
);
4518 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4519 * or a refresh has already been triggered.
4521 if (!subgrp
|| paf
->t_announce_route
)
4525 * Start a timer to stagger/delay the announce. This serves
4526 * two purposes - announcement can potentially be combined for
4527 * multiple peers and the announcement doesn't happen in the
4530 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4531 (subgrp
->peer_count
== 1)
4532 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4533 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4534 &paf
->t_announce_route
);
4538 * Announce routes from all AF tables to a peer.
4540 * This should ONLY be called when there is a need to refresh the
4541 * routes to the peer based on a policy change for this peer alone
4542 * or a route refresh request received from the peer.
4543 * The operation will result in splitting the peer from its existing
4544 * subgroups and putting it in new subgroups.
4546 void bgp_announce_route_all(struct peer
*peer
)
4551 FOREACH_AFI_SAFI (afi
, safi
)
4552 bgp_announce_route(peer
, afi
, safi
);
4555 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4556 struct bgp_table
*table
,
4557 struct prefix_rd
*prd
)
4560 struct bgp_dest
*dest
;
4561 struct bgp_adj_in
*ain
;
4564 table
= peer
->bgp
->rib
[afi
][safi
];
4566 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4567 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4568 if (ain
->peer
!= peer
)
4571 struct bgp_path_info
*pi
;
4572 uint32_t num_labels
= 0;
4573 mpls_label_t
*label_pnt
= NULL
;
4574 struct bgp_route_evpn evpn
;
4576 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4578 if (pi
->peer
== peer
)
4581 if (pi
&& pi
->extra
)
4582 num_labels
= pi
->extra
->num_labels
;
4584 label_pnt
= &pi
->extra
->label
[0];
4587 bgp_attr_get_evpn_overlay(pi
->attr
),
4590 memset(&evpn
, 0, sizeof(evpn
));
4592 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4593 ain
->addpath_rx_id
, ain
->attr
, afi
,
4594 safi
, ZEBRA_ROUTE_BGP
,
4595 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4596 num_labels
, 1, &evpn
);
4599 bgp_dest_unlock_node(dest
);
4605 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4607 struct bgp_dest
*dest
;
4608 struct bgp_table
*table
;
4610 if (peer
->status
!= Established
)
4613 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4614 && (safi
!= SAFI_EVPN
))
4615 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4617 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4618 dest
= bgp_route_next(dest
)) {
4619 table
= bgp_dest_get_bgp_table_info(dest
);
4624 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4625 struct prefix_rd prd
;
4627 prd
.family
= AF_UNSPEC
;
4629 memcpy(&prd
.val
, p
->u
.val
, 8);
4631 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4636 struct bgp_clear_node_queue
{
4637 struct bgp_dest
*dest
;
4640 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4642 struct bgp_clear_node_queue
*cnq
= data
;
4643 struct bgp_dest
*dest
= cnq
->dest
;
4644 struct peer
*peer
= wq
->spec
.data
;
4645 struct bgp_path_info
*pi
;
4647 afi_t afi
= bgp_dest_table(dest
)->afi
;
4648 safi_t safi
= bgp_dest_table(dest
)->safi
;
4650 assert(dest
&& peer
);
4653 /* It is possible that we have multiple paths for a prefix from a peer
4654 * if that peer is using AddPath.
4656 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4657 if (pi
->peer
!= peer
)
4660 /* graceful restart STALE flag set. */
4661 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4662 && peer
->nsf
[afi
][safi
])
4663 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4664 PEER_STATUS_ENHANCED_REFRESH
))
4665 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4666 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4667 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4669 /* If this is an EVPN route, process for
4671 if (safi
== SAFI_EVPN
)
4672 bgp_evpn_unimport_route(
4674 bgp_dest_get_prefix(dest
), pi
);
4675 /* Handle withdraw for VRF route-leaking and L3VPN */
4676 if (SAFI_UNICAST
== safi
4677 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4678 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4679 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4682 if (SAFI_MPLS_VPN
== safi
&&
4683 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4684 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4687 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4693 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4695 struct bgp_clear_node_queue
*cnq
= data
;
4696 struct bgp_dest
*dest
= cnq
->dest
;
4697 struct bgp_table
*table
= bgp_dest_table(dest
);
4699 bgp_dest_unlock_node(dest
);
4700 bgp_table_unlock(table
);
4701 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4704 static void bgp_clear_node_complete(struct work_queue
*wq
)
4706 struct peer
*peer
= wq
->spec
.data
;
4708 /* Tickle FSM to start moving again */
4709 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4711 peer_unlock(peer
); /* bgp_clear_route */
4714 static void bgp_clear_node_queue_init(struct peer
*peer
)
4716 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4718 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4719 #undef CLEAR_QUEUE_NAME_LEN
4721 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4722 peer
->clear_node_queue
->spec
.hold
= 10;
4723 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4724 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4725 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4726 peer
->clear_node_queue
->spec
.max_retries
= 0;
4728 /* we only 'lock' this peer reference when the queue is actually active
4730 peer
->clear_node_queue
->spec
.data
= peer
;
4733 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4734 struct bgp_table
*table
)
4736 struct bgp_dest
*dest
;
4737 int force
= peer
->bgp
->process_queue
? 0 : 1;
4740 table
= peer
->bgp
->rib
[afi
][safi
];
4742 /* If still no table => afi/safi isn't configured at all or smth. */
4746 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4747 struct bgp_path_info
*pi
, *next
;
4748 struct bgp_adj_in
*ain
;
4749 struct bgp_adj_in
*ain_next
;
4751 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4752 * queued for every clearing peer, regardless of whether it is
4753 * relevant to the peer at hand.
4755 * Overview: There are 3 different indices which need to be
4756 * scrubbed, potentially, when a peer is removed:
4758 * 1 peer's routes visible via the RIB (ie accepted routes)
4759 * 2 peer's routes visible by the (optional) peer's adj-in index
4760 * 3 other routes visible by the peer's adj-out index
4762 * 3 there is no hurry in scrubbing, once the struct peer is
4763 * removed from bgp->peer, we could just GC such deleted peer's
4764 * adj-outs at our leisure.
4766 * 1 and 2 must be 'scrubbed' in some way, at least made
4767 * invisible via RIB index before peer session is allowed to be
4768 * brought back up. So one needs to know when such a 'search' is
4773 * - there'd be a single global queue or a single RIB walker
4774 * - rather than tracking which route_nodes still need to be
4775 * examined on a peer basis, we'd track which peers still
4778 * Given that our per-peer prefix-counts now should be reliable,
4779 * this may actually be achievable. It doesn't seem to be a huge
4780 * problem at this time,
4782 * It is possible that we have multiple paths for a prefix from
4784 * if that peer is using AddPath.
4788 ain_next
= ain
->next
;
4790 if (ain
->peer
== peer
) {
4791 bgp_adj_in_remove(dest
, ain
);
4792 bgp_dest_unlock_node(dest
);
4798 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4800 if (pi
->peer
!= peer
)
4804 bgp_path_info_reap(dest
, pi
);
4806 struct bgp_clear_node_queue
*cnq
;
4808 /* both unlocked in bgp_clear_node_queue_del */
4809 bgp_table_lock(bgp_dest_table(dest
));
4810 bgp_dest_lock_node(dest
);
4812 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4813 sizeof(struct bgp_clear_node_queue
));
4815 work_queue_add(peer
->clear_node_queue
, cnq
);
4823 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4825 struct bgp_dest
*dest
;
4826 struct bgp_table
*table
;
4828 if (peer
->clear_node_queue
== NULL
)
4829 bgp_clear_node_queue_init(peer
);
4831 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4832 * Idle until it receives a Clearing_Completed event. This protects
4833 * against peers which flap faster than we can we clear, which could
4836 * a) race with routes from the new session being installed before
4837 * clear_route_node visits the node (to delete the route of that
4839 * b) resource exhaustion, clear_route_node likely leads to an entry
4840 * on the process_main queue. Fast-flapping could cause that queue
4844 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4845 * the unlock will happen upon work-queue completion; other wise, the
4846 * unlock happens at the end of this function.
4848 if (!peer
->clear_node_queue
->thread
)
4851 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4852 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4854 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4855 dest
= bgp_route_next(dest
)) {
4856 table
= bgp_dest_get_bgp_table_info(dest
);
4860 bgp_clear_route_table(peer
, afi
, safi
, table
);
4863 /* unlock if no nodes got added to the clear-node-queue. */
4864 if (!peer
->clear_node_queue
->thread
)
4868 void bgp_clear_route_all(struct peer
*peer
)
4873 FOREACH_AFI_SAFI (afi
, safi
)
4874 bgp_clear_route(peer
, afi
, safi
);
4876 #ifdef ENABLE_BGP_VNC
4877 rfapiProcessPeerDown(peer
);
4881 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4883 struct bgp_table
*table
;
4884 struct bgp_dest
*dest
;
4885 struct bgp_adj_in
*ain
;
4886 struct bgp_adj_in
*ain_next
;
4888 table
= peer
->bgp
->rib
[afi
][safi
];
4890 /* It is possible that we have multiple paths for a prefix from a peer
4891 * if that peer is using AddPath.
4893 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4897 ain_next
= ain
->next
;
4899 if (ain
->peer
== peer
) {
4900 bgp_adj_in_remove(dest
, ain
);
4901 bgp_dest_unlock_node(dest
);
4909 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4911 struct bgp_dest
*dest
;
4912 struct bgp_path_info
*pi
;
4913 struct bgp_table
*table
;
4915 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4916 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4917 dest
= bgp_route_next(dest
)) {
4918 struct bgp_dest
*rm
;
4920 /* look for neighbor in tables */
4921 table
= bgp_dest_get_bgp_table_info(dest
);
4925 for (rm
= bgp_table_top(table
); rm
;
4926 rm
= bgp_route_next(rm
))
4927 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4929 if (pi
->peer
!= peer
)
4931 if (!CHECK_FLAG(pi
->flags
,
4935 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4940 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4941 dest
= bgp_route_next(dest
))
4942 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4944 if (pi
->peer
!= peer
)
4946 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4948 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4954 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4956 struct bgp_dest
*dest
, *ndest
;
4957 struct bgp_path_info
*pi
;
4958 struct bgp_table
*table
;
4960 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4961 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4962 dest
= bgp_route_next(dest
)) {
4963 table
= bgp_dest_get_bgp_table_info(dest
);
4967 for (ndest
= bgp_table_top(table
); ndest
;
4968 ndest
= bgp_route_next(ndest
)) {
4969 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
4971 if (pi
->peer
!= peer
)
4975 peer
->af_sflags
[afi
][safi
],
4976 PEER_STATUS_ENHANCED_REFRESH
))
4977 && !CHECK_FLAG(pi
->flags
,
4981 BGP_PATH_UNUSEABLE
)) {
4982 if (bgp_debug_neighbor_events(
4985 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4989 bgp_dest_get_prefix(
4992 bgp_path_info_set_flag(
5000 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5001 dest
= bgp_route_next(dest
)) {
5002 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5004 if (pi
->peer
!= peer
)
5007 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5008 PEER_STATUS_ENHANCED_REFRESH
))
5009 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5010 && !CHECK_FLAG(pi
->flags
,
5011 BGP_PATH_UNUSEABLE
)) {
5012 if (bgp_debug_neighbor_events(peer
))
5014 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5018 bgp_dest_get_prefix(
5021 bgp_path_info_set_flag(dest
, pi
,
5029 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5031 if (peer
->sort
== BGP_PEER_IBGP
)
5034 if (peer
->sort
== BGP_PEER_EBGP
5035 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5036 || FILTER_LIST_OUT_NAME(filter
)
5037 || DISTRIBUTE_OUT_NAME(filter
)))
5042 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5044 if (peer
->sort
== BGP_PEER_IBGP
)
5047 if (peer
->sort
== BGP_PEER_EBGP
5048 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5049 || FILTER_LIST_IN_NAME(filter
)
5050 || DISTRIBUTE_IN_NAME(filter
)))
5055 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5058 struct bgp_dest
*dest
;
5059 struct bgp_path_info
*pi
;
5060 struct bgp_path_info
*next
;
5062 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5063 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5064 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5068 /* Unimport EVPN routes from VRFs */
5069 if (safi
== SAFI_EVPN
)
5070 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5073 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5074 && pi
->type
== ZEBRA_ROUTE_BGP
5075 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5076 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5077 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5079 if (bgp_fibupd_safi(safi
))
5080 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5083 bgp_path_info_reap(dest
, pi
);
5087 /* Delete all kernel routes. */
5088 void bgp_cleanup_routes(struct bgp
*bgp
)
5091 struct bgp_dest
*dest
;
5092 struct bgp_table
*table
;
5094 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5095 if (afi
== AFI_L2VPN
)
5097 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5100 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5102 if (afi
!= AFI_L2VPN
) {
5104 safi
= SAFI_MPLS_VPN
;
5105 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5106 dest
= bgp_route_next(dest
)) {
5107 table
= bgp_dest_get_bgp_table_info(dest
);
5108 if (table
!= NULL
) {
5109 bgp_cleanup_table(bgp
, table
, safi
);
5110 bgp_table_finish(&table
);
5111 bgp_dest_set_bgp_table_info(dest
, NULL
);
5112 bgp_dest_unlock_node(dest
);
5116 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5117 dest
= bgp_route_next(dest
)) {
5118 table
= bgp_dest_get_bgp_table_info(dest
);
5119 if (table
!= NULL
) {
5120 bgp_cleanup_table(bgp
, table
, safi
);
5121 bgp_table_finish(&table
);
5122 bgp_dest_set_bgp_table_info(dest
, NULL
);
5123 bgp_dest_unlock_node(dest
);
5128 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5129 dest
= bgp_route_next(dest
)) {
5130 table
= bgp_dest_get_bgp_table_info(dest
);
5131 if (table
!= NULL
) {
5132 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5133 bgp_table_finish(&table
);
5134 bgp_dest_set_bgp_table_info(dest
, NULL
);
5135 bgp_dest_unlock_node(dest
);
5140 void bgp_reset(void)
5143 bgp_zclient_reset();
5144 access_list_reset();
5145 prefix_list_reset();
5148 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5150 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5151 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5152 PEER_CAP_ADDPATH_AF_TX_RCV
));
5155 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5157 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5158 struct bgp_nlri
*packet
)
5167 int addpath_encoded
;
5168 uint32_t addpath_id
;
5171 lim
= pnt
+ packet
->length
;
5173 safi
= packet
->safi
;
5175 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5177 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5178 syntactic validity. If the field is syntactically incorrect,
5179 then the Error Subcode is set to Invalid Network Field. */
5180 for (; pnt
< lim
; pnt
+= psize
) {
5181 /* Clear prefix structure. */
5182 memset(&p
, 0, sizeof(struct prefix
));
5184 if (addpath_encoded
) {
5186 /* When packet overflow occurs return immediately. */
5187 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5188 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5190 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5191 addpath_id
= ntohl(addpath_id
);
5192 pnt
+= BGP_ADDPATH_ID_LEN
;
5195 /* Fetch prefix length. */
5196 p
.prefixlen
= *pnt
++;
5197 /* afi/safi validity already verified by caller,
5198 * bgp_update_receive */
5199 p
.family
= afi2family(afi
);
5201 /* Prefix length check. */
5202 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5205 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5206 peer
->host
, p
.prefixlen
, packet
->afi
);
5207 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5210 /* Packet size overflow check. */
5211 psize
= PSIZE(p
.prefixlen
);
5213 /* When packet overflow occur return immediately. */
5214 if (pnt
+ psize
> lim
) {
5217 "%s [Error] Update packet error (prefix length %d overflows packet)",
5218 peer
->host
, p
.prefixlen
);
5219 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5222 /* Defensive coding, double-check the psize fits in a struct
5224 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5227 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5228 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5229 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5232 /* Fetch prefix from NLRI packet. */
5233 memcpy(p
.u
.val
, pnt
, psize
);
5235 /* Check address. */
5236 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5237 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5238 /* From RFC4271 Section 6.3:
5240 * If a prefix in the NLRI field is semantically
5242 * (e.g., an unexpected multicast IP address),
5244 * be logged locally, and the prefix SHOULD be
5249 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5250 peer
->host
, &p
.u
.prefix4
);
5255 /* Check address. */
5256 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5257 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5260 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5261 peer
->host
, &p
.u
.prefix6
);
5265 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5268 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5269 peer
->host
, &p
.u
.prefix6
);
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
,
6393 sizeof(addr_prefix_str
));
6395 vty_out(vty
, "%% Inconsistent address and mask\n");
6396 return CMD_WARNING_CONFIG_FAILED
;
6400 afi
= bgp_node_afi(vty
);
6401 safi
= bgp_node_safi(vty
);
6404 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6406 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6409 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6410 NB_OP_CREATE
, map_name
);
6412 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6413 NB_OP_DESTROY
, NULL
);
6415 if (label_index_str
)
6416 nb_cli_enqueue_change(vty
, "./label-index",
6417 NB_OP_MODIFY
, label_index_str
);
6419 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6420 backdoor
? "true" : "false");
6424 base_xpath
, sizeof(base_xpath
),
6425 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6426 yang_afi_safi_value2identity(afi
, safi
),
6427 bgp_afi_safi_get_container_str(afi
, safi
),
6428 address_str
? addr_prefix_str
: prefix_str
);
6430 return nb_cli_apply_changes(vty
, base_xpath
);
6433 DEFPY_YANG (ipv6_bgp_network
,
6434 ipv6_bgp_network_cmd
,
6435 "[no] network X:X::X:X/M$prefix \
6436 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6438 "Specify a network to announce via BGP\n"
6440 "Route-map to modify the attributes\n"
6441 "Name of the route map\n"
6442 "Label index to associate with the prefix\n"
6443 "Label index value\n")
6445 char base_xpath
[XPATH_MAXLEN
];
6449 afi
= bgp_node_afi(vty
);
6450 safi
= bgp_node_safi(vty
);
6453 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6455 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6458 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6459 NB_OP_MODIFY
, map_name
);
6461 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6462 NB_OP_DESTROY
, NULL
);
6464 if (label_index_str
)
6465 nb_cli_enqueue_change(vty
, "./label-index",
6466 NB_OP_MODIFY
, label_index_str
);
6470 base_xpath
, sizeof(base_xpath
),
6471 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6472 yang_afi_safi_value2identity(afi
, safi
),
6473 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6475 return nb_cli_apply_changes(vty
, base_xpath
);
6478 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6479 struct lyd_node
*dnode
,
6482 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6484 if (yang_dnode_exists(dnode
, "./label-index"))
6485 vty_out(vty
, " label-index %s",
6486 yang_dnode_get_string(dnode
, "./label-index"));
6488 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6489 vty_out(vty
, " route-map %s",
6490 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6492 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6493 vty_out(vty
, " backdoor");
6498 static struct bgp_aggregate
*bgp_aggregate_new(void)
6500 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6503 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6505 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6506 route_map_counter_decrement(aggregate
->suppress_map
);
6507 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6508 route_map_counter_decrement(aggregate
->rmap
.map
);
6509 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6513 * Helper function to avoid repeated code: prepare variables for a
6514 * `route_map_apply` call.
6516 * \returns `true` on route map match, otherwise `false`.
6518 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6519 struct bgp_aggregate
*aggregate
,
6520 struct bgp_path_info
*pi
)
6522 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6523 route_map_result_t rmr
= RMAP_DENYMATCH
;
6524 struct bgp_path_info rmap_path
= {};
6525 struct attr attr
= {};
6527 /* No route map entries created, just don't match. */
6528 if (aggregate
->suppress_map
== NULL
)
6531 /* Call route map matching and return result. */
6532 attr
.aspath
= aspath_empty();
6533 rmap_path
.peer
= bgp
->peer_self
;
6534 rmap_path
.attr
= &attr
;
6536 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6537 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6538 bgp
->peer_self
->rmap_type
= 0;
6540 bgp_attr_flush(&attr
);
6542 return rmr
== RMAP_PERMITMATCH
;
6545 /** Test whether the aggregation has suppressed this path or not. */
6546 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6547 struct bgp_path_info
*pi
)
6549 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6552 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6556 * Suppress this path and keep the reference.
6558 * \returns `true` if needs processing otherwise `false`.
6560 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6561 struct bgp_path_info
*pi
)
6563 struct bgp_path_info_extra
*pie
;
6565 /* Path is already suppressed by this aggregation. */
6566 if (aggr_suppress_exists(aggregate
, pi
))
6569 pie
= bgp_path_info_extra_get(pi
);
6571 /* This is the first suppression, allocate memory and list it. */
6572 if (pie
->aggr_suppressors
== NULL
)
6573 pie
->aggr_suppressors
= list_new();
6575 listnode_add(pie
->aggr_suppressors
, aggregate
);
6577 /* Only mark for processing if suppressed. */
6578 if (listcount(pie
->aggr_suppressors
) == 1) {
6579 if (BGP_DEBUG(update
, UPDATE_OUT
))
6580 zlog_debug("aggregate-address suppressing: %pFX",
6581 bgp_dest_get_prefix(pi
->net
));
6583 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6591 * Unsuppress this path and remove the reference.
6593 * \returns `true` if needs processing otherwise `false`.
6595 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6596 struct bgp_path_info
*pi
)
6598 /* Path wasn't suppressed. */
6599 if (!aggr_suppress_exists(aggregate
, pi
))
6602 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6604 /* Unsuppress and free extra memory if last item. */
6605 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6606 if (BGP_DEBUG(update
, UPDATE_OUT
))
6607 zlog_debug("aggregate-address unsuppressing: %pFX",
6608 bgp_dest_get_prefix(pi
->net
));
6610 list_delete(&pi
->extra
->aggr_suppressors
);
6611 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6618 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6619 struct aspath
*aspath
,
6620 struct community
*comm
,
6621 struct ecommunity
*ecomm
,
6622 struct lcommunity
*lcomm
)
6624 static struct aspath
*ae
= NULL
;
6627 ae
= aspath_empty();
6632 if (origin
!= pi
->attr
->origin
)
6635 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6638 if (!community_cmp(pi
->attr
->community
, comm
))
6641 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6644 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6647 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6653 static void bgp_aggregate_install(
6654 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6655 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6656 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6657 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6659 struct bgp_dest
*dest
;
6660 struct bgp_table
*table
;
6661 struct bgp_path_info
*pi
, *orig
, *new;
6664 table
= bgp
->rib
[afi
][safi
];
6666 dest
= bgp_node_get(table
, p
);
6668 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6669 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6670 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6674 * If we have paths with different MEDs, then don't install
6675 * (or uninstall) the aggregate route.
6677 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6678 goto uninstall_aggregate_route
;
6680 if (aggregate
->count
> 0) {
6682 * If the aggregate information has not changed
6683 * no need to re-install it again.
6685 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6686 ecommunity
, lcommunity
)) {
6687 bgp_dest_unlock_node(dest
);
6690 aspath_free(aspath
);
6692 community_free(&community
);
6694 ecommunity_free(&ecommunity
);
6696 lcommunity_free(&lcommunity
);
6702 * Mark the old as unusable
6705 bgp_path_info_delete(dest
, pi
);
6707 attr
= bgp_attr_aggregate_intern(
6708 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6709 aggregate
, atomic_aggregate
, p
);
6712 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6713 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6714 zlog_debug("%s: %pFX null attribute", __func__
,
6719 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6720 bgp
->peer_self
, attr
, dest
);
6722 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6724 bgp_path_info_add(dest
, new);
6725 bgp_process(bgp
, dest
, afi
, safi
);
6727 uninstall_aggregate_route
:
6728 for (pi
= orig
; pi
; pi
= pi
->next
)
6729 if (pi
->peer
== bgp
->peer_self
6730 && pi
->type
== ZEBRA_ROUTE_BGP
6731 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6734 /* Withdraw static BGP route from routing table. */
6736 bgp_path_info_delete(dest
, pi
);
6737 bgp_process(bgp
, dest
, afi
, safi
);
6741 bgp_dest_unlock_node(dest
);
6745 * Check if the current path has different MED than other known paths.
6747 * \returns `true` if the MED matched the others else `false`.
6749 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6750 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6752 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6754 /* This is the first route being analyzed. */
6755 if (!aggregate
->med_initialized
) {
6756 aggregate
->med_initialized
= true;
6757 aggregate
->med_mismatched
= false;
6758 aggregate
->med_matched_value
= cur_med
;
6760 /* Check if routes with different MED showed up. */
6761 if (cur_med
!= aggregate
->med_matched_value
)
6762 aggregate
->med_mismatched
= true;
6765 return !aggregate
->med_mismatched
;
6769 * Initializes and tests all routes in the aggregate address path for MED
6772 * \returns `true` if all MEDs are the same otherwise `false`.
6774 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6775 struct bgp
*bgp
, const struct prefix
*p
,
6776 afi_t afi
, safi_t safi
)
6778 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6779 const struct prefix
*dest_p
;
6780 struct bgp_dest
*dest
, *top
;
6781 struct bgp_path_info
*pi
;
6782 bool med_matched
= true;
6784 aggregate
->med_initialized
= false;
6786 top
= bgp_node_get(table
, p
);
6787 for (dest
= bgp_node_get(table
, p
); dest
;
6788 dest
= bgp_route_next_until(dest
, top
)) {
6789 dest_p
= bgp_dest_get_prefix(dest
);
6790 if (dest_p
->prefixlen
<= p
->prefixlen
)
6793 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6794 if (BGP_PATH_HOLDDOWN(pi
))
6796 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6798 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6799 med_matched
= false;
6806 bgp_dest_unlock_node(top
);
6812 * Toggles the route suppression status for this aggregate address
6815 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6816 struct bgp
*bgp
, const struct prefix
*p
,
6817 afi_t afi
, safi_t safi
, bool suppress
)
6819 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6820 const struct prefix
*dest_p
;
6821 struct bgp_dest
*dest
, *top
;
6822 struct bgp_path_info
*pi
;
6823 bool toggle_suppression
;
6825 /* We've found a different MED we must revert any suppressed routes. */
6826 top
= bgp_node_get(table
, p
);
6827 for (dest
= bgp_node_get(table
, p
); dest
;
6828 dest
= bgp_route_next_until(dest
, top
)) {
6829 dest_p
= bgp_dest_get_prefix(dest
);
6830 if (dest_p
->prefixlen
<= p
->prefixlen
)
6833 toggle_suppression
= false;
6834 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6835 if (BGP_PATH_HOLDDOWN(pi
))
6837 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6840 /* We are toggling suppression back. */
6842 /* Suppress route if not suppressed already. */
6843 if (aggr_suppress_path(aggregate
, pi
))
6844 toggle_suppression
= true;
6848 /* Install route if there is no more suppression. */
6849 if (aggr_unsuppress_path(aggregate
, pi
))
6850 toggle_suppression
= true;
6853 if (toggle_suppression
)
6854 bgp_process(bgp
, dest
, afi
, safi
);
6856 bgp_dest_unlock_node(top
);
6860 * Aggregate address MED matching incremental test: this function is called
6861 * when the initial aggregation occurred and we are only testing a single
6864 * In addition to testing and setting the MED validity it also installs back
6865 * suppressed routes (if summary is configured).
6867 * Must not be called in `bgp_aggregate_route`.
6869 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6870 struct bgp
*bgp
, const struct prefix
*p
,
6871 afi_t afi
, safi_t safi
,
6872 struct bgp_path_info
*pi
, bool is_adding
)
6874 /* MED matching disabled. */
6875 if (!aggregate
->match_med
)
6878 /* Aggregation with different MED, nothing to do. */
6879 if (aggregate
->med_mismatched
)
6883 * Test the current entry:
6885 * is_adding == true: if the new entry doesn't match then we must
6886 * install all suppressed routes.
6888 * is_adding == false: if the entry being removed was the last
6889 * unmatching entry then we can suppress all routes.
6892 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6893 && aggregate
->summary_only
)
6894 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6897 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6899 /* No mismatches, just quit. */
6900 if (!aggregate
->med_mismatched
)
6903 /* Route summarization is disabled. */
6904 if (!aggregate
->summary_only
)
6907 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6910 /* Update an aggregate as routes are added/removed from the BGP table */
6911 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6912 safi_t safi
, struct bgp_aggregate
*aggregate
)
6914 struct bgp_table
*table
;
6915 struct bgp_dest
*top
;
6916 struct bgp_dest
*dest
;
6918 struct aspath
*aspath
= NULL
;
6919 struct community
*community
= NULL
;
6920 struct ecommunity
*ecommunity
= NULL
;
6921 struct lcommunity
*lcommunity
= NULL
;
6922 struct bgp_path_info
*pi
;
6923 unsigned long match
= 0;
6924 uint8_t atomic_aggregate
= 0;
6926 /* If the bgp instance is being deleted or self peer is deleted
6927 * then do not create aggregate route
6929 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6930 || (bgp
->peer_self
== NULL
))
6933 /* Initialize and test routes for MED difference. */
6934 if (aggregate
->match_med
)
6935 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6938 * Reset aggregate count: we might've been called from route map
6939 * update so in that case we must retest all more specific routes.
6941 * \see `bgp_route_map_process_update`.
6943 aggregate
->count
= 0;
6944 aggregate
->incomplete_origin_count
= 0;
6945 aggregate
->incomplete_origin_count
= 0;
6946 aggregate
->egp_origin_count
= 0;
6948 /* ORIGIN attribute: If at least one route among routes that are
6949 aggregated has ORIGIN with the value INCOMPLETE, then the
6950 aggregated route must have the ORIGIN attribute with the value
6951 INCOMPLETE. Otherwise, if at least one route among routes that
6952 are aggregated has ORIGIN with the value EGP, then the aggregated
6953 route must have the origin attribute with the value EGP. In all
6954 other case the value of the ORIGIN attribute of the aggregated
6955 route is INTERNAL. */
6956 origin
= BGP_ORIGIN_IGP
;
6958 table
= bgp
->rib
[afi
][safi
];
6960 top
= bgp_node_get(table
, p
);
6961 for (dest
= bgp_node_get(table
, p
); dest
;
6962 dest
= bgp_route_next_until(dest
, top
)) {
6963 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6965 if (dest_p
->prefixlen
<= p
->prefixlen
)
6968 /* If suppress fib is enabled and route not installed
6969 * in FIB, skip the route
6971 if (!bgp_check_advertise(bgp
, dest
))
6976 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6977 if (BGP_PATH_HOLDDOWN(pi
))
6981 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6982 atomic_aggregate
= 1;
6984 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6988 * summary-only aggregate route suppress
6989 * aggregated route announcements.
6992 * Don't create summaries if MED didn't match
6993 * otherwise neither the specific routes and the
6994 * aggregation will be announced.
6996 if (aggregate
->summary_only
6997 && AGGREGATE_MED_VALID(aggregate
)) {
6998 if (aggr_suppress_path(aggregate
, pi
))
7003 * Suppress more specific routes that match the route
7007 * Don't suppress routes if MED matching is enabled and
7008 * it mismatched otherwise we might end up with no
7009 * routes for this path.
7011 if (aggregate
->suppress_map_name
7012 && AGGREGATE_MED_VALID(aggregate
)
7013 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7014 if (aggr_suppress_path(aggregate
, pi
))
7021 * If at least one route among routes that are
7022 * aggregated has ORIGIN with the value INCOMPLETE,
7023 * then the aggregated route MUST have the ORIGIN
7024 * attribute with the value INCOMPLETE. Otherwise, if
7025 * at least one route among routes that are aggregated
7026 * has ORIGIN with the value EGP, then the aggregated
7027 * route MUST have the ORIGIN attribute with the value
7030 switch (pi
->attr
->origin
) {
7031 case BGP_ORIGIN_INCOMPLETE
:
7032 aggregate
->incomplete_origin_count
++;
7034 case BGP_ORIGIN_EGP
:
7035 aggregate
->egp_origin_count
++;
7043 if (!aggregate
->as_set
)
7047 * as-set aggregate route generate origin, as path,
7048 * and community aggregation.
7050 /* Compute aggregate route's as-path.
7052 bgp_compute_aggregate_aspath_hash(aggregate
,
7055 /* Compute aggregate route's community.
7057 if (pi
->attr
->community
)
7058 bgp_compute_aggregate_community_hash(
7060 pi
->attr
->community
);
7062 /* Compute aggregate route's extended community.
7064 if (pi
->attr
->ecommunity
)
7065 bgp_compute_aggregate_ecommunity_hash(
7067 pi
->attr
->ecommunity
);
7069 /* Compute aggregate route's large community.
7071 if (pi
->attr
->lcommunity
)
7072 bgp_compute_aggregate_lcommunity_hash(
7074 pi
->attr
->lcommunity
);
7077 bgp_process(bgp
, dest
, afi
, safi
);
7079 if (aggregate
->as_set
) {
7080 bgp_compute_aggregate_aspath_val(aggregate
);
7081 bgp_compute_aggregate_community_val(aggregate
);
7082 bgp_compute_aggregate_ecommunity_val(aggregate
);
7083 bgp_compute_aggregate_lcommunity_val(aggregate
);
7087 bgp_dest_unlock_node(top
);
7090 if (aggregate
->incomplete_origin_count
> 0)
7091 origin
= BGP_ORIGIN_INCOMPLETE
;
7092 else if (aggregate
->egp_origin_count
> 0)
7093 origin
= BGP_ORIGIN_EGP
;
7095 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7096 origin
= aggregate
->origin
;
7098 if (aggregate
->as_set
) {
7099 if (aggregate
->aspath
)
7100 /* Retrieve aggregate route's as-path.
7102 aspath
= aspath_dup(aggregate
->aspath
);
7104 if (aggregate
->community
)
7105 /* Retrieve aggregate route's community.
7107 community
= community_dup(aggregate
->community
);
7109 if (aggregate
->ecommunity
)
7110 /* Retrieve aggregate route's ecommunity.
7112 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7114 if (aggregate
->lcommunity
)
7115 /* Retrieve aggregate route's lcommunity.
7117 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7120 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7121 ecommunity
, lcommunity
, atomic_aggregate
,
7125 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7126 safi_t safi
, struct bgp_aggregate
*aggregate
)
7128 struct bgp_table
*table
;
7129 struct bgp_dest
*top
;
7130 struct bgp_dest
*dest
;
7131 struct bgp_path_info
*pi
;
7132 unsigned long match
;
7134 table
= bgp
->rib
[afi
][safi
];
7136 /* If routes exists below this node, generate aggregate routes. */
7137 top
= bgp_node_get(table
, p
);
7138 for (dest
= bgp_node_get(table
, p
); dest
;
7139 dest
= bgp_route_next_until(dest
, top
)) {
7140 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7142 if (dest_p
->prefixlen
<= p
->prefixlen
)
7146 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7147 if (BGP_PATH_HOLDDOWN(pi
))
7150 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7153 if (aggregate
->summary_only
&& pi
->extra
7154 && AGGREGATE_MED_VALID(aggregate
)) {
7155 if (aggr_unsuppress_path(aggregate
, pi
))
7159 if (aggregate
->suppress_map_name
7160 && AGGREGATE_MED_VALID(aggregate
)
7161 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7162 if (aggr_unsuppress_path(aggregate
, pi
))
7168 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7169 aggregate
->incomplete_origin_count
--;
7170 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7171 aggregate
->egp_origin_count
--;
7173 if (aggregate
->as_set
) {
7174 /* Remove as-path from aggregate.
7176 bgp_remove_aspath_from_aggregate_hash(
7180 if (pi
->attr
->community
)
7181 /* Remove community from aggregate.
7183 bgp_remove_comm_from_aggregate_hash(
7185 pi
->attr
->community
);
7187 if (pi
->attr
->ecommunity
)
7188 /* Remove ecommunity from aggregate.
7190 bgp_remove_ecomm_from_aggregate_hash(
7192 pi
->attr
->ecommunity
);
7194 if (pi
->attr
->lcommunity
)
7195 /* Remove lcommunity from aggregate.
7197 bgp_remove_lcomm_from_aggregate_hash(
7199 pi
->attr
->lcommunity
);
7203 /* If this node was suppressed, process the change. */
7205 bgp_process(bgp
, dest
, afi
, safi
);
7207 if (aggregate
->as_set
) {
7208 aspath_free(aggregate
->aspath
);
7209 aggregate
->aspath
= NULL
;
7210 if (aggregate
->community
)
7211 community_free(&aggregate
->community
);
7212 if (aggregate
->ecommunity
)
7213 ecommunity_free(&aggregate
->ecommunity
);
7214 if (aggregate
->lcommunity
)
7215 lcommunity_free(&aggregate
->lcommunity
);
7218 bgp_dest_unlock_node(top
);
7221 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7222 const struct prefix
*aggr_p
,
7223 struct bgp_path_info
*pinew
, afi_t afi
,
7225 struct bgp_aggregate
*aggregate
)
7228 struct aspath
*aspath
= NULL
;
7229 uint8_t atomic_aggregate
= 0;
7230 struct community
*community
= NULL
;
7231 struct ecommunity
*ecommunity
= NULL
;
7232 struct lcommunity
*lcommunity
= NULL
;
7234 /* If the bgp instance is being deleted or self peer is deleted
7235 * then do not create aggregate route
7237 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7238 || (bgp
->peer_self
== NULL
))
7241 /* ORIGIN attribute: If at least one route among routes that are
7242 * aggregated has ORIGIN with the value INCOMPLETE, then the
7243 * aggregated route must have the ORIGIN attribute with the value
7244 * INCOMPLETE. Otherwise, if at least one route among routes that
7245 * are aggregated has ORIGIN with the value EGP, then the aggregated
7246 * route must have the origin attribute with the value EGP. In all
7247 * other case the value of the ORIGIN attribute of the aggregated
7248 * route is INTERNAL.
7250 origin
= BGP_ORIGIN_IGP
;
7255 * This must be called before `summary` check to avoid
7256 * "suppressing" twice.
7258 if (aggregate
->match_med
)
7259 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7262 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7263 aggr_suppress_path(aggregate
, pinew
);
7265 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7266 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7267 aggr_suppress_path(aggregate
, pinew
);
7269 switch (pinew
->attr
->origin
) {
7270 case BGP_ORIGIN_INCOMPLETE
:
7271 aggregate
->incomplete_origin_count
++;
7273 case BGP_ORIGIN_EGP
:
7274 aggregate
->egp_origin_count
++;
7282 if (aggregate
->incomplete_origin_count
> 0)
7283 origin
= BGP_ORIGIN_INCOMPLETE
;
7284 else if (aggregate
->egp_origin_count
> 0)
7285 origin
= BGP_ORIGIN_EGP
;
7287 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7288 origin
= aggregate
->origin
;
7290 if (aggregate
->as_set
) {
7291 /* Compute aggregate route's as-path.
7293 bgp_compute_aggregate_aspath(aggregate
,
7294 pinew
->attr
->aspath
);
7296 /* Compute aggregate route's community.
7298 if (pinew
->attr
->community
)
7299 bgp_compute_aggregate_community(
7301 pinew
->attr
->community
);
7303 /* Compute aggregate route's extended community.
7305 if (pinew
->attr
->ecommunity
)
7306 bgp_compute_aggregate_ecommunity(
7308 pinew
->attr
->ecommunity
);
7310 /* Compute aggregate route's large community.
7312 if (pinew
->attr
->lcommunity
)
7313 bgp_compute_aggregate_lcommunity(
7315 pinew
->attr
->lcommunity
);
7317 /* Retrieve aggregate route's as-path.
7319 if (aggregate
->aspath
)
7320 aspath
= aspath_dup(aggregate
->aspath
);
7322 /* Retrieve aggregate route's community.
7324 if (aggregate
->community
)
7325 community
= community_dup(aggregate
->community
);
7327 /* Retrieve aggregate route's ecommunity.
7329 if (aggregate
->ecommunity
)
7330 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7332 /* Retrieve aggregate route's lcommunity.
7334 if (aggregate
->lcommunity
)
7335 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7338 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7339 aspath
, community
, ecommunity
,
7340 lcommunity
, atomic_aggregate
, aggregate
);
7343 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7345 struct bgp_path_info
*pi
,
7346 struct bgp_aggregate
*aggregate
,
7347 const struct prefix
*aggr_p
)
7350 struct aspath
*aspath
= NULL
;
7351 uint8_t atomic_aggregate
= 0;
7352 struct community
*community
= NULL
;
7353 struct ecommunity
*ecommunity
= NULL
;
7354 struct lcommunity
*lcommunity
= NULL
;
7355 unsigned long match
= 0;
7357 /* If the bgp instance is being deleted or self peer is deleted
7358 * then do not create aggregate route
7360 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7361 || (bgp
->peer_self
== NULL
))
7364 if (BGP_PATH_HOLDDOWN(pi
))
7367 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7370 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7371 if (aggr_unsuppress_path(aggregate
, pi
))
7374 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7375 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7376 if (aggr_unsuppress_path(aggregate
, pi
))
7380 * This must be called after `summary`, `suppress-map` check to avoid
7381 * "unsuppressing" twice.
7383 if (aggregate
->match_med
)
7384 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7387 if (aggregate
->count
> 0)
7390 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7391 aggregate
->incomplete_origin_count
--;
7392 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7393 aggregate
->egp_origin_count
--;
7395 if (aggregate
->as_set
) {
7396 /* Remove as-path from aggregate.
7398 bgp_remove_aspath_from_aggregate(aggregate
,
7401 if (pi
->attr
->community
)
7402 /* Remove community from aggregate.
7404 bgp_remove_community_from_aggregate(
7406 pi
->attr
->community
);
7408 if (pi
->attr
->ecommunity
)
7409 /* Remove ecommunity from aggregate.
7411 bgp_remove_ecommunity_from_aggregate(
7413 pi
->attr
->ecommunity
);
7415 if (pi
->attr
->lcommunity
)
7416 /* Remove lcommunity from aggregate.
7418 bgp_remove_lcommunity_from_aggregate(
7420 pi
->attr
->lcommunity
);
7423 /* If this node was suppressed, process the change. */
7425 bgp_process(bgp
, pi
->net
, afi
, safi
);
7427 origin
= BGP_ORIGIN_IGP
;
7428 if (aggregate
->incomplete_origin_count
> 0)
7429 origin
= BGP_ORIGIN_INCOMPLETE
;
7430 else if (aggregate
->egp_origin_count
> 0)
7431 origin
= BGP_ORIGIN_EGP
;
7433 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7434 origin
= aggregate
->origin
;
7436 if (aggregate
->as_set
) {
7437 /* Retrieve aggregate route's as-path.
7439 if (aggregate
->aspath
)
7440 aspath
= aspath_dup(aggregate
->aspath
);
7442 /* Retrieve aggregate route's community.
7444 if (aggregate
->community
)
7445 community
= community_dup(aggregate
->community
);
7447 /* Retrieve aggregate route's ecommunity.
7449 if (aggregate
->ecommunity
)
7450 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7452 /* Retrieve aggregate route's lcommunity.
7454 if (aggregate
->lcommunity
)
7455 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7458 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7459 aspath
, community
, ecommunity
,
7460 lcommunity
, atomic_aggregate
, aggregate
);
7463 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7464 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7466 struct bgp_dest
*child
;
7467 struct bgp_dest
*dest
;
7468 struct bgp_aggregate
*aggregate
;
7469 struct bgp_table
*table
;
7471 table
= bgp
->aggregate
[afi
][safi
];
7473 /* No aggregates configured. */
7474 if (bgp_table_top_nolock(table
) == NULL
)
7477 if (p
->prefixlen
== 0)
7480 if (BGP_PATH_HOLDDOWN(pi
))
7483 /* If suppress fib is enabled and route not installed
7484 * in FIB, do not update the aggregate route
7486 if (!bgp_check_advertise(bgp
, pi
->net
))
7489 child
= bgp_node_get(table
, p
);
7491 /* Aggregate address configuration check. */
7492 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7493 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7495 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7496 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7497 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7501 bgp_dest_unlock_node(child
);
7504 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7505 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7507 struct bgp_dest
*child
;
7508 struct bgp_dest
*dest
;
7509 struct bgp_aggregate
*aggregate
;
7510 struct bgp_table
*table
;
7512 table
= bgp
->aggregate
[afi
][safi
];
7514 /* No aggregates configured. */
7515 if (bgp_table_top_nolock(table
) == NULL
)
7518 if (p
->prefixlen
== 0)
7521 child
= bgp_node_get(table
, p
);
7523 /* Aggregate address configuration check. */
7524 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7525 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7527 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7528 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7529 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7533 bgp_dest_unlock_node(child
);
7536 /* Aggregate route attribute. */
7537 #define AGGREGATE_SUMMARY_ONLY 1
7538 #define AGGREGATE_AS_SET 1
7539 #define AGGREGATE_AS_UNSET 0
7541 static const char *bgp_origin2str(uint8_t origin
)
7544 case BGP_ORIGIN_IGP
:
7546 case BGP_ORIGIN_EGP
:
7548 case BGP_ORIGIN_INCOMPLETE
:
7549 return "incomplete";
7554 static const char *bgp_rpki_validation2str(int v_state
)
7569 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7570 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7572 struct bgp_dest
*dest
;
7573 struct bgp_aggregate
*aggregate
;
7575 /* If the bgp instance is being deleted or self peer is deleted
7576 * then do not create aggregate route
7578 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7579 || (bgp
->peer_self
== NULL
))
7583 /* Old configuration check. */
7584 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7586 snprintf(errmsg
, errmsg_len
,
7587 "There is no aggregate-address configuration.\n");
7591 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7592 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7593 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7596 /* Unlock aggregate address configuration. */
7597 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7599 if (aggregate
->community
)
7600 community_free(&aggregate
->community
);
7602 if (aggregate
->community_hash
) {
7603 /* Delete all communities in the hash.
7605 hash_clean(aggregate
->community_hash
,
7606 bgp_aggr_community_remove
);
7607 /* Free up the community_hash.
7609 hash_free(aggregate
->community_hash
);
7612 if (aggregate
->ecommunity
)
7613 ecommunity_free(&aggregate
->ecommunity
);
7615 if (aggregate
->ecommunity_hash
) {
7616 /* Delete all ecommunities in the hash.
7618 hash_clean(aggregate
->ecommunity_hash
,
7619 bgp_aggr_ecommunity_remove
);
7620 /* Free up the ecommunity_hash.
7622 hash_free(aggregate
->ecommunity_hash
);
7625 if (aggregate
->lcommunity
)
7626 lcommunity_free(&aggregate
->lcommunity
);
7628 if (aggregate
->lcommunity_hash
) {
7629 /* Delete all lcommunities in the hash.
7631 hash_clean(aggregate
->lcommunity_hash
,
7632 bgp_aggr_lcommunity_remove
);
7633 /* Free up the lcommunity_hash.
7635 hash_free(aggregate
->lcommunity_hash
);
7638 if (aggregate
->aspath
)
7639 aspath_free(aggregate
->aspath
);
7641 if (aggregate
->aspath_hash
) {
7642 /* Delete all as-paths in the hash.
7644 hash_clean(aggregate
->aspath_hash
,
7645 bgp_aggr_aspath_remove
);
7646 /* Free up the aspath_hash.
7648 hash_free(aggregate
->aspath_hash
);
7651 bgp_aggregate_free(aggregate
);
7652 bgp_dest_unlock_node(dest
);
7653 bgp_dest_unlock_node(dest
);
7658 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7659 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7660 uint8_t as_set
, uint8_t origin
, bool match_med
,
7661 const char *suppress_map
,
7662 char *errmsg
, size_t errmsg_len
)
7665 struct bgp_dest
*dest
;
7666 struct bgp_aggregate
*aggregate
;
7667 uint8_t as_set_new
= as_set
;
7668 char buf
[PREFIX2STR_BUFFER
];
7670 if (suppress_map
&& summary_only
) {
7671 snprintf(errmsg
, errmsg_len
,
7672 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7678 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7679 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7682 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7683 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7687 /* Old configuration check. */
7688 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7689 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7692 snprintf(errmsg
, errmsg_len
,
7693 "There is already same aggregate network.\n");
7694 /* try to remove the old entry */
7695 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7698 snprintf(errmsg
, errmsg_len
,
7699 "Error deleting aggregate.\n");
7700 bgp_dest_unlock_node(dest
);
7705 /* Make aggregate address structure. */
7706 aggregate
= bgp_aggregate_new();
7707 aggregate
->summary_only
= summary_only
;
7708 aggregate
->match_med
= match_med
;
7710 /* Network operators MUST NOT locally generate any new
7711 * announcements containing AS_SET or AS_CONFED_SET. If they have
7712 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7713 * SHOULD withdraw those routes and re-announce routes for the
7714 * aggregate or component prefixes (i.e., the more-specific routes
7715 * subsumed by the previously aggregated route) without AS_SET
7716 * or AS_CONFED_SET in the updates.
7718 if (bgp
->reject_as_sets
) {
7719 if (as_set
== AGGREGATE_AS_SET
) {
7720 as_set_new
= AGGREGATE_AS_UNSET
;
7722 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7726 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7730 aggregate
->as_set
= as_set_new
;
7731 aggregate
->safi
= safi
;
7732 /* Override ORIGIN attribute if defined.
7733 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7734 * to IGP which is not what rfc4271 says.
7735 * This enables the same behavior, optionally.
7737 aggregate
->origin
= origin
;
7740 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7741 route_map_counter_decrement(aggregate
->rmap
.map
);
7742 aggregate
->rmap
.name
=
7743 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7744 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7745 route_map_counter_increment(aggregate
->rmap
.map
);
7749 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7750 route_map_counter_decrement(aggregate
->suppress_map
);
7752 aggregate
->suppress_map_name
=
7753 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7754 aggregate
->suppress_map
=
7755 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7756 route_map_counter_increment(aggregate
->suppress_map
);
7759 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7761 /* Aggregate address insert into BGP routing table. */
7762 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
7768 aggregate_addressv4
, aggregate_addressv4_cmd
,
7769 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7771 "|summary-only$summary_only"
7772 "|route-map WORD$rmap_name"
7773 "|origin <egp|igp|incomplete>$origin_s"
7774 "|matching-MED-only$match_med"
7775 "|suppress-map WORD$suppress_map"
7778 "Configure BGP aggregate entries\n"
7779 "Aggregate prefix\n"
7780 "Aggregate address\n"
7782 "Generate AS set path information\n"
7783 "Filter more specific routes from updates\n"
7784 "Apply route map to aggregate network\n"
7789 "Unknown heritage\n"
7790 "Only aggregate routes with matching MED\n"
7791 "Suppress the selected more specific routes\n"
7792 "Route map with the route selectors\n")
7794 char base_xpath
[XPATH_MAXLEN
];
7795 safi_t safi
= bgp_node_safi(vty
);
7796 char prefix_buf
[PREFIX2STR_BUFFER
];
7799 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
7802 vty_out(vty
, "%% Inconsistent address and mask\n");
7803 return CMD_WARNING_CONFIG_FAILED
;
7806 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
7809 if (!no
&& origin_s
)
7810 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7812 if (!no
&& as_set_s
)
7813 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7815 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7817 if (!no
&& summary_only
)
7818 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7821 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7824 if (!no
&& match_med
)
7825 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7827 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7831 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7834 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
7835 NB_OP_DESTROY
, NULL
);
7838 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7841 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7845 base_xpath
, sizeof(base_xpath
),
7846 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7847 yang_afi_safi_value2identity(AFI_IP
, safi
),
7848 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
7851 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7853 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7855 return nb_cli_apply_changes(vty
, base_xpath
);
7858 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
7859 "[no] aggregate-address X:X::X:X/M$prefix {"
7861 "|summary-only$summary_only"
7862 "|route-map WORD$rmap_name"
7863 "|origin <egp|igp|incomplete>$origin_s"
7864 "|matching-MED-only$match_med"
7865 "|suppress-map WORD$suppress_map"
7868 "Configure BGP aggregate entries\n"
7869 "Aggregate prefix\n"
7870 "Generate AS set path information\n"
7871 "Filter more specific routes from updates\n"
7872 "Apply route map to aggregate network\n"
7877 "Unknown heritage\n"
7878 "Only aggregate routes with matching MED\n"
7879 "Suppress the selected more specific routes\n"
7880 "Route map with the route selectors\n")
7882 char base_xpath
[XPATH_MAXLEN
];
7883 safi_t safi
= bgp_node_safi(vty
);
7885 if (!no
&& origin_s
)
7886 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7888 if (!no
&& as_set_s
)
7889 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7891 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7893 if (!no
&& summary_only
)
7894 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7897 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7900 if (!no
&& match_med
)
7901 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7903 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7907 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7911 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7914 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7918 base_xpath
, sizeof(base_xpath
),
7919 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7920 yang_afi_safi_value2identity(AFI_IP6
, safi
),
7921 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
7924 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7926 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7928 return nb_cli_apply_changes(vty
, base_xpath
);
7931 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7932 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
7936 vty_out(vty
, " aggregate-address %s",
7937 yang_dnode_get_string(dnode
, "./prefix"));
7939 if (yang_dnode_get_bool(dnode
, "./as-set"))
7940 vty_out(vty
, " as-set");
7942 if (yang_dnode_get_bool(dnode
, "./summary-only"))
7943 vty_out(vty
, " summary-only");
7945 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
7946 vty_out(vty
, " route-map %s",
7947 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
7949 origin
= yang_dnode_get_enum(dnode
, "./origin");
7950 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
7951 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
7953 if (yang_dnode_get_bool(dnode
, "./match-med"))
7954 vty_out(vty
, " matching-MED-only");
7959 /* Redistribute route treatment. */
7960 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7961 const union g_addr
*nexthop
, ifindex_t ifindex
,
7962 enum nexthop_types_t nhtype
, uint32_t metric
,
7963 uint8_t type
, unsigned short instance
,
7966 struct bgp_path_info
*new;
7967 struct bgp_path_info
*bpi
;
7968 struct bgp_path_info rmap_path
;
7969 struct bgp_dest
*bn
;
7971 struct attr
*new_attr
;
7973 route_map_result_t ret
;
7974 struct bgp_redist
*red
;
7976 /* Make default attribute. */
7977 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7979 * This must not be NULL to satisfy Coverity SA
7981 assert(attr
.aspath
);
7984 case NEXTHOP_TYPE_IFINDEX
:
7986 case NEXTHOP_TYPE_IPV4
:
7987 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7988 attr
.nexthop
= nexthop
->ipv4
;
7990 case NEXTHOP_TYPE_IPV6
:
7991 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7992 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7993 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7995 case NEXTHOP_TYPE_BLACKHOLE
:
7996 switch (p
->family
) {
7998 attr
.nexthop
.s_addr
= INADDR_ANY
;
8001 memset(&attr
.mp_nexthop_global
, 0,
8002 sizeof(attr
.mp_nexthop_global
));
8003 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8008 attr
.nh_ifindex
= ifindex
;
8011 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8014 afi
= family2afi(p
->family
);
8016 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8018 struct attr attr_new
;
8020 /* Copy attribute for modification. */
8023 if (red
->redist_metric_flag
)
8024 attr_new
.med
= red
->redist_metric
;
8026 /* Apply route-map. */
8027 if (red
->rmap
.name
) {
8028 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8029 rmap_path
.peer
= bgp
->peer_self
;
8030 rmap_path
.attr
= &attr_new
;
8032 SET_FLAG(bgp
->peer_self
->rmap_type
,
8033 PEER_RMAP_TYPE_REDISTRIBUTE
);
8035 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8037 bgp
->peer_self
->rmap_type
= 0;
8039 if (ret
== RMAP_DENYMATCH
) {
8040 /* Free uninterned attribute. */
8041 bgp_attr_flush(&attr_new
);
8043 /* Unintern original. */
8044 aspath_unintern(&attr
.aspath
);
8045 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8050 if (bgp_in_graceful_shutdown(bgp
))
8051 bgp_attr_add_gshut_community(&attr_new
);
8053 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8054 SAFI_UNICAST
, p
, NULL
);
8056 new_attr
= bgp_attr_intern(&attr_new
);
8058 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8059 if (bpi
->peer
== bgp
->peer_self
8060 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8064 /* Ensure the (source route) type is updated. */
8066 if (attrhash_cmp(bpi
->attr
, new_attr
)
8067 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8068 bgp_attr_unintern(&new_attr
);
8069 aspath_unintern(&attr
.aspath
);
8070 bgp_dest_unlock_node(bn
);
8073 /* The attribute is changed. */
8074 bgp_path_info_set_flag(bn
, bpi
,
8075 BGP_PATH_ATTR_CHANGED
);
8077 /* Rewrite BGP route information. */
8078 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8079 bgp_path_info_restore(bn
, bpi
);
8081 bgp_aggregate_decrement(
8082 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8083 bgp_attr_unintern(&bpi
->attr
);
8084 bpi
->attr
= new_attr
;
8085 bpi
->uptime
= bgp_clock();
8087 /* Process change. */
8088 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8090 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8091 bgp_dest_unlock_node(bn
);
8092 aspath_unintern(&attr
.aspath
);
8094 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8096 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8098 vpn_leak_from_vrf_update(
8099 bgp_get_default(), bgp
, bpi
);
8105 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8106 bgp
->peer_self
, new_attr
, bn
);
8107 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8109 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8110 bgp_path_info_add(bn
, new);
8111 bgp_dest_unlock_node(bn
);
8112 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8114 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8115 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8117 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8121 /* Unintern original. */
8122 aspath_unintern(&attr
.aspath
);
8125 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8126 unsigned short instance
)
8129 struct bgp_dest
*dest
;
8130 struct bgp_path_info
*pi
;
8131 struct bgp_redist
*red
;
8133 afi
= family2afi(p
->family
);
8135 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8137 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8138 SAFI_UNICAST
, p
, NULL
);
8140 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8141 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8145 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8146 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8148 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8151 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8152 bgp_path_info_delete(dest
, pi
);
8153 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8155 bgp_dest_unlock_node(dest
);
8159 /* Withdraw specified route type's route. */
8160 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8161 unsigned short instance
)
8163 struct bgp_dest
*dest
;
8164 struct bgp_path_info
*pi
;
8165 struct bgp_table
*table
;
8167 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8169 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8170 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8171 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8172 && pi
->instance
== instance
)
8176 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8177 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8179 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8182 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8183 pi
, afi
, SAFI_UNICAST
);
8184 bgp_path_info_delete(dest
, pi
);
8185 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8190 /* Static function to display route. */
8191 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
8192 json_object
*json
, bool wide
)
8198 if (p
->family
== AF_INET
) {
8200 len
= vty_out(vty
, "%pFX", p
);
8202 json_object_string_add(json
, "prefix",
8203 inet_ntop(p
->family
,
8206 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8207 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8208 json_object_string_add(json
, "network", buf2
);
8210 } else if (p
->family
== AF_ETHERNET
) {
8211 len
= vty_out(vty
, "%pFX", p
);
8212 } else if (p
->family
== AF_EVPN
) {
8214 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8216 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8217 } else if (p
->family
== AF_FLOWSPEC
) {
8218 route_vty_out_flowspec(vty
, p
, NULL
,
8220 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8221 NLRI_STRING_FORMAT_MIN
, json
);
8224 len
= vty_out(vty
, "%pFX", p
);
8226 json_object_string_add(json
, "prefix",
8227 inet_ntop(p
->family
,
8230 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8231 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8232 json_object_string_add(json
, "network", buf2
);
8237 len
= wide
? (45 - len
) : (17 - len
);
8239 vty_out(vty
, "\n%*s", 20, " ");
8241 vty_out(vty
, "%*s", len
, " ");
8245 enum bgp_display_type
{
8250 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8253 case bgp_path_selection_none
:
8254 return "Nothing to Select";
8255 case bgp_path_selection_first
:
8256 return "First path received";
8257 case bgp_path_selection_evpn_sticky_mac
:
8258 return "EVPN Sticky Mac";
8259 case bgp_path_selection_evpn_seq
:
8260 return "EVPN sequence number";
8261 case bgp_path_selection_evpn_lower_ip
:
8262 return "EVPN lower IP";
8263 case bgp_path_selection_evpn_local_path
:
8264 return "EVPN local ES path";
8265 case bgp_path_selection_evpn_non_proxy
:
8266 return "EVPN non proxy";
8267 case bgp_path_selection_weight
:
8269 case bgp_path_selection_local_pref
:
8270 return "Local Pref";
8271 case bgp_path_selection_local_route
:
8272 return "Local Route";
8273 case bgp_path_selection_confed_as_path
:
8274 return "Confederation based AS Path";
8275 case bgp_path_selection_as_path
:
8277 case bgp_path_selection_origin
:
8279 case bgp_path_selection_med
:
8281 case bgp_path_selection_peer
:
8283 case bgp_path_selection_confed
:
8284 return "Confed Peer Type";
8285 case bgp_path_selection_igp_metric
:
8286 return "IGP Metric";
8287 case bgp_path_selection_older
:
8288 return "Older Path";
8289 case bgp_path_selection_router_id
:
8291 case bgp_path_selection_cluster_length
:
8292 return "Cluster length";
8293 case bgp_path_selection_stale
:
8294 return "Path Staleness";
8295 case bgp_path_selection_local_configured
:
8296 return "Locally configured route";
8297 case bgp_path_selection_neighbor_ip
:
8298 return "Neighbor IP";
8299 case bgp_path_selection_default
:
8300 return "Nothing left to compare";
8302 return "Invalid (internal error)";
8305 /* Print the short form route status for a bgp_path_info */
8306 static void route_vty_short_status_out(struct vty
*vty
,
8307 struct bgp_path_info
*path
,
8308 json_object
*json_path
)
8312 /* Route status display. */
8313 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8314 json_object_boolean_true_add(json_path
, "removed");
8316 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8317 json_object_boolean_true_add(json_path
, "stale");
8319 if (path
->extra
&& bgp_path_suppressed(path
))
8320 json_object_boolean_true_add(json_path
, "suppressed");
8322 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8323 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8324 json_object_boolean_true_add(json_path
, "valid");
8327 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8328 json_object_boolean_true_add(json_path
, "history");
8330 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8331 json_object_boolean_true_add(json_path
, "damped");
8333 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8334 json_object_boolean_true_add(json_path
, "bestpath");
8335 json_object_string_add(json_path
, "selectionReason",
8336 bgp_path_selection_reason2str(
8337 path
->net
->reason
));
8340 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8341 json_object_boolean_true_add(json_path
, "multipath");
8343 /* Internal route. */
8344 if ((path
->peer
->as
)
8345 && (path
->peer
->as
== path
->peer
->local_as
))
8346 json_object_string_add(json_path
, "pathFrom",
8349 json_object_string_add(json_path
, "pathFrom",
8355 /* Route status display. */
8356 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8358 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8360 else if (bgp_path_suppressed(path
))
8362 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8363 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8369 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8371 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8373 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8375 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8380 /* Internal route. */
8381 if (path
->peer
&& (path
->peer
->as
)
8382 && (path
->peer
->as
== path
->peer
->local_as
))
8388 static char *bgp_nexthop_hostname(struct peer
*peer
,
8389 struct bgp_nexthop_cache
*bnc
)
8392 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8393 return peer
->hostname
;
8397 /* called from terminal list command */
8398 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8399 struct bgp_path_info
*path
, int display
, safi_t safi
,
8400 json_object
*json_paths
, bool wide
)
8403 struct attr
*attr
= path
->attr
;
8404 json_object
*json_path
= NULL
;
8405 json_object
*json_nexthops
= NULL
;
8406 json_object
*json_nexthop_global
= NULL
;
8407 json_object
*json_nexthop_ll
= NULL
;
8408 json_object
*json_ext_community
= NULL
;
8409 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8411 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8412 bool nexthop_othervrf
= false;
8413 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8414 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8415 char *nexthop_hostname
=
8416 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8417 char esi_buf
[ESI_STR_LEN
];
8420 json_path
= json_object_new_object();
8422 /* short status lead text */
8423 route_vty_short_status_out(vty
, path
, json_path
);
8426 /* print prefix and mask */
8428 route_vty_out_route(p
, vty
, json_path
, wide
);
8430 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8432 route_vty_out_route(p
, vty
, json_path
, wide
);
8436 * If vrf id of nexthop is different from that of prefix,
8437 * set up printable string to append
8439 if (path
->extra
&& path
->extra
->bgp_orig
) {
8440 const char *self
= "";
8445 nexthop_othervrf
= true;
8446 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8448 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8449 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8450 "@%s%s", VRFID_NONE_STR
, self
);
8452 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8453 path
->extra
->bgp_orig
->vrf_id
, self
);
8455 if (path
->extra
->bgp_orig
->inst_type
8456 != BGP_INSTANCE_TYPE_DEFAULT
)
8458 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8460 const char *self
= "";
8465 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8469 * For ENCAP and EVPN routes, nexthop address family is not
8470 * neccessarily the same as the prefix address family.
8471 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8472 * EVPN routes are also exchanged with a MP nexthop. Currently,
8474 * is only IPv4, the value will be present in either
8476 * attr->mp_nexthop_global_in
8478 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8481 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8485 snprintf(nexthop
, sizeof(nexthop
), "%s",
8486 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8490 snprintf(nexthop
, sizeof(nexthop
), "%s",
8491 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8495 snprintf(nexthop
, sizeof(nexthop
), "?");
8500 json_nexthop_global
= json_object_new_object();
8502 json_object_string_add(json_nexthop_global
, "ip",
8505 if (path
->peer
->hostname
)
8506 json_object_string_add(json_nexthop_global
,
8508 path
->peer
->hostname
);
8510 json_object_string_add(json_nexthop_global
, "afi",
8511 (af
== AF_INET
) ? "ipv4"
8513 json_object_boolean_true_add(json_nexthop_global
,
8516 if (nexthop_hostname
)
8517 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8518 nexthop_hostname
, vrf_id_str
);
8520 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8522 len
= wide
? (41 - len
) : (16 - len
);
8524 vty_out(vty
, "\n%*s", 36, " ");
8526 vty_out(vty
, "%*s", len
, " ");
8528 } else if (safi
== SAFI_EVPN
) {
8530 char buf
[BUFSIZ
] = {0};
8532 json_nexthop_global
= json_object_new_object();
8534 json_object_string_add(json_nexthop_global
, "ip",
8536 &attr
->nexthop
, buf
,
8539 if (path
->peer
->hostname
)
8540 json_object_string_add(json_nexthop_global
,
8542 path
->peer
->hostname
);
8544 json_object_string_add(json_nexthop_global
, "afi",
8546 json_object_boolean_true_add(json_nexthop_global
,
8549 if (nexthop_hostname
)
8550 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8551 nexthop_hostname
, vrf_id_str
);
8553 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8556 len
= wide
? (41 - len
) : (16 - len
);
8558 vty_out(vty
, "\n%*s", 36, " ");
8560 vty_out(vty
, "%*s", len
, " ");
8562 } else if (safi
== SAFI_FLOWSPEC
) {
8563 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8565 char buf
[BUFSIZ
] = {0};
8567 json_nexthop_global
= json_object_new_object();
8569 json_object_string_add(json_nexthop_global
,
8571 json_object_string_add(
8572 json_nexthop_global
, "ip",
8573 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8576 if (path
->peer
->hostname
)
8577 json_object_string_add(
8578 json_nexthop_global
, "hostname",
8579 path
->peer
->hostname
);
8581 json_object_boolean_true_add(
8582 json_nexthop_global
,
8585 if (nexthop_hostname
)
8586 len
= vty_out(vty
, "%pI4(%s)%s",
8591 len
= vty_out(vty
, "%pI4%s",
8595 len
= wide
? (41 - len
) : (16 - len
);
8597 vty_out(vty
, "\n%*s", 36, " ");
8599 vty_out(vty
, "%*s", len
, " ");
8602 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8604 char buf
[BUFSIZ
] = {0};
8606 json_nexthop_global
= json_object_new_object();
8608 json_object_string_add(json_nexthop_global
, "ip",
8610 &attr
->nexthop
, buf
,
8613 if (path
->peer
->hostname
)
8614 json_object_string_add(json_nexthop_global
,
8616 path
->peer
->hostname
);
8618 json_object_string_add(json_nexthop_global
, "afi",
8620 json_object_boolean_true_add(json_nexthop_global
,
8623 if (nexthop_hostname
)
8624 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8625 nexthop_hostname
, vrf_id_str
);
8627 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8630 len
= wide
? (41 - len
) : (16 - len
);
8632 vty_out(vty
, "\n%*s", 36, " ");
8634 vty_out(vty
, "%*s", len
, " ");
8639 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8643 json_nexthop_global
= json_object_new_object();
8644 json_object_string_add(
8645 json_nexthop_global
, "ip",
8646 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8649 if (path
->peer
->hostname
)
8650 json_object_string_add(json_nexthop_global
,
8652 path
->peer
->hostname
);
8654 json_object_string_add(json_nexthop_global
, "afi",
8656 json_object_string_add(json_nexthop_global
, "scope",
8659 /* We display both LL & GL if both have been
8661 if ((attr
->mp_nexthop_len
8662 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8663 || (path
->peer
->conf_if
)) {
8664 json_nexthop_ll
= json_object_new_object();
8665 json_object_string_add(
8666 json_nexthop_ll
, "ip",
8668 &attr
->mp_nexthop_local
, buf
,
8671 if (path
->peer
->hostname
)
8672 json_object_string_add(
8673 json_nexthop_ll
, "hostname",
8674 path
->peer
->hostname
);
8676 json_object_string_add(json_nexthop_ll
, "afi",
8678 json_object_string_add(json_nexthop_ll
, "scope",
8681 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8682 &attr
->mp_nexthop_local
)
8684 && !attr
->mp_nexthop_prefer_global
)
8685 json_object_boolean_true_add(
8686 json_nexthop_ll
, "used");
8688 json_object_boolean_true_add(
8689 json_nexthop_global
, "used");
8691 json_object_boolean_true_add(
8692 json_nexthop_global
, "used");
8694 /* Display LL if LL/Global both in table unless
8695 * prefer-global is set */
8696 if (((attr
->mp_nexthop_len
8697 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8698 && !attr
->mp_nexthop_prefer_global
)
8699 || (path
->peer
->conf_if
)) {
8700 if (path
->peer
->conf_if
) {
8701 len
= vty_out(vty
, "%s",
8702 path
->peer
->conf_if
);
8703 /* len of IPv6 addr + max len of def
8705 len
= wide
? (41 - len
) : (16 - len
);
8708 vty_out(vty
, "\n%*s", 36, " ");
8710 vty_out(vty
, "%*s", len
, " ");
8712 if (nexthop_hostname
)
8715 &attr
->mp_nexthop_local
,
8721 &attr
->mp_nexthop_local
,
8724 len
= wide
? (41 - len
) : (16 - len
);
8727 vty_out(vty
, "\n%*s", 36, " ");
8729 vty_out(vty
, "%*s", len
, " ");
8732 if (nexthop_hostname
)
8733 len
= vty_out(vty
, "%pI6(%s)%s",
8734 &attr
->mp_nexthop_global
,
8738 len
= vty_out(vty
, "%pI6%s",
8739 &attr
->mp_nexthop_global
,
8742 len
= wide
? (41 - len
) : (16 - len
);
8745 vty_out(vty
, "\n%*s", 36, " ");
8747 vty_out(vty
, "%*s", len
, " ");
8753 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8755 json_object_int_add(json_path
, "metric", attr
->med
);
8757 vty_out(vty
, "%7u", attr
->med
);
8759 vty_out(vty
, "%10u", attr
->med
);
8760 else if (!json_paths
) {
8762 vty_out(vty
, "%*s", 7, " ");
8764 vty_out(vty
, "%*s", 10, " ");
8768 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8770 json_object_int_add(json_path
, "locPrf",
8773 vty_out(vty
, "%7u", attr
->local_pref
);
8774 else if (!json_paths
)
8778 json_object_int_add(json_path
, "weight", attr
->weight
);
8780 vty_out(vty
, "%7u ", attr
->weight
);
8784 json_object_string_add(
8785 json_path
, "peerId",
8786 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8792 json_object_string_add(json_path
, "path",
8795 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8800 json_object_string_add(json_path
, "origin",
8801 bgp_origin_long_str
[attr
->origin
]);
8803 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8806 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8807 json_object_string_add(json_path
, "esi",
8808 esi_to_str(&attr
->esi
,
8809 esi_buf
, sizeof(esi_buf
)));
8811 if (safi
== SAFI_EVPN
&&
8812 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8813 json_ext_community
= json_object_new_object();
8814 json_object_string_add(json_ext_community
,
8816 attr
->ecommunity
->str
);
8817 json_object_object_add(json_path
,
8818 "extendedCommunity",
8819 json_ext_community
);
8823 json_object_boolean_true_add(json_path
,
8824 "announceNexthopSelf");
8825 if (nexthop_othervrf
) {
8826 json_object_string_add(json_path
, "nhVrfName",
8829 json_object_int_add(json_path
, "nhVrfId",
8830 ((nexthop_vrfid
== VRF_UNKNOWN
)
8832 : (int)nexthop_vrfid
));
8837 if (json_nexthop_global
|| json_nexthop_ll
) {
8838 json_nexthops
= json_object_new_array();
8840 if (json_nexthop_global
)
8841 json_object_array_add(json_nexthops
,
8842 json_nexthop_global
);
8844 if (json_nexthop_ll
)
8845 json_object_array_add(json_nexthops
,
8848 json_object_object_add(json_path
, "nexthops",
8852 json_object_array_add(json_paths
, json_path
);
8856 if (safi
== SAFI_EVPN
) {
8857 struct bgp_path_es_info
*path_es_info
= NULL
;
8860 path_es_info
= path
->extra
->es_info
;
8862 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8863 /* XXX - add these params to the json out */
8864 vty_out(vty
, "%*s", 20, " ");
8865 vty_out(vty
, "ESI:%s",
8866 esi_to_str(&attr
->esi
, esi_buf
,
8868 if (path_es_info
&& path_es_info
->es
)
8869 vty_out(vty
, " VNI: %u",
8874 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8875 vty_out(vty
, "%*s", 20, " ");
8876 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8880 #ifdef ENABLE_BGP_VNC
8881 /* prints an additional line, indented, with VNC info, if
8883 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8884 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8889 /* called from terminal list command */
8890 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8891 struct attr
*attr
, safi_t safi
, bool use_json
,
8892 json_object
*json_ar
, bool wide
)
8894 json_object
*json_status
= NULL
;
8895 json_object
*json_net
= NULL
;
8899 /* Route status display. */
8901 json_status
= json_object_new_object();
8902 json_net
= json_object_new_object();
8909 /* print prefix and mask */
8911 if (safi
== SAFI_EVPN
)
8912 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8913 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8914 json_object_string_add(
8915 json_net
, "addrPrefix",
8916 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8918 json_object_int_add(json_net
, "prefixLen",
8920 prefix2str(p
, buff
, PREFIX_STRLEN
);
8921 json_object_string_add(json_net
, "network", buff
);
8924 route_vty_out_route(p
, vty
, NULL
, wide
);
8926 /* Print attribute */
8929 char buf
[BUFSIZ
] = {0};
8931 if (p
->family
== AF_INET
8932 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8933 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8934 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8935 json_object_string_add(
8936 json_net
, "nextHop",
8939 &attr
->mp_nexthop_global_in
,
8942 json_object_string_add(
8943 json_net
, "nextHop",
8945 &attr
->nexthop
, buf
,
8947 } else if (p
->family
== AF_INET6
8948 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8951 json_object_string_add(
8952 json_net
, "nextHopGlobal",
8954 &attr
->mp_nexthop_global
, buf
,
8956 } else if (p
->family
== AF_EVPN
8957 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8958 char buf
[BUFSIZ
] = {0};
8960 json_object_string_add(
8961 json_net
, "nextHop",
8963 &attr
->mp_nexthop_global_in
,
8968 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8969 json_object_int_add(json_net
, "metric",
8972 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8973 json_object_int_add(json_net
, "locPrf",
8976 json_object_int_add(json_net
, "weight", attr
->weight
);
8980 json_object_string_add(json_net
, "path",
8984 json_object_string_add(json_net
, "bgpOriginCode",
8985 bgp_origin_str
[attr
->origin
]);
8987 if (p
->family
== AF_INET
8988 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8989 || safi
== SAFI_EVPN
8990 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8991 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8992 || safi
== SAFI_EVPN
)
8993 vty_out(vty
, "%-16pI4",
8994 &attr
->mp_nexthop_global_in
);
8996 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
8998 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
8999 } else if (p
->family
== AF_INET6
9000 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9006 &attr
->mp_nexthop_global
, buf
,
9008 len
= wide
? (41 - len
) : (16 - len
);
9010 vty_out(vty
, "\n%*s", 36, " ");
9012 vty_out(vty
, "%*s", len
, " ");
9015 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9017 vty_out(vty
, "%7u", attr
->med
);
9019 vty_out(vty
, "%10u", attr
->med
);
9025 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9026 vty_out(vty
, "%7u", attr
->local_pref
);
9030 vty_out(vty
, "%7u ", attr
->weight
);
9034 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9037 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9041 json_object_boolean_true_add(json_status
, "*");
9042 json_object_boolean_true_add(json_status
, ">");
9043 json_object_object_add(json_net
, "appliedStatusSymbols",
9046 prefix2str(p
, buff
, PREFIX_STRLEN
);
9047 json_object_object_add(json_ar
, buff
, json_net
);
9052 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9053 struct bgp_path_info
*path
, int display
, safi_t safi
,
9056 json_object
*json_out
= NULL
;
9058 mpls_label_t label
= MPLS_INVALID_LABEL
;
9064 json_out
= json_object_new_object();
9066 /* short status lead text */
9067 route_vty_short_status_out(vty
, path
, json_out
);
9069 /* print prefix and mask */
9072 route_vty_out_route(p
, vty
, NULL
, false);
9074 vty_out(vty
, "%*s", 17, " ");
9077 /* Print attribute */
9079 if (((p
->family
== AF_INET
)
9080 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9081 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9082 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9083 char buf
[BUFSIZ
] = {0};
9085 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9086 || safi
== SAFI_EVPN
) {
9088 json_object_string_add(
9089 json_out
, "mpNexthopGlobalIn",
9091 &attr
->mp_nexthop_global_in
,
9094 vty_out(vty
, "%-16pI4",
9095 &attr
->mp_nexthop_global_in
);
9098 json_object_string_add(
9099 json_out
, "nexthop",
9100 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9103 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9105 } else if (((p
->family
== AF_INET6
)
9106 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9107 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9108 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9111 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9113 json_object_string_add(
9114 json_out
, "mpNexthopGlobalIn",
9116 &attr
->mp_nexthop_global
,
9117 buf_a
, sizeof(buf_a
)));
9121 &attr
->mp_nexthop_global
,
9122 buf_a
, sizeof(buf_a
)));
9123 } else if (attr
->mp_nexthop_len
9124 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9125 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9126 &attr
->mp_nexthop_global
,
9127 &attr
->mp_nexthop_local
);
9129 json_object_string_add(json_out
,
9130 "mpNexthopGlobalLocal",
9133 vty_out(vty
, "%s", buf_a
);
9137 label
= decode_label(&path
->extra
->label
[0]);
9139 if (bgp_is_valid_label(&label
)) {
9141 json_object_int_add(json_out
, "notag", label
);
9142 json_object_array_add(json
, json_out
);
9144 vty_out(vty
, "notag/%d", label
);
9150 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9151 struct bgp_path_info
*path
, int display
,
9152 json_object
*json_paths
)
9155 char buf
[BUFSIZ
] = {0};
9156 json_object
*json_path
= NULL
;
9157 json_object
*json_nexthop
= NULL
;
9158 json_object
*json_overlay
= NULL
;
9164 json_path
= json_object_new_object();
9165 json_overlay
= json_object_new_object();
9166 json_nexthop
= json_object_new_object();
9169 /* short status lead text */
9170 route_vty_short_status_out(vty
, path
, json_path
);
9172 /* print prefix and mask */
9174 route_vty_out_route(p
, vty
, json_path
, false);
9176 vty_out(vty
, "%*s", 17, " ");
9178 /* Print attribute */
9181 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9185 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9187 vty_out(vty
, "%-16s", buf
);
9189 json_object_string_add(json_nexthop
, "ip", buf
);
9191 json_object_string_add(json_nexthop
, "afi", "ipv4");
9193 json_object_object_add(json_path
, "nexthop",
9198 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9199 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9201 vty_out(vty
, "%s(%s)", buf
, buf1
);
9203 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9205 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9208 json_object_string_add(json_nexthop
, "afi", "ipv6");
9210 json_object_object_add(json_path
, "nexthop",
9218 json_object_string_add(json_nexthop
, "Error",
9219 "Unsupported address-family");
9223 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9225 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9226 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9227 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9228 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9231 vty_out(vty
, "/%s", buf
);
9233 json_object_string_add(json_overlay
, "gw", buf
);
9235 if (attr
->ecommunity
) {
9237 struct ecommunity_val
*routermac
= ecommunity_lookup(
9238 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9239 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9242 mac
= ecom_mac2str((char *)routermac
->val
);
9245 vty_out(vty
, "/%s", mac
);
9247 json_object_string_add(json_overlay
, "rmac",
9250 XFREE(MTYPE_TMP
, mac
);
9257 json_object_object_add(json_path
, "overlay", json_overlay
);
9259 json_object_array_add(json_paths
, json_path
);
9263 /* dampening route */
9264 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9265 struct bgp_path_info
*path
, int display
,
9266 afi_t afi
, safi_t safi
, bool use_json
,
9271 char timebuf
[BGP_UPTIME_LEN
];
9273 /* short status lead text */
9274 route_vty_short_status_out(vty
, path
, json
);
9276 /* print prefix and mask */
9279 route_vty_out_route(p
, vty
, NULL
, false);
9281 vty_out(vty
, "%*s", 17, " ");
9284 len
= vty_out(vty
, "%s", path
->peer
->host
);
9288 vty_out(vty
, "\n%*s", 34, " ");
9291 json_object_int_add(json
, "peerHost", len
);
9293 vty_out(vty
, "%*s", len
, " ");
9297 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9298 safi
, use_json
, json
);
9301 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9302 BGP_UPTIME_LEN
, afi
, safi
,
9305 /* Print attribute */
9311 json_object_string_add(json
, "asPath",
9314 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9319 json_object_string_add(json
, "origin",
9320 bgp_origin_str
[attr
->origin
]);
9322 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9329 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9330 struct bgp_path_info
*path
, int display
,
9331 afi_t afi
, safi_t safi
, bool use_json
,
9335 struct bgp_damp_info
*bdi
;
9336 char timebuf
[BGP_UPTIME_LEN
];
9342 bdi
= path
->extra
->damp_info
;
9344 /* short status lead text */
9345 route_vty_short_status_out(vty
, path
, json
);
9347 /* print prefix and mask */
9350 route_vty_out_route(p
, vty
, NULL
, false);
9352 vty_out(vty
, "%*s", 17, " ");
9355 len
= vty_out(vty
, "%s", path
->peer
->host
);
9359 vty_out(vty
, "\n%*s", 33, " ");
9362 json_object_int_add(json
, "peerHost", len
);
9364 vty_out(vty
, "%*s", len
, " ");
9367 len
= vty_out(vty
, "%d", bdi
->flap
);
9374 json_object_int_add(json
, "bdiFlap", len
);
9376 vty_out(vty
, "%*s", len
, " ");
9380 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9383 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9384 BGP_UPTIME_LEN
, 0, NULL
));
9386 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9387 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9389 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9390 BGP_UPTIME_LEN
, afi
, safi
,
9394 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9395 BGP_UPTIME_LEN
, afi
,
9396 safi
, use_json
, json
));
9399 vty_out(vty
, "%*s ", 8, " ");
9402 /* Print attribute */
9408 json_object_string_add(json
, "asPath",
9411 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9416 json_object_string_add(json
, "origin",
9417 bgp_origin_str
[attr
->origin
]);
9419 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9425 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9426 int *first
, const char *header
,
9427 json_object
*json_adv_to
)
9429 char buf1
[INET6_ADDRSTRLEN
];
9430 json_object
*json_peer
= NULL
;
9433 /* 'advertised-to' is a dictionary of peers we have advertised
9435 * prefix too. The key is the peer's IP or swpX, the value is
9437 * hostname if we know it and "" if not.
9439 json_peer
= json_object_new_object();
9442 json_object_string_add(json_peer
, "hostname",
9446 json_object_object_add(json_adv_to
, peer
->conf_if
,
9449 json_object_object_add(
9451 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9455 vty_out(vty
, "%s", header
);
9460 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9462 vty_out(vty
, " %s(%s)", peer
->hostname
,
9465 vty_out(vty
, " %s(%s)", peer
->hostname
,
9466 sockunion2str(&peer
->su
, buf1
,
9470 vty_out(vty
, " %s", peer
->conf_if
);
9473 sockunion2str(&peer
->su
, buf1
,
9479 static void route_vty_out_tx_ids(struct vty
*vty
,
9480 struct bgp_addpath_info_data
*d
)
9484 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9485 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9486 d
->addpath_tx_id
[i
],
9487 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9491 static void route_vty_out_detail_es_info(struct vty
*vty
,
9492 struct bgp_path_info
*pi
,
9494 json_object
*json_path
)
9496 char esi_buf
[ESI_STR_LEN
];
9497 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9498 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9499 ATTR_ES_PEER_ROUTER
);
9500 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9501 ATTR_ES_PEER_ACTIVE
);
9502 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9503 ATTR_ES_PEER_PROXY
);
9504 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9506 json_object
*json_es_info
= NULL
;
9508 json_object_string_add(
9511 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9512 json_es_info
= json_object_new_object();
9514 json_object_boolean_true_add(
9515 json_es_info
, "localEs");
9517 json_object_boolean_true_add(
9518 json_es_info
, "peerActive");
9520 json_object_boolean_true_add(
9521 json_es_info
, "peerProxy");
9523 json_object_boolean_true_add(
9524 json_es_info
, "peerRouter");
9525 if (attr
->mm_sync_seqnum
)
9526 json_object_int_add(
9527 json_es_info
, "peerSeq",
9528 attr
->mm_sync_seqnum
);
9529 json_object_object_add(
9530 json_path
, "es_info",
9534 if (bgp_evpn_attr_is_sync(attr
))
9536 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9538 es_local
? "local-es":"",
9539 peer_proxy
? "proxy " : "",
9540 peer_active
? "active ":"",
9541 peer_router
? "router ":"",
9542 attr
->mm_sync_seqnum
);
9544 vty_out(vty
, " ESI %s %s\n",
9546 es_local
? "local-es":"");
9550 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
9551 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
9552 afi_t afi
, safi_t safi
, json_object
*json_paths
)
9554 char buf
[INET6_ADDRSTRLEN
];
9556 struct attr
*attr
= path
->attr
;
9557 int sockunion_vty_out(struct vty
*, union sockunion
*);
9559 json_object
*json_bestpath
= NULL
;
9560 json_object
*json_cluster_list
= NULL
;
9561 json_object
*json_cluster_list_list
= NULL
;
9562 json_object
*json_ext_community
= NULL
;
9563 json_object
*json_last_update
= NULL
;
9564 json_object
*json_pmsi
= NULL
;
9565 json_object
*json_nexthop_global
= NULL
;
9566 json_object
*json_nexthop_ll
= NULL
;
9567 json_object
*json_nexthops
= NULL
;
9568 json_object
*json_path
= NULL
;
9569 json_object
*json_peer
= NULL
;
9570 json_object
*json_string
= NULL
;
9571 json_object
*json_adv_to
= NULL
;
9573 struct listnode
*node
, *nnode
;
9575 int addpath_capable
;
9577 unsigned int first_as
;
9579 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9581 char *nexthop_hostname
=
9582 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9583 int rpki_validation_state
= 0;
9586 json_path
= json_object_new_object();
9587 json_peer
= json_object_new_object();
9588 json_nexthop_global
= json_object_new_object();
9595 if (path
->extra
&& path
->extra
->num_labels
) {
9596 bgp_evpn_label2str(path
->extra
->label
,
9597 path
->extra
->num_labels
, tag_buf
,
9600 if (safi
== SAFI_EVPN
) {
9602 vty_out(vty
, " Route %pFX",
9603 (struct prefix_evpn
*)
9604 bgp_dest_get_prefix(bn
));
9605 if (tag_buf
[0] != '\0')
9606 vty_out(vty
, " VNI %s", tag_buf
);
9610 json_object_string_add(json_path
, "VNI",
9615 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9616 struct bgp_path_info
*parent_ri
;
9617 struct bgp_dest
*dest
, *pdest
;
9619 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9620 dest
= parent_ri
->net
;
9621 if (dest
&& dest
->pdest
) {
9622 pdest
= dest
->pdest
;
9624 (struct prefix_rd
*)bgp_dest_get_prefix(
9626 buf1
, sizeof(buf1
));
9627 if (is_pi_family_evpn(parent_ri
)) {
9629 " Imported from %s:%pFX, VNI %s\n",
9631 (struct prefix_evpn
*)
9632 bgp_dest_get_prefix(
9637 " Imported from %s:%pFX\n",
9639 (struct prefix_evpn
*)
9640 bgp_dest_get_prefix(
9646 /* Line1 display AS-path, Aggregator */
9649 if (!attr
->aspath
->json
)
9650 aspath_str_update(attr
->aspath
, true);
9651 json_object_lock(attr
->aspath
->json
);
9652 json_object_object_add(json_path
, "aspath",
9653 attr
->aspath
->json
);
9655 if (attr
->aspath
->segments
)
9656 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9658 vty_out(vty
, " Local");
9662 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9664 json_object_boolean_true_add(json_path
, "removed");
9666 vty_out(vty
, ", (removed)");
9669 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9671 json_object_boolean_true_add(json_path
, "stale");
9673 vty_out(vty
, ", (stale)");
9676 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9678 char buf
[BUFSIZ
] = {0};
9680 json_object_int_add(json_path
, "aggregatorAs",
9681 attr
->aggregator_as
);
9682 json_object_string_add(json_path
, "aggregatorId",
9684 &attr
->aggregator_addr
,
9687 vty_out(vty
, ", (aggregated by %u %pI4)",
9688 attr
->aggregator_as
, &attr
->aggregator_addr
);
9692 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9693 PEER_FLAG_REFLECTOR_CLIENT
)) {
9695 json_object_boolean_true_add(json_path
,
9696 "rxedFromRrClient");
9698 vty_out(vty
, ", (Received from a RR-client)");
9701 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9702 PEER_FLAG_RSERVER_CLIENT
)) {
9704 json_object_boolean_true_add(json_path
,
9705 "rxedFromRsClient");
9707 vty_out(vty
, ", (Received from a RS-client)");
9710 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9712 json_object_boolean_true_add(json_path
,
9713 "dampeningHistoryEntry");
9715 vty_out(vty
, ", (history entry)");
9716 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9718 json_object_boolean_true_add(json_path
,
9719 "dampeningSuppressed");
9721 vty_out(vty
, ", (suppressed due to dampening)");
9727 /* Line2 display Next-hop, Neighbor, Router-id */
9728 /* Display the nexthop */
9729 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9731 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9732 || bn_p
->family
== AF_EVPN
)
9733 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9734 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9735 char buf
[BUFSIZ
] = {0};
9737 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9738 || safi
== SAFI_EVPN
) {
9740 json_object_string_add(
9741 json_nexthop_global
, "ip",
9743 &attr
->mp_nexthop_global_in
,
9746 if (path
->peer
->hostname
)
9747 json_object_string_add(
9748 json_nexthop_global
, "hostname",
9749 path
->peer
->hostname
);
9751 if (nexthop_hostname
)
9752 vty_out(vty
, " %pI4(%s)",
9753 &attr
->mp_nexthop_global_in
,
9756 vty_out(vty
, " %pI4",
9757 &attr
->mp_nexthop_global_in
);
9761 json_object_string_add(
9762 json_nexthop_global
, "ip",
9763 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9766 if (path
->peer
->hostname
)
9767 json_object_string_add(
9768 json_nexthop_global
, "hostname",
9769 path
->peer
->hostname
);
9771 if (nexthop_hostname
)
9772 vty_out(vty
, " %pI4(%s)",
9776 vty_out(vty
, " %pI4",
9782 json_object_string_add(json_nexthop_global
, "afi",
9786 json_object_string_add(
9787 json_nexthop_global
, "ip",
9788 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9789 buf
, INET6_ADDRSTRLEN
));
9791 if (path
->peer
->hostname
)
9792 json_object_string_add(json_nexthop_global
,
9794 path
->peer
->hostname
);
9796 json_object_string_add(json_nexthop_global
, "afi",
9798 json_object_string_add(json_nexthop_global
, "scope",
9801 if (nexthop_hostname
)
9802 vty_out(vty
, " %pI6(%s)",
9803 &attr
->mp_nexthop_global
,
9806 vty_out(vty
, " %pI6",
9807 &attr
->mp_nexthop_global
);
9811 /* Display the IGP cost or 'inaccessible' */
9812 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9814 json_object_boolean_false_add(json_nexthop_global
,
9817 vty_out(vty
, " (inaccessible)");
9819 if (path
->extra
&& path
->extra
->igpmetric
) {
9821 json_object_int_add(json_nexthop_global
,
9823 path
->extra
->igpmetric
);
9825 vty_out(vty
, " (metric %u)",
9826 path
->extra
->igpmetric
);
9829 /* IGP cost is 0, display this only for json */
9832 json_object_int_add(json_nexthop_global
,
9837 json_object_boolean_true_add(json_nexthop_global
,
9841 /* Display peer "from" output */
9842 /* This path was originated locally */
9843 if (path
->peer
== bgp
->peer_self
) {
9845 if (safi
== SAFI_EVPN
9846 || (bn_p
->family
== AF_INET
9847 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9849 json_object_string_add(json_peer
, "peerId",
9852 vty_out(vty
, " from 0.0.0.0 ");
9855 json_object_string_add(json_peer
, "peerId",
9858 vty_out(vty
, " from :: ");
9862 char buf
[BUFSIZ
] = {0};
9864 json_object_string_add(json_peer
, "routerId",
9866 &bgp
->router_id
, buf
,
9869 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
9873 /* We RXed this path from one of our peers */
9877 json_object_string_add(json_peer
, "peerId",
9878 sockunion2str(&path
->peer
->su
,
9881 json_object_string_add(json_peer
, "routerId",
9883 &path
->peer
->remote_id
,
9884 buf1
, sizeof(buf1
)));
9886 if (path
->peer
->hostname
)
9887 json_object_string_add(json_peer
, "hostname",
9888 path
->peer
->hostname
);
9890 if (path
->peer
->domainname
)
9891 json_object_string_add(json_peer
, "domainname",
9892 path
->peer
->domainname
);
9894 if (path
->peer
->conf_if
)
9895 json_object_string_add(json_peer
, "interface",
9896 path
->peer
->conf_if
);
9898 if (path
->peer
->conf_if
) {
9899 if (path
->peer
->hostname
9900 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9901 BGP_FLAG_SHOW_HOSTNAME
))
9902 vty_out(vty
, " from %s(%s)",
9903 path
->peer
->hostname
,
9904 path
->peer
->conf_if
);
9906 vty_out(vty
, " from %s",
9907 path
->peer
->conf_if
);
9909 if (path
->peer
->hostname
9910 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9911 BGP_FLAG_SHOW_HOSTNAME
))
9912 vty_out(vty
, " from %s(%s)",
9913 path
->peer
->hostname
,
9916 vty_out(vty
, " from %s",
9917 sockunion2str(&path
->peer
->su
,
9922 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9923 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
9925 vty_out(vty
, " (%s)",
9927 &path
->peer
->remote_id
, buf1
,
9933 * Note when vrfid of nexthop is different from that of prefix
9935 if (path
->extra
&& path
->extra
->bgp_orig
) {
9936 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9941 if (path
->extra
->bgp_orig
->inst_type
9942 == BGP_INSTANCE_TYPE_DEFAULT
)
9943 vn
= VRF_DEFAULT_NAME
;
9945 vn
= path
->extra
->bgp_orig
->name
;
9947 json_object_string_add(json_path
, "nhVrfName", vn
);
9949 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9950 json_object_int_add(json_path
, "nhVrfId", -1);
9952 json_object_int_add(json_path
, "nhVrfId",
9953 (int)nexthop_vrfid
);
9956 if (nexthop_vrfid
== VRF_UNKNOWN
)
9957 vty_out(vty
, " vrf ?");
9961 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9962 vty_out(vty
, " vrf %s(%u)",
9963 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9970 json_object_boolean_true_add(json_path
,
9971 "announceNexthopSelf");
9973 vty_out(vty
, " announce-nh-self");
9980 /* display the link-local nexthop */
9981 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9983 json_nexthop_ll
= json_object_new_object();
9984 json_object_string_add(
9985 json_nexthop_ll
, "ip",
9986 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9987 buf
, INET6_ADDRSTRLEN
));
9989 if (path
->peer
->hostname
)
9990 json_object_string_add(json_nexthop_ll
,
9992 path
->peer
->hostname
);
9994 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9995 json_object_string_add(json_nexthop_ll
, "scope",
9998 json_object_boolean_true_add(json_nexthop_ll
,
10001 if (!attr
->mp_nexthop_prefer_global
)
10002 json_object_boolean_true_add(json_nexthop_ll
,
10005 json_object_boolean_true_add(
10006 json_nexthop_global
, "used");
10008 vty_out(vty
, " (%s) %s\n",
10009 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10010 buf
, INET6_ADDRSTRLEN
),
10011 attr
->mp_nexthop_prefer_global
10012 ? "(prefer-global)"
10016 /* If we do not have a link-local nexthop then we must flag the
10017 global as "used" */
10020 json_object_boolean_true_add(json_nexthop_global
,
10024 if (safi
== SAFI_EVPN
&&
10025 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10026 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10029 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10030 * Int/Ext/Local, Atomic, best */
10032 json_object_string_add(json_path
, "origin",
10033 bgp_origin_long_str
[attr
->origin
]);
10035 vty_out(vty
, " Origin %s",
10036 bgp_origin_long_str
[attr
->origin
]);
10038 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10040 json_object_int_add(json_path
, "metric", attr
->med
);
10042 vty_out(vty
, ", metric %u", attr
->med
);
10045 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10047 json_object_int_add(json_path
, "locPrf",
10050 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10053 if (attr
->weight
!= 0) {
10055 json_object_int_add(json_path
, "weight", attr
->weight
);
10057 vty_out(vty
, ", weight %u", attr
->weight
);
10060 if (attr
->tag
!= 0) {
10062 json_object_int_add(json_path
, "tag", attr
->tag
);
10064 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10067 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10069 json_object_boolean_false_add(json_path
, "valid");
10071 vty_out(vty
, ", invalid");
10072 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10074 json_object_boolean_true_add(json_path
, "valid");
10076 vty_out(vty
, ", valid");
10079 if (path
->peer
!= bgp
->peer_self
) {
10080 if (path
->peer
->as
== path
->peer
->local_as
) {
10081 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10083 json_object_string_add(
10085 "confed-internal");
10087 vty_out(vty
, ", confed-internal");
10090 json_object_string_add(
10091 json_peer
, "type", "internal");
10093 vty_out(vty
, ", internal");
10096 if (bgp_confederation_peers_check(bgp
,
10099 json_object_string_add(
10101 "confed-external");
10103 vty_out(vty
, ", confed-external");
10106 json_object_string_add(
10107 json_peer
, "type", "external");
10109 vty_out(vty
, ", external");
10112 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10114 json_object_boolean_true_add(json_path
, "aggregated");
10115 json_object_boolean_true_add(json_path
, "local");
10117 vty_out(vty
, ", aggregated, local");
10119 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10121 json_object_boolean_true_add(json_path
, "sourced");
10123 vty_out(vty
, ", sourced");
10126 json_object_boolean_true_add(json_path
, "sourced");
10127 json_object_boolean_true_add(json_path
, "local");
10129 vty_out(vty
, ", sourced, local");
10133 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10135 json_object_boolean_true_add(json_path
,
10136 "atomicAggregate");
10138 vty_out(vty
, ", atomic-aggregate");
10141 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10142 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10143 && bgp_path_info_mpath_count(path
))) {
10145 json_object_boolean_true_add(json_path
, "multipath");
10147 vty_out(vty
, ", multipath");
10150 // Mark the bestpath(s)
10151 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10152 first_as
= aspath_get_first_as(attr
->aspath
);
10155 if (!json_bestpath
)
10156 json_bestpath
= json_object_new_object();
10157 json_object_int_add(json_bestpath
, "bestpathFromAs",
10161 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10163 vty_out(vty
, ", bestpath-from-AS Local");
10167 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10169 if (!json_bestpath
)
10170 json_bestpath
= json_object_new_object();
10171 json_object_boolean_true_add(json_bestpath
, "overall");
10172 json_object_string_add(
10173 json_bestpath
, "selectionReason",
10174 bgp_path_selection_reason2str(bn
->reason
));
10176 vty_out(vty
, ", best");
10177 vty_out(vty
, " (%s)",
10178 bgp_path_selection_reason2str(bn
->reason
));
10182 const struct prefix
*p
= bgp_dest_get_prefix(bn
);
10183 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
10184 rpki_validation_state
= hook_call(bgp_rpki_prefix_status
,
10185 path
->peer
, path
->attr
, p
);
10186 if (rpki_validation_state
) {
10188 json_object_string_add(
10189 json_path
, "rpkiValidationState",
10190 bgp_rpki_validation2str(rpki_validation_state
));
10192 vty_out(vty
, ", validation-state: %s",
10193 bgp_rpki_validation2str(rpki_validation_state
));
10197 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10200 vty_out(vty
, "\n");
10202 /* Line 4 display Community */
10203 if (attr
->community
) {
10205 if (!attr
->community
->json
)
10206 community_str(attr
->community
, true);
10207 json_object_lock(attr
->community
->json
);
10208 json_object_object_add(json_path
, "community",
10209 attr
->community
->json
);
10211 vty_out(vty
, " Community: %s\n",
10212 attr
->community
->str
);
10216 /* Line 5 display Extended-community */
10217 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10219 json_ext_community
= json_object_new_object();
10220 json_object_string_add(json_ext_community
, "string",
10221 attr
->ecommunity
->str
);
10222 json_object_object_add(json_path
, "extendedCommunity",
10223 json_ext_community
);
10225 vty_out(vty
, " Extended Community: %s\n",
10226 attr
->ecommunity
->str
);
10230 /* Line 6 display Large community */
10231 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10233 if (!attr
->lcommunity
->json
)
10234 lcommunity_str(attr
->lcommunity
, true);
10235 json_object_lock(attr
->lcommunity
->json
);
10236 json_object_object_add(json_path
, "largeCommunity",
10237 attr
->lcommunity
->json
);
10239 vty_out(vty
, " Large Community: %s\n",
10240 attr
->lcommunity
->str
);
10244 /* Line 7 display Originator, Cluster-id */
10245 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10246 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10247 char buf
[BUFSIZ
] = {0};
10249 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10251 json_object_string_add(
10252 json_path
, "originatorId",
10253 inet_ntop(AF_INET
, &attr
->originator_id
,
10254 buf
, sizeof(buf
)));
10256 vty_out(vty
, " Originator: %pI4",
10257 &attr
->originator_id
);
10260 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10261 struct cluster_list
*cluster
=
10262 bgp_attr_get_cluster(attr
);
10266 json_cluster_list
= json_object_new_object();
10267 json_cluster_list_list
=
10268 json_object_new_array();
10270 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10271 json_string
= json_object_new_string(
10274 buf
, sizeof(buf
)));
10275 json_object_array_add(
10276 json_cluster_list_list
,
10281 * struct cluster_list does not have
10282 * "str" variable like aspath and community
10283 * do. Add this someday if someone asks
10285 * json_object_string_add(json_cluster_list,
10286 * "string", cluster->str);
10288 json_object_object_add(json_cluster_list
,
10290 json_cluster_list_list
);
10291 json_object_object_add(json_path
, "clusterList",
10292 json_cluster_list
);
10294 vty_out(vty
, ", Cluster list: ");
10296 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10297 vty_out(vty
, "%pI4 ",
10298 &cluster
->list
[i
]);
10304 vty_out(vty
, "\n");
10307 if (path
->extra
&& path
->extra
->damp_info
)
10308 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10311 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10312 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10313 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10316 json_object_int_add(json_path
, "remoteLabel", label
);
10318 vty_out(vty
, " Remote label: %d\n", label
);
10322 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10323 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10325 json_object_string_add(json_path
, "remoteSid", buf
);
10327 vty_out(vty
, " Remote SID: %s\n", buf
);
10331 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10333 json_object_int_add(json_path
, "labelIndex",
10334 attr
->label_index
);
10336 vty_out(vty
, " Label Index: %d\n",
10337 attr
->label_index
);
10340 /* Line 8 display Addpath IDs */
10341 if (path
->addpath_rx_id
10342 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10344 json_object_int_add(json_path
, "addpathRxId",
10345 path
->addpath_rx_id
);
10347 /* Keep backwards compatibility with the old API
10348 * by putting TX All's ID in the old field
10350 json_object_int_add(
10351 json_path
, "addpathTxId",
10353 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10355 /* ... but create a specific field for each
10358 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10359 json_object_int_add(
10361 bgp_addpath_names(i
)->id_json_name
,
10362 path
->tx_addpath
.addpath_tx_id
[i
]);
10365 vty_out(vty
, " AddPath ID: RX %u, ",
10366 path
->addpath_rx_id
);
10368 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10372 /* If we used addpath to TX a non-bestpath we need to display
10373 * "Advertised to" on a path-by-path basis
10375 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10378 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10380 bgp_addpath_encode_tx(peer
, afi
, safi
);
10381 has_adj
= bgp_adj_out_lookup(
10383 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10384 &path
->tx_addpath
));
10386 if ((addpath_capable
&& has_adj
)
10387 || (!addpath_capable
&& has_adj
10388 && CHECK_FLAG(path
->flags
,
10389 BGP_PATH_SELECTED
))) {
10390 if (json_path
&& !json_adv_to
)
10391 json_adv_to
= json_object_new_object();
10393 route_vty_out_advertised_to(
10395 " Advertised to:", json_adv_to
);
10401 json_object_object_add(
10402 json_path
, "advertisedTo", json_adv_to
);
10406 vty_out(vty
, "\n");
10411 /* Line 9 display Uptime */
10412 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10414 json_last_update
= json_object_new_object();
10415 json_object_int_add(json_last_update
, "epoch", tbuf
);
10416 json_object_string_add(json_last_update
, "string",
10418 json_object_object_add(json_path
, "lastUpdate",
10421 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10423 /* Line 10 display PMSI tunnel attribute, if present */
10424 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10425 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10426 bgp_attr_get_pmsi_tnl_type(attr
),
10427 PMSI_TNLTYPE_STR_DEFAULT
);
10430 json_pmsi
= json_object_new_object();
10431 json_object_string_add(json_pmsi
, "tunnelType", str
);
10432 json_object_int_add(json_pmsi
, "label",
10433 label2vni(&attr
->label
));
10434 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10436 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10437 str
, label2vni(&attr
->label
));
10440 /* Output some debug about internal state of the dest flags */
10442 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10443 json_object_boolean_true_add(json_path
, "processScheduled");
10444 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10445 json_object_boolean_true_add(json_path
, "userCleared");
10446 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10447 json_object_boolean_true_add(json_path
, "labelChanged");
10448 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10449 json_object_boolean_true_add(json_path
, "registeredForLabel");
10450 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10451 json_object_boolean_true_add(json_path
, "selectDefered");
10452 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10453 json_object_boolean_true_add(json_path
, "fibInstalled");
10454 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10455 json_object_boolean_true_add(json_path
, "fibPending");
10458 /* We've constructed the json object for this path, add it to the json
10462 if (json_nexthop_global
|| json_nexthop_ll
) {
10463 json_nexthops
= json_object_new_array();
10465 if (json_nexthop_global
)
10466 json_object_array_add(json_nexthops
,
10467 json_nexthop_global
);
10469 if (json_nexthop_ll
)
10470 json_object_array_add(json_nexthops
,
10473 json_object_object_add(json_path
, "nexthops",
10477 json_object_object_add(json_path
, "peer", json_peer
);
10478 json_object_array_add(json_paths
, json_path
);
10482 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10483 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10484 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10486 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10487 const char *prefix_list_str
, afi_t afi
,
10488 safi_t safi
, enum bgp_show_type type
);
10489 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10490 const char *filter
, afi_t afi
, safi_t safi
,
10491 enum bgp_show_type type
);
10492 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10493 const char *rmap_str
, afi_t afi
, safi_t safi
,
10494 enum bgp_show_type type
);
10495 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10496 const char *com
, int exact
, afi_t afi
,
10498 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10499 const char *prefix
, afi_t afi
, safi_t safi
,
10500 enum bgp_show_type type
);
10501 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10502 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10504 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10505 const char *comstr
, int exact
, afi_t afi
,
10506 safi_t safi
, uint8_t show_flags
);
10509 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10510 struct bgp_table
*table
, enum bgp_show_type type
,
10511 void *output_arg
, char *rd
, int is_last
,
10512 unsigned long *output_cum
, unsigned long *total_cum
,
10513 unsigned long *json_header_depth
, uint8_t show_flags
)
10515 struct bgp_path_info
*pi
;
10516 struct bgp_dest
*dest
;
10519 unsigned long output_count
= 0;
10520 unsigned long total_count
= 0;
10522 json_object
*json_paths
= NULL
;
10524 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10525 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10526 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10528 if (output_cum
&& *output_cum
!= 0)
10531 if (use_json
&& !*json_header_depth
) {
10533 *json_header_depth
= 1;
10535 vty_out(vty
, "{\n");
10536 *json_header_depth
= 2;
10540 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10541 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10542 " \"localAS\": %u,\n \"routes\": { ",
10543 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10544 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10547 table
->version
, &bgp
->router_id
,
10548 bgp
->default_local_pref
, bgp
->as
);
10550 vty_out(vty
, " \"routeDistinguishers\" : {");
10551 ++*json_header_depth
;
10555 if (use_json
&& rd
) {
10556 vty_out(vty
, " \"%s\" : { ", rd
);
10559 /* Start processing of routes. */
10560 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10561 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10563 pi
= bgp_dest_get_bgp_path_info(dest
);
10569 json_paths
= json_object_new_array();
10573 for (; pi
; pi
= pi
->next
) {
10575 if (type
== bgp_show_type_flap_statistics
10576 || type
== bgp_show_type_flap_neighbor
10577 || type
== bgp_show_type_dampend_paths
10578 || type
== bgp_show_type_damp_neighbor
) {
10579 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10582 if (type
== bgp_show_type_regexp
) {
10583 regex_t
*regex
= output_arg
;
10585 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10589 if (type
== bgp_show_type_prefix_list
) {
10590 struct prefix_list
*plist
= output_arg
;
10592 if (prefix_list_apply(plist
, dest_p
)
10596 if (type
== bgp_show_type_filter_list
) {
10597 struct as_list
*as_list
= output_arg
;
10599 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10600 != AS_FILTER_PERMIT
)
10603 if (type
== bgp_show_type_route_map
) {
10604 struct route_map
*rmap
= output_arg
;
10605 struct bgp_path_info path
;
10606 struct attr dummy_attr
;
10607 route_map_result_t ret
;
10609 dummy_attr
= *pi
->attr
;
10611 path
.peer
= pi
->peer
;
10612 path
.attr
= &dummy_attr
;
10614 ret
= route_map_apply(rmap
, dest_p
, &path
);
10615 if (ret
== RMAP_DENYMATCH
)
10618 if (type
== bgp_show_type_neighbor
10619 || type
== bgp_show_type_flap_neighbor
10620 || type
== bgp_show_type_damp_neighbor
) {
10621 union sockunion
*su
= output_arg
;
10623 if (pi
->peer
== NULL
10624 || pi
->peer
->su_remote
== NULL
10625 || !sockunion_same(pi
->peer
->su_remote
, su
))
10628 if (type
== bgp_show_type_cidr_only
) {
10629 uint32_t destination
;
10631 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10632 if (IN_CLASSC(destination
)
10633 && dest_p
->prefixlen
== 24)
10635 if (IN_CLASSB(destination
)
10636 && dest_p
->prefixlen
== 16)
10638 if (IN_CLASSA(destination
)
10639 && dest_p
->prefixlen
== 8)
10642 if (type
== bgp_show_type_prefix_longer
) {
10644 if (!prefix_match(p
, dest_p
))
10647 if (type
== bgp_show_type_community_all
) {
10648 if (!pi
->attr
->community
)
10651 if (type
== bgp_show_type_community
) {
10652 struct community
*com
= output_arg
;
10654 if (!pi
->attr
->community
10655 || !community_match(pi
->attr
->community
,
10659 if (type
== bgp_show_type_community_exact
) {
10660 struct community
*com
= output_arg
;
10662 if (!pi
->attr
->community
10663 || !community_cmp(pi
->attr
->community
, com
))
10666 if (type
== bgp_show_type_community_list
) {
10667 struct community_list
*list
= output_arg
;
10669 if (!community_list_match(pi
->attr
->community
,
10673 if (type
== bgp_show_type_community_list_exact
) {
10674 struct community_list
*list
= output_arg
;
10676 if (!community_list_exact_match(
10677 pi
->attr
->community
, list
))
10680 if (type
== bgp_show_type_lcommunity
) {
10681 struct lcommunity
*lcom
= output_arg
;
10683 if (!pi
->attr
->lcommunity
10684 || !lcommunity_match(pi
->attr
->lcommunity
,
10689 if (type
== bgp_show_type_lcommunity_exact
) {
10690 struct lcommunity
*lcom
= output_arg
;
10692 if (!pi
->attr
->lcommunity
10693 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10697 if (type
== bgp_show_type_lcommunity_list
) {
10698 struct community_list
*list
= output_arg
;
10700 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10705 == bgp_show_type_lcommunity_list_exact
) {
10706 struct community_list
*list
= output_arg
;
10708 if (!lcommunity_list_exact_match(
10709 pi
->attr
->lcommunity
, list
))
10712 if (type
== bgp_show_type_lcommunity_all
) {
10713 if (!pi
->attr
->lcommunity
)
10716 if (type
== bgp_show_type_dampend_paths
10717 || type
== bgp_show_type_damp_neighbor
) {
10718 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10719 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10723 if (!use_json
&& header
) {
10725 "BGP table version is %" PRIu64
10726 ", local router ID is %pI4, vrf id ",
10727 table
->version
, &bgp
->router_id
);
10728 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10729 vty_out(vty
, "%s", VRFID_NONE_STR
);
10731 vty_out(vty
, "%u", bgp
->vrf_id
);
10732 vty_out(vty
, "\n");
10733 vty_out(vty
, "Default local pref %u, ",
10734 bgp
->default_local_pref
);
10735 vty_out(vty
, "local AS %u\n", bgp
->as
);
10736 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10737 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10738 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10739 if (type
== bgp_show_type_dampend_paths
10740 || type
== bgp_show_type_damp_neighbor
)
10741 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10742 else if (type
== bgp_show_type_flap_statistics
10743 || type
== bgp_show_type_flap_neighbor
)
10744 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10746 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10747 : BGP_SHOW_HEADER
));
10750 if (rd
!= NULL
&& !display
&& !output_count
) {
10753 "Route Distinguisher: %s\n",
10756 if (type
== bgp_show_type_dampend_paths
10757 || type
== bgp_show_type_damp_neighbor
)
10758 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10759 AFI_IP
, safi
, use_json
,
10761 else if (type
== bgp_show_type_flap_statistics
10762 || type
== bgp_show_type_flap_neighbor
)
10763 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10764 AFI_IP
, safi
, use_json
,
10767 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10777 /* encode prefix */
10778 if (dest_p
->family
== AF_FLOWSPEC
) {
10779 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10782 bgp_fs_nlri_get_string(
10784 dest_p
->u
.prefix_flowspec
.ptr
,
10785 dest_p
->u
.prefix_flowspec
.prefixlen
,
10786 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10787 family2afi(dest_p
->u
10788 .prefix_flowspec
.family
));
10790 vty_out(vty
, "\"%s/%d\": ", retstr
,
10791 dest_p
->u
.prefix_flowspec
10794 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10795 dest_p
->u
.prefix_flowspec
10799 vty_out(vty
, "\"%pFX\": ", dest_p
);
10801 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10804 json_object_to_json_string_ext(
10805 json_paths
, JSON_C_TO_STRING_PRETTY
));
10806 json_object_free(json_paths
);
10810 json_object_free(json_paths
);
10814 output_count
+= *output_cum
;
10815 *output_cum
= output_count
;
10818 total_count
+= *total_cum
;
10819 *total_cum
= total_count
;
10823 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10827 for (i
= 0; i
< *json_header_depth
; ++i
)
10828 vty_out(vty
, " } ");
10830 vty_out(vty
, "\n");
10834 /* No route is displayed */
10835 if (output_count
== 0) {
10836 if (type
== bgp_show_type_normal
)
10838 "No BGP prefixes displayed, %ld exist\n",
10842 "\nDisplayed %ld routes and %ld total paths\n",
10843 output_count
, total_count
);
10847 return CMD_SUCCESS
;
10850 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10851 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10852 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10854 struct bgp_dest
*dest
, *next
;
10855 unsigned long output_cum
= 0;
10856 unsigned long total_cum
= 0;
10857 unsigned long json_header_depth
= 0;
10858 struct bgp_table
*itable
;
10860 uint8_t show_flags
= 0;
10862 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10865 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10867 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10868 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10870 next
= bgp_route_next(dest
);
10871 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10874 itable
= bgp_dest_get_bgp_table_info(dest
);
10875 if (itable
!= NULL
) {
10876 struct prefix_rd prd
;
10877 char rd
[RD_ADDRSTRLEN
];
10879 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10880 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10881 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10882 rd
, next
== NULL
, &output_cum
,
10883 &total_cum
, &json_header_depth
,
10890 if (output_cum
== 0)
10891 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10895 "\nDisplayed %ld routes and %ld total paths\n",
10896 output_cum
, total_cum
);
10898 return CMD_SUCCESS
;
10900 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10901 enum bgp_show_type type
, void *output_arg
,
10902 uint8_t show_flags
)
10904 struct bgp_table
*table
;
10905 unsigned long json_header_depth
= 0;
10906 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10909 bgp
= bgp_get_default();
10914 vty_out(vty
, "No BGP process is configured\n");
10916 vty_out(vty
, "{}\n");
10917 return CMD_WARNING
;
10920 table
= bgp
->rib
[afi
][safi
];
10921 /* use MPLS and ENCAP specific shows until they are merged */
10922 if (safi
== SAFI_MPLS_VPN
) {
10923 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10924 output_arg
, use_json
);
10927 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10928 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10929 output_arg
, use_json
,
10932 /* labeled-unicast routes live in the unicast table */
10933 else if (safi
== SAFI_LABELED_UNICAST
)
10934 safi
= SAFI_UNICAST
;
10936 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10937 NULL
, NULL
, &json_header_depth
, show_flags
);
10940 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10941 safi_t safi
, uint8_t show_flags
)
10943 struct listnode
*node
, *nnode
;
10946 bool route_output
= false;
10947 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10950 vty_out(vty
, "{\n");
10952 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10953 route_output
= true;
10956 vty_out(vty
, ",\n");
10960 vty_out(vty
, "\"%s\":",
10961 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10965 vty_out(vty
, "\nInstance %s:\n",
10966 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10970 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10975 vty_out(vty
, "}\n");
10976 else if (!route_output
)
10977 vty_out(vty
, "%% BGP instance not found\n");
10980 /* Header of detailed BGP route information */
10981 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10982 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10983 afi_t afi
, safi_t safi
, json_object
*json
)
10985 struct bgp_path_info
*pi
;
10986 const struct prefix
*p
;
10988 struct listnode
*node
, *nnode
;
10989 char buf1
[RD_ADDRSTRLEN
];
10990 char prefix_str
[BUFSIZ
];
10994 int accept_own
= 0;
10995 int route_filter_translated_v4
= 0;
10996 int route_filter_v4
= 0;
10997 int route_filter_translated_v6
= 0;
10998 int route_filter_v6
= 0;
10999 int llgr_stale
= 0;
11001 int accept_own_nexthop
= 0;
11004 int no_advertise
= 0;
11008 int has_valid_label
= 0;
11009 mpls_label_t label
= 0;
11010 json_object
*json_adv_to
= NULL
;
11012 p
= bgp_dest_get_prefix(dest
);
11013 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11015 if (has_valid_label
)
11016 label
= label_pton(&dest
->local_label
);
11018 if (safi
== SAFI_EVPN
) {
11021 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11022 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11024 prd
? ":" : "", (struct prefix_evpn
*)p
);
11026 json_object_string_add(json
, "rd",
11027 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11029 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11033 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11034 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11035 ? prefix_rd2str(prd
, buf1
,
11038 safi
== SAFI_MPLS_VPN
? ":" : "", p
);
11041 json_object_string_add(json
, "prefix",
11042 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11045 if (has_valid_label
) {
11047 json_object_int_add(json
, "localLabel", label
);
11049 vty_out(vty
, "Local label: %d\n", label
);
11053 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11054 vty_out(vty
, "not allocated\n");
11056 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11058 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11060 if (bgp_path_suppressed(pi
))
11063 if (pi
->attr
->community
== NULL
)
11066 no_advertise
+= community_include(
11067 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11068 no_export
+= community_include(pi
->attr
->community
,
11069 COMMUNITY_NO_EXPORT
);
11070 local_as
+= community_include(pi
->attr
->community
,
11071 COMMUNITY_LOCAL_AS
);
11072 accept_own
+= community_include(pi
->attr
->community
,
11073 COMMUNITY_ACCEPT_OWN
);
11074 route_filter_translated_v4
+= community_include(
11075 pi
->attr
->community
,
11076 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11077 route_filter_translated_v6
+= community_include(
11078 pi
->attr
->community
,
11079 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11080 route_filter_v4
+= community_include(
11081 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11082 route_filter_v6
+= community_include(
11083 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11084 llgr_stale
+= community_include(pi
->attr
->community
,
11085 COMMUNITY_LLGR_STALE
);
11086 no_llgr
+= community_include(pi
->attr
->community
,
11087 COMMUNITY_NO_LLGR
);
11088 accept_own_nexthop
+=
11089 community_include(pi
->attr
->community
,
11090 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11091 blackhole
+= community_include(pi
->attr
->community
,
11092 COMMUNITY_BLACKHOLE
);
11093 no_peer
+= community_include(pi
->attr
->community
,
11094 COMMUNITY_NO_PEER
);
11099 vty_out(vty
, "Paths: (%d available", count
);
11101 vty_out(vty
, ", best #%d", best
);
11102 if (safi
== SAFI_UNICAST
) {
11103 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11104 vty_out(vty
, ", table %s",
11107 vty_out(vty
, ", vrf %s",
11111 vty_out(vty
, ", no best path");
11115 ", accept own local route exported and imported in different VRF");
11116 else if (route_filter_translated_v4
)
11118 ", mark translated RTs for VPNv4 route filtering");
11119 else if (route_filter_v4
)
11121 ", attach RT as-is for VPNv4 route filtering");
11122 else if (route_filter_translated_v6
)
11124 ", mark translated RTs for VPNv6 route filtering");
11125 else if (route_filter_v6
)
11127 ", attach RT as-is for VPNv6 route filtering");
11128 else if (llgr_stale
)
11130 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11133 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11134 else if (accept_own_nexthop
)
11136 ", accept local nexthop");
11137 else if (blackhole
)
11138 vty_out(vty
, ", inform peer to blackhole prefix");
11139 else if (no_export
)
11140 vty_out(vty
, ", not advertised to EBGP peer");
11141 else if (no_advertise
)
11142 vty_out(vty
, ", not advertised to any peer");
11144 vty_out(vty
, ", not advertised outside local AS");
11147 ", inform EBGP peer not to advertise to their EBGP peers");
11151 ", Advertisements suppressed by an aggregate.");
11152 vty_out(vty
, ")\n");
11155 /* If we are not using addpath then we can display Advertised to and
11157 * show what peers we advertised the bestpath to. If we are using
11159 * though then we must display Advertised to on a path-by-path basis. */
11160 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11161 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11162 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11163 if (json
&& !json_adv_to
)
11164 json_adv_to
= json_object_new_object();
11166 route_vty_out_advertised_to(
11168 " Advertised to non peer-group peers:\n ",
11175 json_object_object_add(json
, "advertisedTo",
11180 vty_out(vty
, " Not advertised to any peer");
11181 vty_out(vty
, "\n");
11186 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11187 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11188 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11189 json_object
*json
, enum bgp_path_type pathtype
,
11192 struct bgp_path_info
*pi
;
11194 char rdbuf
[RD_ADDRSTRLEN
];
11195 json_object
*json_header
= NULL
;
11196 json_object
*json_paths
= NULL
;
11198 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11200 if (json
&& !json_paths
) {
11201 /* Instantiate json_paths only if path is valid */
11202 json_paths
= json_object_new_array();
11204 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11205 json_header
= json_object_new_object();
11207 json_header
= json
;
11211 route_vty_out_detail_header(
11212 vty
, bgp
, bgp_node
, pfx_rd
,
11213 AFI_IP
, safi
, json_header
);
11218 if (pathtype
== BGP_PATH_SHOW_ALL
11219 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11220 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11221 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11222 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11223 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11224 route_vty_out_detail(vty
, bgp
, bgp_node
,
11229 if (json
&& json_paths
) {
11230 json_object_object_add(json_header
, "paths", json_paths
);
11233 json_object_object_add(json
, rdbuf
, json_header
);
11237 /* Display specified route of BGP table. */
11238 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11239 struct bgp_table
*rib
, const char *ip_str
,
11240 afi_t afi
, safi_t safi
,
11241 struct prefix_rd
*prd
, int prefix_check
,
11242 enum bgp_path_type pathtype
, bool use_json
)
11246 struct prefix match
;
11247 struct bgp_dest
*dest
;
11248 struct bgp_dest
*rm
;
11249 struct bgp_table
*table
;
11250 json_object
*json
= NULL
;
11251 json_object
*json_paths
= NULL
;
11253 /* Check IP address argument. */
11254 ret
= str2prefix(ip_str
, &match
);
11256 vty_out(vty
, "address is malformed\n");
11257 return CMD_WARNING
;
11260 match
.family
= afi2family(afi
);
11263 json
= json_object_new_object();
11265 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11266 for (dest
= bgp_table_top(rib
); dest
;
11267 dest
= bgp_route_next(dest
)) {
11268 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11270 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11272 table
= bgp_dest_get_bgp_table_info(dest
);
11276 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11279 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11281 && rm_p
->prefixlen
!= match
.prefixlen
) {
11282 bgp_dest_unlock_node(rm
);
11286 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11287 bgp
, afi
, safi
, json
, pathtype
,
11290 bgp_dest_unlock_node(rm
);
11292 } else if (safi
== SAFI_EVPN
) {
11293 struct bgp_dest
*longest_pfx
;
11294 bool is_exact_pfxlen_match
= false;
11296 for (dest
= bgp_table_top(rib
); dest
;
11297 dest
= bgp_route_next(dest
)) {
11298 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11300 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11302 table
= bgp_dest_get_bgp_table_info(dest
);
11306 longest_pfx
= NULL
;
11307 is_exact_pfxlen_match
= false;
11309 * Search through all the prefixes for a match. The
11310 * pfx's are enumerated in ascending order of pfxlens.
11311 * So, the last pfx match is the longest match. Set
11312 * is_exact_pfxlen_match when we get exact pfxlen match
11314 for (rm
= bgp_table_top(table
); rm
;
11315 rm
= bgp_route_next(rm
)) {
11316 const struct prefix
*rm_p
=
11317 bgp_dest_get_prefix(rm
);
11319 * Get prefixlen of the ip-prefix within type5
11322 if (evpn_type5_prefix_match(rm_p
, &match
)
11326 bgp_evpn_get_type5_prefixlen(
11328 if (type5_pfxlen
== match
.prefixlen
) {
11329 is_exact_pfxlen_match
= true;
11330 bgp_dest_unlock_node(rm
);
11339 if (prefix_check
&& !is_exact_pfxlen_match
)
11343 bgp_dest_lock_node(rm
);
11345 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11346 bgp
, afi
, safi
, json
, pathtype
,
11349 bgp_dest_unlock_node(rm
);
11351 } else if (safi
== SAFI_FLOWSPEC
) {
11353 json_paths
= json_object_new_array();
11355 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11356 &match
, prefix_check
,
11362 json_object_object_add(json
, "paths",
11365 json_object_free(json_paths
);
11368 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
11369 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11371 || dest_p
->prefixlen
== match
.prefixlen
) {
11372 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11373 safi
, json
, pathtype
,
11377 bgp_dest_unlock_node(dest
);
11382 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11383 json
, JSON_C_TO_STRING_PRETTY
|
11384 JSON_C_TO_STRING_NOSLASHESCAPE
));
11385 json_object_free(json
);
11388 vty_out(vty
, "%% Network not in table\n");
11389 return CMD_WARNING
;
11393 return CMD_SUCCESS
;
11396 /* Display specified route of Main RIB */
11397 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11398 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11399 int prefix_check
, enum bgp_path_type pathtype
,
11403 bgp
= bgp_get_default();
11406 vty_out(vty
, "No BGP process is configured\n");
11408 vty_out(vty
, "{}\n");
11409 return CMD_WARNING
;
11413 /* labeled-unicast routes live in the unicast table */
11414 if (safi
== SAFI_LABELED_UNICAST
)
11415 safi
= SAFI_UNICAST
;
11417 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11418 afi
, safi
, prd
, prefix_check
, pathtype
,
11422 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11423 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11424 safi_t safi
, bool uj
)
11426 struct lcommunity
*lcom
;
11431 uint8_t show_flags
= 0;
11435 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11437 b
= buffer_new(1024);
11438 for (i
= 0; i
< argc
; i
++) {
11440 buffer_putc(b
, ' ');
11442 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11444 buffer_putstr(b
, argv
[i
]->arg
);
11448 buffer_putc(b
, '\0');
11450 str
= buffer_getstr(b
);
11453 lcom
= lcommunity_str2com(str
);
11454 XFREE(MTYPE_TMP
, str
);
11456 vty_out(vty
, "%% Large-community malformed\n");
11457 return CMD_WARNING
;
11460 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11461 (exact
? bgp_show_type_lcommunity_exact
11462 : bgp_show_type_lcommunity
),
11465 lcommunity_free(&lcom
);
11469 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11470 const char *lcom
, bool exact
, afi_t afi
,
11471 safi_t safi
, bool uj
)
11473 struct community_list
*list
;
11474 uint8_t show_flags
= 0;
11477 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11480 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11481 LARGE_COMMUNITY_LIST_MASTER
);
11482 if (list
== NULL
) {
11483 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11485 return CMD_WARNING
;
11488 return bgp_show(vty
, bgp
, afi
, safi
,
11489 (exact
? bgp_show_type_lcommunity_list_exact
11490 : bgp_show_type_lcommunity_list
),
11494 DEFUN (show_ip_bgp_large_community_list
,
11495 show_ip_bgp_large_community_list_cmd
,
11496 "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]",
11500 BGP_INSTANCE_HELP_STR
11502 BGP_SAFI_WITH_LABEL_HELP_STR
11503 "Display routes matching the large-community-list\n"
11504 "large-community-list number\n"
11505 "large-community-list name\n"
11506 "Exact match of the large-communities\n"
11509 afi_t afi
= AFI_IP6
;
11510 safi_t safi
= SAFI_UNICAST
;
11512 bool exact_match
= 0;
11513 struct bgp
*bgp
= NULL
;
11514 bool uj
= use_json(argc
, argv
);
11519 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11522 return CMD_WARNING
;
11524 argv_find(argv
, argc
, "large-community-list", &idx
);
11526 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11528 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11531 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11532 exact_match
, afi
, safi
, uj
);
11534 DEFUN (show_ip_bgp_large_community
,
11535 show_ip_bgp_large_community_cmd
,
11536 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11540 BGP_INSTANCE_HELP_STR
11542 BGP_SAFI_WITH_LABEL_HELP_STR
11543 "Display routes matching the large-communities\n"
11544 "List of large-community numbers\n"
11545 "Exact match of the large-communities\n"
11548 afi_t afi
= AFI_IP6
;
11549 safi_t safi
= SAFI_UNICAST
;
11551 bool exact_match
= 0;
11552 struct bgp
*bgp
= NULL
;
11553 bool uj
= use_json(argc
, argv
);
11554 uint8_t show_flags
= 0;
11558 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11561 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11564 return CMD_WARNING
;
11566 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11567 if (argv_find(argv
, argc
, "exact-match", &idx
))
11569 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11570 exact_match
, afi
, safi
, uj
);
11572 return bgp_show(vty
, bgp
, afi
, safi
,
11573 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
11576 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11577 safi_t safi
, struct json_object
*json_array
);
11578 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11579 safi_t safi
, struct json_object
*json
);
11582 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11583 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11584 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11585 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11587 bool uj
= use_json(argc
, argv
);
11588 struct bgp
*bgp
= NULL
;
11589 safi_t safi
= SAFI_UNICAST
;
11590 afi_t afi
= AFI_IP6
;
11592 struct json_object
*json_all
= NULL
;
11593 struct json_object
*json_afi_safi
= NULL
;
11595 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11598 return CMD_WARNING
;
11601 json_all
= json_object_new_object();
11603 FOREACH_AFI_SAFI (afi
, safi
) {
11605 * So limit output to those afi/safi pairs that
11606 * actually have something interesting in them
11608 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11613 json_afi_safi
= json_object_new_array();
11614 json_object_object_add(
11616 get_afi_safi_str(afi
, safi
, true),
11619 json_afi_safi
= NULL
;
11622 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11627 json_object_to_json_string_ext(
11628 json_all
, JSON_C_TO_STRING_PRETTY
));
11629 json_object_free(json_all
);
11632 return CMD_SUCCESS
;
11635 /* BGP route print out function without JSON */
11636 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11637 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11638 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11642 BGP_INSTANCE_HELP_STR
11645 "BGP RIB advertisement statistics\n"
11648 afi_t afi
= AFI_IP6
;
11649 safi_t safi
= SAFI_UNICAST
;
11650 struct bgp
*bgp
= NULL
;
11652 bool uj
= use_json(argc
, argv
);
11653 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11655 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11658 return CMD_WARNING
;
11661 json_afi_safi
= json_object_new_array();
11663 json_afi_safi
= NULL
;
11665 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11668 json
= json_object_new_object();
11669 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11671 vty_out(vty
, "%s", json_object_to_json_string_ext(
11672 json
, JSON_C_TO_STRING_PRETTY
));
11673 json_object_free(json
);
11678 /* BGP route print out function without JSON */
11679 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11680 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11681 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11683 statistics [json]",
11684 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11685 BGP_SAFI_WITH_LABEL_HELP_STR
11686 "BGP RIB advertisement statistics\n" JSON_STR
)
11688 afi_t afi
= AFI_IP6
;
11689 safi_t safi
= SAFI_UNICAST
;
11690 struct bgp
*bgp
= NULL
;
11692 bool uj
= use_json(argc
, argv
);
11693 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11695 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11698 return CMD_WARNING
;
11701 json_afi_safi
= json_object_new_array();
11703 json_afi_safi
= NULL
;
11705 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11708 json
= json_object_new_object();
11709 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11712 json_object_to_json_string_ext(
11713 json
, JSON_C_TO_STRING_PRETTY
));
11714 json_object_free(json
);
11719 /* BGP route print out function without JSON */
11720 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11721 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11722 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11724 <[all$all] dampening <parameters>\
11728 |community-list <(1-500)|WORD> [exact-match]\
11729 |A.B.C.D/M longer-prefixes\
11730 |X:X::X:X/M longer-prefixes\
11732 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11733 BGP_SAFI_WITH_LABEL_HELP_STR
11734 "Display the entries for all address families\n"
11735 "Display detailed information about dampening\n"
11736 "Display detail of configured dampening parameters\n"
11737 "Display routes matching the route-map\n"
11738 "A route-map to match on\n"
11739 "Display routes conforming to the prefix-list\n"
11740 "Prefix-list name\n"
11741 "Display routes conforming to the filter-list\n"
11742 "Regular expression access list name\n"
11743 "Display routes matching the community-list\n"
11744 "community-list number\n"
11745 "community-list name\n"
11746 "Exact match of the communities\n"
11748 "Display route and more specific routes\n"
11750 "Display route and more specific routes\n")
11752 afi_t afi
= AFI_IP6
;
11753 safi_t safi
= SAFI_UNICAST
;
11754 int exact_match
= 0;
11755 struct bgp
*bgp
= NULL
;
11757 uint8_t show_flags
= 0;
11759 /* [<ipv4|ipv6> [all]] */
11761 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11762 if (argv_find(argv
, argc
, "ipv4", &idx
))
11763 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11765 if (argv_find(argv
, argc
, "ipv6", &idx
))
11766 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11769 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11772 return CMD_WARNING
;
11774 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11775 if (argv_find(argv
, argc
, "parameters", &idx
))
11776 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11780 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11781 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11782 safi
, bgp_show_type_prefix_list
);
11784 if (argv_find(argv
, argc
, "filter-list", &idx
))
11785 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11786 safi
, bgp_show_type_filter_list
);
11788 if (argv_find(argv
, argc
, "route-map", &idx
))
11789 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11790 safi
, bgp_show_type_route_map
);
11792 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11793 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11794 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11796 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11797 exact_match
, afi
, safi
);
11799 /* prefix-longer */
11800 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11801 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11802 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11804 bgp_show_type_prefix_longer
);
11806 return CMD_WARNING
;
11809 /* BGP route print out function with JSON */
11810 DEFPY (show_ip_bgp_json
,
11811 show_ip_bgp_json_cmd
,
11812 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11815 |dampening <flap-statistics|dampened-paths>\
11816 |community [AA:NN|local-AS|no-advertise|no-export\
11817 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11818 |accept-own|accept-own-nexthop|route-filter-v6\
11819 |route-filter-v4|route-filter-translated-v6\
11820 |route-filter-translated-v4] [exact-match]\
11821 ] [json$uj | wide$wide]",
11825 BGP_INSTANCE_HELP_STR
11827 BGP_SAFI_WITH_LABEL_HELP_STR
11828 "Display the entries for all address families\n"
11829 "Display only routes with non-natural netmasks\n"
11830 "Display detailed information about dampening\n"
11831 "Display flap statistics of routes\n"
11832 "Display paths suppressed due to dampening\n"
11833 "Display routes matching the communities\n"
11835 "Do not send outside local AS (well-known community)\n"
11836 "Do not advertise to any peer (well-known community)\n"
11837 "Do not export to next AS (well-known community)\n"
11838 "Graceful shutdown (well-known community)\n"
11839 "Do not export to any peer (well-known community)\n"
11840 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11841 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11842 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11843 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11844 "Should accept VPN route with local nexthop (well-known community)\n"
11845 "RT VPNv6 route filtering (well-known community)\n"
11846 "RT VPNv4 route filtering (well-known community)\n"
11847 "RT translated VPNv6 route filtering (well-known community)\n"
11848 "RT translated VPNv4 route filtering (well-known community)\n"
11849 "Exact match of the communities\n"
11851 "Increase table width for longer prefixes\n")
11853 afi_t afi
= AFI_IP6
;
11854 safi_t safi
= SAFI_UNICAST
;
11855 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11856 struct bgp
*bgp
= NULL
;
11858 int exact_match
= 0;
11859 char *community
= NULL
;
11861 uint8_t show_flags
= 0;
11866 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11869 /* [<ipv4|ipv6> [all]] */
11871 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11873 if (argv_find(argv
, argc
, "ipv4", &idx
))
11874 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11876 if (argv_find(argv
, argc
, "ipv6", &idx
))
11877 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11881 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11883 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11886 return CMD_WARNING
;
11888 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11889 sh_type
= bgp_show_type_cidr_only
;
11891 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11892 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11893 sh_type
= bgp_show_type_dampend_paths
;
11894 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11895 sh_type
= bgp_show_type_flap_statistics
;
11898 if (argv_find(argv
, argc
, "community", &idx
)) {
11899 char *maybecomm
= NULL
;
11901 if (idx
+ 1 < argc
) {
11902 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11903 maybecomm
= argv
[idx
+ 1]->arg
;
11905 maybecomm
= argv
[idx
+ 1]->text
;
11908 if (maybecomm
&& !strmatch(maybecomm
, "json")
11909 && !strmatch(maybecomm
, "exact-match"))
11910 community
= maybecomm
;
11912 if (argv_find(argv
, argc
, "exact-match", &idx
))
11916 sh_type
= bgp_show_type_community_all
;
11920 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11922 return bgp_show_community(vty
, bgp
, community
,
11923 exact_match
, afi
, safi
,
11926 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11929 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11933 vty_out(vty
, "{\n");
11935 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11936 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11937 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11940 FOREACH_SAFI (safi
) {
11941 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11948 vty_out(vty
, ",\n");
11949 vty_out(vty
, "\"%s\":{\n",
11950 get_afi_safi_str(afi
, safi
,
11954 "\nFor address family: %s\n",
11955 get_afi_safi_str(afi
, safi
,
11959 bgp_show_community(vty
, bgp
, community
,
11963 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11966 vty_out(vty
, "}\n");
11969 /* show <ip> bgp all: for each AFI and SAFI*/
11970 FOREACH_AFI_SAFI (afi
, safi
) {
11971 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11978 vty_out(vty
, ",\n");
11980 vty_out(vty
, "\"%s\":{\n",
11981 get_afi_safi_str(afi
, safi
,
11985 "\nFor address family: %s\n",
11986 get_afi_safi_str(afi
, safi
,
11990 bgp_show_community(vty
, bgp
, community
,
11994 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11997 vty_out(vty
, "}\n");
12001 vty_out(vty
, "}\n");
12003 return CMD_SUCCESS
;
12006 DEFUN (show_ip_bgp_route
,
12007 show_ip_bgp_route_cmd
,
12008 "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]",
12012 BGP_INSTANCE_HELP_STR
12014 BGP_SAFI_WITH_LABEL_HELP_STR
12015 "Network in the BGP routing table to display\n"
12017 "Network in the BGP routing table to display\n"
12019 "Display only the bestpath\n"
12020 "Display only multipaths\n"
12023 int prefix_check
= 0;
12025 afi_t afi
= AFI_IP6
;
12026 safi_t safi
= SAFI_UNICAST
;
12027 char *prefix
= NULL
;
12028 struct bgp
*bgp
= NULL
;
12029 enum bgp_path_type path_type
;
12030 bool uj
= use_json(argc
, argv
);
12034 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12037 return CMD_WARNING
;
12041 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12042 return CMD_WARNING
;
12045 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12046 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12047 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12049 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12050 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12053 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12054 && afi
!= AFI_IP6
) {
12056 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12057 return CMD_WARNING
;
12059 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12060 && afi
!= AFI_IP
) {
12062 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12063 return CMD_WARNING
;
12066 prefix
= argv
[idx
]->arg
;
12068 /* [<bestpath|multipath>] */
12069 if (argv_find(argv
, argc
, "bestpath", &idx
))
12070 path_type
= BGP_PATH_SHOW_BESTPATH
;
12071 else if (argv_find(argv
, argc
, "multipath", &idx
))
12072 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12074 path_type
= BGP_PATH_SHOW_ALL
;
12076 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12080 DEFUN (show_ip_bgp_regexp
,
12081 show_ip_bgp_regexp_cmd
,
12082 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12086 BGP_INSTANCE_HELP_STR
12088 BGP_SAFI_WITH_LABEL_HELP_STR
12089 "Display routes matching the AS path regular expression\n"
12090 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12093 afi_t afi
= AFI_IP6
;
12094 safi_t safi
= SAFI_UNICAST
;
12095 struct bgp
*bgp
= NULL
;
12096 bool uj
= use_json(argc
, argv
);
12097 char *regstr
= NULL
;
12100 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12103 return CMD_WARNING
;
12105 // get index of regex
12106 if (argv_find(argv
, argc
, "REGEX", &idx
))
12107 regstr
= argv
[idx
]->arg
;
12110 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12111 bgp_show_type_regexp
, uj
);
12114 DEFPY (show_ip_bgp_instance_all
,
12115 show_ip_bgp_instance_all_cmd
,
12116 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12120 BGP_INSTANCE_ALL_HELP_STR
12122 BGP_SAFI_WITH_LABEL_HELP_STR
12124 "Increase table width for longer prefixes\n")
12126 afi_t afi
= AFI_IP
;
12127 safi_t safi
= SAFI_UNICAST
;
12128 struct bgp
*bgp
= NULL
;
12130 uint8_t show_flags
= 0;
12134 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12138 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12140 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12143 return CMD_WARNING
;
12145 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12146 return CMD_SUCCESS
;
12149 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12150 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12155 uint8_t show_flags
= 0;
12158 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12160 if (!config_bgp_aspath_validate(regstr
)) {
12161 vty_out(vty
, "Invalid character in REGEX %s\n",
12163 return CMD_WARNING_CONFIG_FAILED
;
12166 regex
= bgp_regcomp(regstr
);
12168 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12169 return CMD_WARNING
;
12172 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
12173 bgp_regex_free(regex
);
12177 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12178 const char *prefix_list_str
, afi_t afi
,
12179 safi_t safi
, enum bgp_show_type type
)
12181 struct prefix_list
*plist
;
12182 uint8_t show_flags
= 0;
12184 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12185 if (plist
== NULL
) {
12186 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12188 return CMD_WARNING
;
12191 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
12194 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12195 const char *filter
, afi_t afi
, safi_t safi
,
12196 enum bgp_show_type type
)
12198 struct as_list
*as_list
;
12199 uint8_t show_flags
= 0;
12201 as_list
= as_list_lookup(filter
);
12202 if (as_list
== NULL
) {
12203 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12205 return CMD_WARNING
;
12208 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
12211 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12212 const char *rmap_str
, afi_t afi
, safi_t safi
,
12213 enum bgp_show_type type
)
12215 struct route_map
*rmap
;
12216 uint8_t show_flags
= 0;
12218 rmap
= route_map_lookup_by_name(rmap_str
);
12220 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12221 return CMD_WARNING
;
12224 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
12227 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12228 const char *comstr
, int exact
, afi_t afi
,
12229 safi_t safi
, uint8_t show_flags
)
12231 struct community
*com
;
12234 com
= community_str2com(comstr
);
12236 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12237 return CMD_WARNING
;
12240 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12241 (exact
? bgp_show_type_community_exact
12242 : bgp_show_type_community
),
12244 community_free(&com
);
12249 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12250 const char *com
, int exact
, afi_t afi
,
12253 struct community_list
*list
;
12254 uint8_t show_flags
= 0;
12256 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12257 if (list
== NULL
) {
12258 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12259 return CMD_WARNING
;
12262 return bgp_show(vty
, bgp
, afi
, safi
,
12263 (exact
? bgp_show_type_community_list_exact
12264 : bgp_show_type_community_list
),
12268 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12269 const char *prefix
, afi_t afi
, safi_t safi
,
12270 enum bgp_show_type type
)
12274 uint8_t show_flags
= 0;
12278 ret
= str2prefix(prefix
, p
);
12280 vty_out(vty
, "%% Malformed Prefix\n");
12281 return CMD_WARNING
;
12284 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
12290 BGP_STATS_MAXBITLEN
= 0,
12292 BGP_STATS_PREFIXES
,
12294 BGP_STATS_UNAGGREGATEABLE
,
12295 BGP_STATS_MAX_AGGREGATEABLE
,
12296 BGP_STATS_AGGREGATES
,
12298 BGP_STATS_ASPATH_COUNT
,
12299 BGP_STATS_ASPATH_MAXHOPS
,
12300 BGP_STATS_ASPATH_TOTHOPS
,
12301 BGP_STATS_ASPATH_MAXSIZE
,
12302 BGP_STATS_ASPATH_TOTSIZE
,
12303 BGP_STATS_ASN_HIGHEST
,
12307 #define TABLE_STATS_IDX_VTY 0
12308 #define TABLE_STATS_IDX_JSON 1
12310 static const char *table_stats_strs
[][2] = {
12311 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12312 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12313 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12314 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12315 "unaggregateablePrefixes"},
12316 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12317 "maximumAggregateablePrefixes"},
12318 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12319 "bgpAggregateAdvertisements"},
12320 [BGP_STATS_SPACE
] = {"Address space advertised",
12321 "addressSpaceAdvertised"},
12322 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12323 "advertisementsWithPaths"},
12324 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12326 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12328 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12329 "averageAsPathLengthHops"},
12330 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12331 "averageAsPathSizeBytes"},
12332 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12333 [BGP_STATS_MAX
] = {NULL
, NULL
}
12336 struct bgp_table_stats
{
12337 struct bgp_table
*table
;
12338 unsigned long long counts
[BGP_STATS_MAX
];
12339 double total_space
;
12342 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12343 struct bgp_table_stats
*ts
, unsigned int space
)
12345 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12346 struct bgp_path_info
*pi
;
12347 const struct prefix
*rn_p
;
12349 if (!bgp_dest_has_bgp_path_info_data(dest
))
12352 rn_p
= bgp_dest_get_prefix(dest
);
12353 ts
->counts
[BGP_STATS_PREFIXES
]++;
12354 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12356 /* check if the prefix is included by any other announcements */
12357 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12358 pdest
= bgp_dest_parent_nolock(pdest
);
12360 if (pdest
== NULL
|| pdest
== top
) {
12361 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12362 /* announced address space */
12364 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12365 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12366 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12369 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12370 ts
->counts
[BGP_STATS_RIB
]++;
12372 if (CHECK_FLAG(pi
->attr
->flag
,
12373 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12374 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12376 /* as-path stats */
12377 if (pi
->attr
->aspath
) {
12378 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12379 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12380 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12382 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12384 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12385 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12387 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12388 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12390 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12391 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12392 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12393 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12398 static int bgp_table_stats_walker(struct thread
*t
)
12400 struct bgp_dest
*dest
, *ndest
;
12401 struct bgp_dest
*top
;
12402 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12403 unsigned int space
= 0;
12405 if (!(top
= bgp_table_top(ts
->table
)))
12408 switch (ts
->table
->afi
) {
12410 space
= IPV4_MAX_BITLEN
;
12413 space
= IPV6_MAX_BITLEN
;
12416 space
= EVPN_ROUTE_PREFIXLEN
;
12422 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12424 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12425 if (ts
->table
->safi
== SAFI_MPLS_VPN
12426 || ts
->table
->safi
== SAFI_ENCAP
12427 || ts
->table
->safi
== SAFI_EVPN
) {
12428 struct bgp_table
*table
;
12430 table
= bgp_dest_get_bgp_table_info(dest
);
12434 top
= bgp_table_top(table
);
12435 for (ndest
= bgp_table_top(table
); ndest
;
12436 ndest
= bgp_route_next(ndest
))
12437 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12439 bgp_table_stats_rn(dest
, top
, ts
, space
);
12446 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12447 struct json_object
*json_array
)
12449 struct listnode
*node
, *nnode
;
12452 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12453 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12456 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12457 safi_t safi
, struct json_object
*json_array
)
12459 struct bgp_table_stats ts
;
12461 int ret
= CMD_SUCCESS
;
12463 struct json_object
*json
= NULL
;
12466 json
= json_object_new_object();
12468 if (!bgp
->rib
[afi
][safi
]) {
12469 char warning_msg
[50];
12471 snprintf(warning_msg
, sizeof(warning_msg
),
12472 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12476 vty_out(vty
, "%s\n", warning_msg
);
12478 json_object_string_add(json
, "warning", warning_msg
);
12481 goto end_table_stats
;
12485 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12486 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12488 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12490 /* labeled-unicast routes live in the unicast table */
12491 if (safi
== SAFI_LABELED_UNICAST
)
12492 safi
= SAFI_UNICAST
;
12494 memset(&ts
, 0, sizeof(ts
));
12495 ts
.table
= bgp
->rib
[afi
][safi
];
12496 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12498 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12499 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12500 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12504 case BGP_STATS_ASPATH_TOTHOPS
:
12505 case BGP_STATS_ASPATH_TOTSIZE
:
12508 temp_buf
, sizeof(temp_buf
), "%12.2f",
12510 ? (float)ts
.counts
[i
]
12512 [BGP_STATS_ASPATH_COUNT
]
12514 vty_out(vty
, "%-30s: %s",
12515 table_stats_strs
[i
]
12516 [TABLE_STATS_IDX_VTY
],
12519 json_object_double_add(
12521 table_stats_strs
[i
]
12522 [TABLE_STATS_IDX_JSON
],
12524 ? (double)ts
.counts
[i
]
12525 / (double)ts
.counts
12526 [BGP_STATS_ASPATH_COUNT
]
12530 case BGP_STATS_TOTPLEN
:
12533 temp_buf
, sizeof(temp_buf
), "%12.2f",
12535 ? (float)ts
.counts
[i
]
12537 [BGP_STATS_PREFIXES
]
12539 vty_out(vty
, "%-30s: %s",
12540 table_stats_strs
[i
]
12541 [TABLE_STATS_IDX_VTY
],
12544 json_object_double_add(
12546 table_stats_strs
[i
]
12547 [TABLE_STATS_IDX_JSON
],
12549 ? (double)ts
.counts
[i
]
12550 / (double)ts
.counts
12551 [BGP_STATS_PREFIXES
]
12555 case BGP_STATS_SPACE
:
12557 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12559 vty_out(vty
, "%-30s: %s\n",
12560 table_stats_strs
[i
]
12561 [TABLE_STATS_IDX_VTY
],
12564 json_object_double_add(
12566 table_stats_strs
[i
]
12567 [TABLE_STATS_IDX_JSON
],
12568 (double)ts
.total_space
);
12570 if (afi
== AFI_IP6
) {
12572 snprintf(temp_buf
, sizeof(temp_buf
),
12575 * pow(2.0, -128 + 32));
12576 vty_out(vty
, "%30s: %s\n",
12577 "/32 equivalent %s\n",
12580 json_object_double_add(
12581 json
, "/32equivalent",
12582 (double)(ts
.total_space
12587 snprintf(temp_buf
, sizeof(temp_buf
),
12590 * pow(2.0, -128 + 48));
12591 vty_out(vty
, "%30s: %s\n",
12592 "/48 equivalent %s\n",
12595 json_object_double_add(
12596 json
, "/48equivalent",
12597 (double)(ts
.total_space
12603 snprintf(temp_buf
, sizeof(temp_buf
),
12605 ts
.total_space
* 100.
12607 vty_out(vty
, "%30s: %s\n",
12608 "% announced ", temp_buf
);
12610 json_object_double_add(
12611 json
, "%announced",
12612 (double)(ts
.total_space
* 100.
12616 snprintf(temp_buf
, sizeof(temp_buf
),
12619 * pow(2.0, -32 + 8));
12620 vty_out(vty
, "%30s: %s\n",
12621 "/8 equivalent ", temp_buf
);
12623 json_object_double_add(
12624 json
, "/8equivalent",
12625 (double)(ts
.total_space
12626 * pow(2.0, -32 + 8)));
12629 snprintf(temp_buf
, sizeof(temp_buf
),
12632 * pow(2.0, -32 + 24));
12633 vty_out(vty
, "%30s: %s\n",
12634 "/24 equivalent ", temp_buf
);
12636 json_object_double_add(
12637 json
, "/24equivalent",
12638 (double)(ts
.total_space
12639 * pow(2.0, -32 + 24)));
12645 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12647 vty_out(vty
, "%-30s: %s",
12648 table_stats_strs
[i
]
12649 [TABLE_STATS_IDX_VTY
],
12652 json_object_int_add(
12654 table_stats_strs
[i
]
12655 [TABLE_STATS_IDX_JSON
],
12660 vty_out(vty
, "\n");
12664 json_object_array_add(json_array
, json
);
12668 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12669 safi_t safi
, struct json_object
*json_array
)
12672 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12673 return CMD_SUCCESS
;
12676 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12688 PCOUNT_BPATH_SELECTED
,
12689 PCOUNT_PFCNT
, /* the figure we display to users */
12693 static const char *const pcount_strs
[] = {
12694 [PCOUNT_ADJ_IN
] = "Adj-in",
12695 [PCOUNT_DAMPED
] = "Damped",
12696 [PCOUNT_REMOVED
] = "Removed",
12697 [PCOUNT_HISTORY
] = "History",
12698 [PCOUNT_STALE
] = "Stale",
12699 [PCOUNT_VALID
] = "Valid",
12700 [PCOUNT_ALL
] = "All RIB",
12701 [PCOUNT_COUNTED
] = "PfxCt counted",
12702 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12703 [PCOUNT_PFCNT
] = "Useable",
12704 [PCOUNT_MAX
] = NULL
,
12707 struct peer_pcounts
{
12708 unsigned int count
[PCOUNT_MAX
];
12709 const struct peer
*peer
;
12710 const struct bgp_table
*table
;
12714 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12716 const struct bgp_adj_in
*ain
;
12717 const struct bgp_path_info
*pi
;
12718 const struct peer
*peer
= pc
->peer
;
12720 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12721 if (ain
->peer
== peer
)
12722 pc
->count
[PCOUNT_ADJ_IN
]++;
12724 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12726 if (pi
->peer
!= peer
)
12729 pc
->count
[PCOUNT_ALL
]++;
12731 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12732 pc
->count
[PCOUNT_DAMPED
]++;
12733 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12734 pc
->count
[PCOUNT_HISTORY
]++;
12735 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12736 pc
->count
[PCOUNT_REMOVED
]++;
12737 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12738 pc
->count
[PCOUNT_STALE
]++;
12739 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12740 pc
->count
[PCOUNT_VALID
]++;
12741 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12742 pc
->count
[PCOUNT_PFCNT
]++;
12743 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12744 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12746 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12747 pc
->count
[PCOUNT_COUNTED
]++;
12748 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12750 EC_LIB_DEVELOPMENT
,
12751 "Attempting to count but flags say it is unusable");
12753 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12755 EC_LIB_DEVELOPMENT
,
12756 "Not counted but flags say we should");
12761 static int bgp_peer_count_walker(struct thread
*t
)
12763 struct bgp_dest
*rn
, *rm
;
12764 const struct bgp_table
*table
;
12765 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12767 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12768 || pc
->safi
== SAFI_EVPN
) {
12769 /* Special handling for 2-level routing tables. */
12770 for (rn
= bgp_table_top(pc
->table
); rn
;
12771 rn
= bgp_route_next(rn
)) {
12772 table
= bgp_dest_get_bgp_table_info(rn
);
12774 for (rm
= bgp_table_top(table
); rm
;
12775 rm
= bgp_route_next(rm
))
12776 bgp_peer_count_proc(rm
, pc
);
12779 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
12780 bgp_peer_count_proc(rn
, pc
);
12785 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12786 safi_t safi
, bool use_json
)
12788 struct peer_pcounts pcounts
= {.peer
= peer
};
12790 json_object
*json
= NULL
;
12791 json_object
*json_loop
= NULL
;
12794 json
= json_object_new_object();
12795 json_loop
= json_object_new_object();
12798 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
12799 || !peer
->bgp
->rib
[afi
][safi
]) {
12801 json_object_string_add(
12803 "No such neighbor or address family");
12804 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12805 json_object_free(json
);
12806 json_object_free(json_loop
);
12808 vty_out(vty
, "%% No such neighbor or address family\n");
12810 return CMD_WARNING
;
12813 memset(&pcounts
, 0, sizeof(pcounts
));
12814 pcounts
.peer
= peer
;
12815 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
12816 pcounts
.safi
= safi
;
12818 /* in-place call via thread subsystem so as to record execution time
12819 * stats for the thread-walk (i.e. ensure this can't be blamed on
12820 * on just vty_read()).
12822 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
12825 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
12826 json_object_string_add(json
, "multiProtocol",
12827 get_afi_safi_str(afi
, safi
, true));
12828 json_object_int_add(json
, "pfxCounter",
12829 peer
->pcount
[afi
][safi
]);
12831 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12832 json_object_int_add(json_loop
, pcount_strs
[i
],
12835 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12837 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12838 json_object_string_add(json
, "pfxctDriftFor",
12840 json_object_string_add(
12841 json
, "recommended",
12842 "Please report this bug, with the above command output");
12844 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12845 json
, JSON_C_TO_STRING_PRETTY
));
12846 json_object_free(json
);
12850 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12851 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12852 peer
->hostname
, peer
->host
,
12853 get_afi_safi_str(afi
, safi
, false));
12855 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12856 get_afi_safi_str(afi
, safi
, false));
12859 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12860 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12862 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12863 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12866 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12867 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12869 "Please report this bug, with the above command output\n");
12873 return CMD_SUCCESS
;
12876 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12877 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12878 "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]",
12882 BGP_INSTANCE_HELP_STR
12885 "Detailed information on TCP and BGP neighbor connections\n"
12886 "Neighbor to display information about\n"
12887 "Neighbor to display information about\n"
12888 "Neighbor on BGP configured interface\n"
12889 "Display detailed prefix count information\n"
12892 afi_t afi
= AFI_IP6
;
12893 safi_t safi
= SAFI_UNICAST
;
12896 struct bgp
*bgp
= NULL
;
12897 bool uj
= use_json(argc
, argv
);
12902 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12905 return CMD_WARNING
;
12907 argv_find(argv
, argc
, "neighbors", &idx
);
12908 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12910 return CMD_WARNING
;
12912 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12915 #ifdef KEEP_OLD_VPN_COMMANDS
12916 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12917 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12918 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12923 "Display information about all VPNv4 NLRIs\n"
12924 "Detailed information on TCP and BGP neighbor connections\n"
12925 "Neighbor to display information about\n"
12926 "Neighbor to display information about\n"
12927 "Neighbor on BGP configured interface\n"
12928 "Display detailed prefix count information\n"
12933 bool uj
= use_json(argc
, argv
);
12935 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12937 return CMD_WARNING
;
12939 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12942 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12943 show_ip_bgp_vpn_all_route_prefix_cmd
,
12944 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12949 "Display information about all VPNv4 NLRIs\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 struct bgp
*bgp
= bgp_get_default();
12958 vty_out(vty
, "Can't find default instance\n");
12959 return CMD_WARNING
;
12962 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12963 network
= argv
[idx
]->arg
;
12964 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12965 network
= argv
[idx
]->arg
;
12967 vty_out(vty
, "Unable to figure out Network\n");
12968 return CMD_WARNING
;
12971 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12972 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12974 #endif /* KEEP_OLD_VPN_COMMANDS */
12976 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12977 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12978 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12983 "Network in the BGP routing table to display\n"
12984 "Network in the BGP routing table to display\n"
12985 "Network in the BGP routing table to display\n"
12986 "Network in the BGP routing table to display\n"
12990 char *network
= NULL
;
12991 int prefix_check
= 0;
12993 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12994 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12995 network
= argv
[idx
]->arg
;
12996 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12997 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12998 network
= argv
[idx
]->arg
;
13001 vty_out(vty
, "Unable to figure out Network\n");
13002 return CMD_WARNING
;
13004 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13005 prefix_check
, BGP_PATH_SHOW_ALL
,
13006 use_json(argc
, argv
));
13009 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13010 struct bgp_table
*table
, int *header1
,
13011 int *header2
, json_object
*json
,
13012 json_object
*json_scode
,
13013 json_object
*json_ocode
, bool wide
)
13015 uint64_t version
= table
? table
->version
: 0;
13016 char buf
[BUFSIZ
] = {0};
13020 json_object_int_add(json
, "bgpTableVersion", version
);
13021 json_object_string_add(json
, "bgpLocalRouterId",
13023 &bgp
->router_id
, buf
,
13025 json_object_int_add(json
, "defaultLocPrf",
13026 bgp
->default_local_pref
);
13027 json_object_int_add(json
, "localAS", bgp
->as
);
13028 json_object_object_add(json
, "bgpStatusCodes",
13030 json_object_object_add(json
, "bgpOriginCodes",
13034 "BGP table version is %" PRIu64
13035 ", local router ID is %pI4, vrf id ",
13036 version
, &bgp
->router_id
);
13037 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13038 vty_out(vty
, "%s", VRFID_NONE_STR
);
13040 vty_out(vty
, "%u", bgp
->vrf_id
);
13041 vty_out(vty
, "\n");
13042 vty_out(vty
, "Default local pref %u, ",
13043 bgp
->default_local_pref
);
13044 vty_out(vty
, "local AS %u\n", bgp
->as
);
13045 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13046 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13047 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13053 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13054 : BGP_SHOW_HEADER
));
13060 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13061 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13062 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13063 json_object
*json_scode
, json_object
*json_ocode
,
13064 uint8_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13065 unsigned long *output_count
, unsigned long *filtered_count
)
13067 struct bgp_adj_in
*ain
;
13068 struct bgp_adj_out
*adj
;
13069 struct bgp_dest
*dest
;
13073 struct update_subgroup
*subgrp
;
13074 struct peer_af
*paf
;
13075 bool route_filtered
;
13076 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13077 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13078 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13079 || (safi
== SAFI_EVPN
))
13087 json_object_string_add(json
, "alert", "no BGP");
13088 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13089 json_object_free(json
);
13091 vty_out(vty
, "%% No bgp\n");
13095 subgrp
= peer_subgroup(peer
, afi
, safi
);
13097 if (type
== bgp_show_adj_route_advertised
&& subgrp
13098 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13099 char buf
[BUFSIZ
] = {0};
13102 json_object_int_add(json
, "bgpTableVersion",
13104 json_object_string_add(json
, "bgpLocalRouterId",
13106 &bgp
->router_id
, buf
,
13108 json_object_int_add(json
, "defaultLocPrf",
13109 bgp
->default_local_pref
);
13110 json_object_int_add(json
, "localAS", bgp
->as
);
13111 json_object_object_add(json
, "bgpStatusCodes",
13113 json_object_object_add(json
, "bgpOriginCodes",
13115 json_object_string_add(
13116 json
, "bgpOriginatingDefaultNetwork",
13117 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13120 "BGP table version is %" PRIu64
13121 ", local router ID is %pI4, vrf id ",
13122 table
->version
, &bgp
->router_id
);
13123 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13124 vty_out(vty
, "%s", VRFID_NONE_STR
);
13126 vty_out(vty
, "%u", bgp
->vrf_id
);
13127 vty_out(vty
, "\n");
13128 vty_out(vty
, "Default local pref %u, ",
13129 bgp
->default_local_pref
);
13130 vty_out(vty
, "local AS %u\n", bgp
->as
);
13131 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13132 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13133 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13135 vty_out(vty
, "Originating default network %s\n\n",
13136 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13141 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13142 if (type
== bgp_show_adj_route_received
13143 || type
== bgp_show_adj_route_filtered
) {
13144 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13145 if (ain
->peer
!= peer
)
13148 show_adj_route_header(vty
, bgp
, table
, header1
,
13149 header2
, json
, json_scode
,
13152 if ((safi
== SAFI_MPLS_VPN
)
13153 || (safi
== SAFI_ENCAP
)
13154 || (safi
== SAFI_EVPN
)) {
13156 json_object_string_add(
13157 json_ar
, "rd", rd_str
);
13158 else if (show_rd
&& rd_str
) {
13160 "Route Distinguisher: %s\n",
13167 route_filtered
= false;
13169 /* Filter prefix using distribute list,
13170 * filter list or prefix list
13172 const struct prefix
*rn_p
=
13173 bgp_dest_get_prefix(dest
);
13174 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13177 route_filtered
= true;
13179 /* Filter prefix using route-map */
13180 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13181 safi
, rmap_name
, NULL
,
13184 if (type
== bgp_show_adj_route_filtered
&&
13185 !route_filtered
&& ret
!= RMAP_DENY
) {
13186 bgp_attr_undup(&attr
, ain
->attr
);
13190 if (type
== bgp_show_adj_route_received
13191 && (route_filtered
|| ret
== RMAP_DENY
))
13192 (*filtered_count
)++;
13194 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
13195 use_json
, json_ar
, wide
);
13196 bgp_attr_undup(&attr
, ain
->attr
);
13199 } else if (type
== bgp_show_adj_route_advertised
) {
13200 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13201 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13202 if (paf
->peer
!= peer
|| !adj
->attr
)
13205 show_adj_route_header(vty
, bgp
, table
,
13210 const struct prefix
*rn_p
=
13211 bgp_dest_get_prefix(dest
);
13214 ret
= bgp_output_modifier(
13215 peer
, rn_p
, &attr
, afi
, safi
,
13218 if (ret
!= RMAP_DENY
) {
13219 if ((safi
== SAFI_MPLS_VPN
)
13220 || (safi
== SAFI_ENCAP
)
13221 || (safi
== SAFI_EVPN
)) {
13223 json_object_string_add(
13230 "Route Distinguisher: %s\n",
13236 vty
, rn_p
, &attr
, safi
,
13241 (*filtered_count
)++;
13244 bgp_attr_undup(&attr
, adj
->attr
);
13246 } else if (type
== bgp_show_adj_route_bestpath
) {
13247 struct bgp_path_info
*pi
;
13249 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13250 json
, json_scode
, json_ocode
,
13253 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13255 if (pi
->peer
!= peer
)
13258 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13261 route_vty_out_tmp(vty
,
13262 bgp_dest_get_prefix(dest
),
13263 pi
->attr
, safi
, use_json
,
13271 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13272 safi_t safi
, enum bgp_show_adj_route_type type
,
13273 const char *rmap_name
, uint8_t show_flags
)
13276 struct bgp_table
*table
;
13277 json_object
*json
= NULL
;
13278 json_object
*json_scode
= NULL
;
13279 json_object
*json_ocode
= NULL
;
13280 json_object
*json_ar
= NULL
;
13281 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13283 /* Init BGP headers here so they're only displayed once
13284 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13290 * Initialize variables for each RD
13291 * All prefixes under an RD is aggregated within "json_routes"
13293 char rd_str
[BUFSIZ
] = {0};
13294 json_object
*json_routes
= NULL
;
13297 /* For 2-tier tables, prefix counts need to be
13298 * maintained across multiple runs of show_adj_route()
13300 unsigned long output_count_per_rd
;
13301 unsigned long filtered_count_per_rd
;
13302 unsigned long output_count
= 0;
13303 unsigned long filtered_count
= 0;
13306 json
= json_object_new_object();
13307 json_ar
= json_object_new_object();
13308 json_scode
= json_object_new_object();
13309 json_ocode
= json_object_new_object();
13311 json_object_string_add(json_scode
, "suppressed", "s");
13312 json_object_string_add(json_scode
, "damped", "d");
13313 json_object_string_add(json_scode
, "history", "h");
13314 json_object_string_add(json_scode
, "valid", "*");
13315 json_object_string_add(json_scode
, "best", ">");
13316 json_object_string_add(json_scode
, "multipath", "=");
13317 json_object_string_add(json_scode
, "internal", "i");
13318 json_object_string_add(json_scode
, "ribFailure", "r");
13319 json_object_string_add(json_scode
, "stale", "S");
13320 json_object_string_add(json_scode
, "removed", "R");
13322 json_object_string_add(json_ocode
, "igp", "i");
13323 json_object_string_add(json_ocode
, "egp", "e");
13324 json_object_string_add(json_ocode
, "incomplete", "?");
13327 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13329 json_object_string_add(
13331 "No such neighbor or address family");
13332 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13333 json_object_free(json
);
13335 vty_out(vty
, "%% No such neighbor or address family\n");
13337 return CMD_WARNING
;
13340 if ((type
== bgp_show_adj_route_received
13341 || type
== bgp_show_adj_route_filtered
)
13342 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13343 PEER_FLAG_SOFT_RECONFIG
)) {
13345 json_object_string_add(
13347 "Inbound soft reconfiguration not enabled");
13348 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13349 json_object_free(json
);
13352 "%% Inbound soft reconfiguration not enabled\n");
13354 return CMD_WARNING
;
13359 /* labeled-unicast routes live in the unicast table */
13360 if (safi
== SAFI_LABELED_UNICAST
)
13361 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13363 table
= bgp
->rib
[afi
][safi
];
13365 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13366 || (safi
== SAFI_EVPN
)) {
13368 struct bgp_dest
*dest
;
13370 for (dest
= bgp_table_top(table
); dest
;
13371 dest
= bgp_route_next(dest
)) {
13372 table
= bgp_dest_get_bgp_table_info(dest
);
13376 output_count_per_rd
= 0;
13377 filtered_count_per_rd
= 0;
13380 json_routes
= json_object_new_object();
13382 const struct prefix_rd
*prd
;
13383 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13386 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13388 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13389 rmap_name
, json
, json_routes
, json_scode
,
13390 json_ocode
, show_flags
, &header1
,
13391 &header2
, rd_str
, &output_count_per_rd
,
13392 &filtered_count_per_rd
);
13394 /* Don't include an empty RD in the output! */
13395 if (json_routes
&& (output_count_per_rd
> 0))
13396 json_object_object_add(json_ar
, rd_str
,
13399 output_count
+= output_count_per_rd
;
13400 filtered_count
+= filtered_count_per_rd
;
13403 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13404 json
, json_ar
, json_scode
, json_ocode
,
13405 show_flags
, &header1
, &header2
, rd_str
,
13406 &output_count
, &filtered_count
);
13409 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13410 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13411 json_object_int_add(json
, "filteredPrefixCounter",
13414 vty_out(vty
, "%s\n",
13415 json_object_to_json_string_ext(
13416 json
, JSON_C_TO_STRING_PRETTY
));
13418 if (!output_count
&& !filtered_count
) {
13419 json_object_free(json_scode
);
13420 json_object_free(json_ocode
);
13424 json_object_free(json
);
13426 } else if (output_count
> 0) {
13427 if (filtered_count
> 0)
13429 "\nTotal number of prefixes %ld (%ld filtered)\n",
13430 output_count
, filtered_count
);
13432 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13436 return CMD_SUCCESS
;
13439 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13440 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13441 "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]",
13445 BGP_INSTANCE_HELP_STR
13447 BGP_SAFI_WITH_LABEL_HELP_STR
13448 "Detailed information on TCP and BGP neighbor connections\n"
13449 "Neighbor to display information about\n"
13450 "Neighbor to display information about\n"
13451 "Neighbor on BGP configured interface\n"
13452 "Display the routes selected by best path\n"
13454 "Increase table width for longer prefixes\n")
13456 afi_t afi
= AFI_IP6
;
13457 safi_t safi
= SAFI_UNICAST
;
13458 char *rmap_name
= NULL
;
13459 char *peerstr
= NULL
;
13460 struct bgp
*bgp
= NULL
;
13462 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13464 uint8_t show_flags
= 0;
13467 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13470 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13472 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13476 return CMD_WARNING
;
13478 argv_find(argv
, argc
, "neighbors", &idx
);
13479 peerstr
= argv
[++idx
]->arg
;
13481 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13483 return CMD_WARNING
;
13485 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13489 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13490 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13491 "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]",
13495 BGP_INSTANCE_HELP_STR
13497 BGP_SAFI_WITH_LABEL_HELP_STR
13498 "Display the entries for all address families\n"
13499 "Detailed information on TCP and BGP neighbor connections\n"
13500 "Neighbor to display information about\n"
13501 "Neighbor to display information about\n"
13502 "Neighbor on BGP configured interface\n"
13503 "Display the routes advertised to a BGP neighbor\n"
13504 "Display the received routes from neighbor\n"
13505 "Display the filtered routes received from neighbor\n"
13506 "Route-map to modify the attributes\n"
13507 "Name of the route map\n"
13509 "Increase table width for longer prefixes\n")
13511 afi_t afi
= AFI_IP6
;
13512 safi_t safi
= SAFI_UNICAST
;
13513 char *rmap_name
= NULL
;
13514 char *peerstr
= NULL
;
13515 struct bgp
*bgp
= NULL
;
13517 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13520 uint8_t show_flags
= 0;
13524 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13528 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13529 if (argv_find(argv
, argc
, "ipv4", &idx
))
13530 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13532 if (argv_find(argv
, argc
, "ipv6", &idx
))
13533 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13537 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13539 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13542 return CMD_WARNING
;
13544 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13545 argv_find(argv
, argc
, "neighbors", &idx
);
13546 peerstr
= argv
[++idx
]->arg
;
13548 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13550 return CMD_WARNING
;
13552 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13553 type
= bgp_show_adj_route_advertised
;
13554 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13555 type
= bgp_show_adj_route_received
;
13556 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13557 type
= bgp_show_adj_route_filtered
;
13559 if (argv_find(argv
, argc
, "route-map", &idx
))
13560 rmap_name
= argv
[++idx
]->arg
;
13563 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13566 vty_out(vty
, "{\n");
13568 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13569 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13570 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13572 FOREACH_SAFI (safi
) {
13573 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13580 vty_out(vty
, ",\n");
13581 vty_out(vty
, "\"%s\":",
13582 get_afi_safi_str(afi
, safi
, true));
13584 vty_out(vty
, "\nFor address family: %s\n",
13585 get_afi_safi_str(afi
, safi
, false));
13587 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13591 FOREACH_AFI_SAFI (afi
, safi
) {
13592 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13599 vty_out(vty
, ",\n");
13600 vty_out(vty
, "\"%s\":",
13601 get_afi_safi_str(afi
, safi
, true));
13603 vty_out(vty
, "\nFor address family: %s\n",
13604 get_afi_safi_str(afi
, safi
, false));
13606 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13611 vty_out(vty
, "}\n");
13613 return CMD_SUCCESS
;
13616 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13617 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13618 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13624 "Address Family modifier\n"
13625 "Detailed information on TCP and BGP neighbor connections\n"
13626 "Neighbor to display information about\n"
13627 "Neighbor to display information about\n"
13628 "Neighbor on BGP configured interface\n"
13629 "Display information received from a BGP neighbor\n"
13630 "Display the prefixlist filter\n"
13633 afi_t afi
= AFI_IP6
;
13634 safi_t safi
= SAFI_UNICAST
;
13635 char *peerstr
= NULL
;
13638 union sockunion su
;
13644 /* show [ip] bgp */
13645 if (argv_find(argv
, argc
, "ip", &idx
))
13647 /* [<ipv4|ipv6> [unicast]] */
13648 if (argv_find(argv
, argc
, "ipv4", &idx
))
13650 if (argv_find(argv
, argc
, "ipv6", &idx
))
13652 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13653 argv_find(argv
, argc
, "neighbors", &idx
);
13654 peerstr
= argv
[++idx
]->arg
;
13656 bool uj
= use_json(argc
, argv
);
13658 ret
= str2sockunion(peerstr
, &su
);
13660 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13663 vty_out(vty
, "{}\n");
13666 "%% Malformed address or name: %s\n",
13668 return CMD_WARNING
;
13671 peer
= peer_lookup(NULL
, &su
);
13674 vty_out(vty
, "{}\n");
13676 vty_out(vty
, "No peer\n");
13677 return CMD_WARNING
;
13681 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13682 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13685 vty_out(vty
, "Address Family: %s\n",
13686 get_afi_safi_str(afi
, safi
, false));
13687 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13690 vty_out(vty
, "{}\n");
13692 vty_out(vty
, "No functional output\n");
13695 return CMD_SUCCESS
;
13698 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13699 afi_t afi
, safi_t safi
,
13700 enum bgp_show_type type
, bool use_json
)
13702 uint8_t show_flags
= 0;
13705 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13707 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13709 json_object
*json_no
= NULL
;
13710 json_no
= json_object_new_object();
13711 json_object_string_add(
13712 json_no
, "warning",
13713 "No such neighbor or address family");
13714 vty_out(vty
, "%s\n",
13715 json_object_to_json_string(json_no
));
13716 json_object_free(json_no
);
13718 vty_out(vty
, "%% No such neighbor or address family\n");
13719 return CMD_WARNING
;
13722 /* labeled-unicast routes live in the unicast table */
13723 if (safi
== SAFI_LABELED_UNICAST
)
13724 safi
= SAFI_UNICAST
;
13726 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
13729 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13730 show_ip_bgp_flowspec_routes_detailed_cmd
,
13731 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13735 BGP_INSTANCE_HELP_STR
13738 "Detailed information on flowspec entries\n"
13741 afi_t afi
= AFI_IP
;
13742 safi_t safi
= SAFI_UNICAST
;
13743 struct bgp
*bgp
= NULL
;
13745 bool uj
= use_json(argc
, argv
);
13746 uint8_t show_flags
= 0;
13750 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13753 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13756 return CMD_WARNING
;
13758 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13762 DEFUN (show_ip_bgp_neighbor_routes
,
13763 show_ip_bgp_neighbor_routes_cmd
,
13764 "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]",
13768 BGP_INSTANCE_HELP_STR
13770 BGP_SAFI_WITH_LABEL_HELP_STR
13771 "Detailed information on TCP and BGP neighbor connections\n"
13772 "Neighbor to display information about\n"
13773 "Neighbor to display information about\n"
13774 "Neighbor on BGP configured interface\n"
13775 "Display flap statistics of the routes learned from neighbor\n"
13776 "Display the dampened routes received from neighbor\n"
13777 "Display routes learned from neighbor\n"
13780 char *peerstr
= NULL
;
13781 struct bgp
*bgp
= NULL
;
13782 afi_t afi
= AFI_IP6
;
13783 safi_t safi
= SAFI_UNICAST
;
13785 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
13787 bool uj
= use_json(argc
, argv
);
13792 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13795 return CMD_WARNING
;
13797 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13798 argv_find(argv
, argc
, "neighbors", &idx
);
13799 peerstr
= argv
[++idx
]->arg
;
13801 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13803 return CMD_WARNING
;
13805 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
13806 sh_type
= bgp_show_type_flap_neighbor
;
13807 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
13808 sh_type
= bgp_show_type_damp_neighbor
;
13809 else if (argv_find(argv
, argc
, "routes", &idx
))
13810 sh_type
= bgp_show_type_neighbor
;
13812 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
13815 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
13817 struct bgp_distance
{
13818 /* Distance value for the IP source prefix. */
13821 /* Name of the access-list to be matched. */
13825 DEFUN (show_bgp_afi_vpn_rd_route
,
13826 show_bgp_afi_vpn_rd_route_cmd
,
13827 "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]",
13831 "Address Family modifier\n"
13832 "Display information for a route distinguisher\n"
13833 "Route Distinguisher\n"
13834 "Network in the BGP routing table to display\n"
13835 "Network in the BGP routing table to display\n"
13839 struct prefix_rd prd
;
13840 afi_t afi
= AFI_MAX
;
13843 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
13844 vty_out(vty
, "%% Malformed Address Family\n");
13845 return CMD_WARNING
;
13848 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
13850 vty_out(vty
, "%% Malformed Route Distinguisher\n");
13851 return CMD_WARNING
;
13854 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
13855 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
13858 static struct bgp_distance
*bgp_distance_new(void)
13860 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
13863 static void bgp_distance_free(struct bgp_distance
*bdistance
)
13865 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
13868 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
13869 const char *access_list_str
, afi_t afi
, safi_t safi
,
13870 char *errmsg
, size_t errmsg_len
)
13874 struct bgp_dest
*dest
;
13875 struct bgp_distance
*bdistance
;
13877 ret
= str2prefix(ip_str
, &p
);
13879 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13880 return CMD_WARNING_CONFIG_FAILED
;
13883 /* Get BGP distance node. */
13884 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
13885 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13887 bgp_dest_unlock_node(dest
);
13889 bdistance
= bgp_distance_new();
13890 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
13893 /* Set distance value. */
13894 bdistance
->distance
= distance
;
13896 /* Reset access-list configuration. */
13897 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13898 if (access_list_str
)
13899 bdistance
->access_list
=
13900 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
13902 return CMD_SUCCESS
;
13905 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
13906 const char *access_list_str
, afi_t afi
, safi_t safi
,
13907 char *errmsg
, size_t errmsg_len
)
13911 struct bgp_dest
*dest
;
13912 struct bgp_distance
*bdistance
;
13914 ret
= str2prefix(ip_str
, &p
);
13916 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13917 return CMD_WARNING_CONFIG_FAILED
;
13920 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13922 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
13923 return CMD_WARNING_CONFIG_FAILED
;
13926 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13928 if (bdistance
->distance
!= distance
) {
13929 snprintf(errmsg
, errmsg_len
,
13930 "Distance does not match configured\n");
13931 return CMD_WARNING_CONFIG_FAILED
;
13934 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13935 bgp_distance_free(bdistance
);
13937 bgp_dest_set_bgp_path_info(dest
, NULL
);
13938 bgp_dest_unlock_node(dest
);
13939 bgp_dest_unlock_node(dest
);
13941 return CMD_SUCCESS
;
13944 /* Apply BGP information to distance method. */
13945 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13946 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13948 struct bgp_dest
*dest
;
13949 struct prefix q
= {0};
13951 struct bgp_distance
*bdistance
;
13952 struct access_list
*alist
;
13953 struct bgp_static
*bgp_static
;
13958 peer
= pinfo
->peer
;
13960 if (pinfo
->attr
->distance
)
13961 return pinfo
->attr
->distance
;
13963 /* Check source address.
13964 * Note: for aggregate route, peer can have unspec af type.
13966 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
13967 && !sockunion2hostprefix(&peer
->su
, &q
))
13970 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13972 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13973 bgp_dest_unlock_node(dest
);
13975 if (bdistance
->access_list
) {
13976 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13978 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13979 return bdistance
->distance
;
13981 return bdistance
->distance
;
13984 /* Backdoor check. */
13985 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
13987 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13988 bgp_dest_unlock_node(dest
);
13990 if (bgp_static
->backdoor
) {
13991 if (bgp
->distance_local
[afi
][safi
])
13992 return bgp
->distance_local
[afi
][safi
];
13994 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13998 if (peer
->sort
== BGP_PEER_EBGP
) {
13999 if (bgp
->distance_ebgp
[afi
][safi
])
14000 return bgp
->distance_ebgp
[afi
][safi
];
14001 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14002 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14003 if (bgp
->distance_ibgp
[afi
][safi
])
14004 return bgp
->distance_ibgp
[afi
][safi
];
14005 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14007 if (bgp
->distance_local
[afi
][safi
])
14008 return bgp
->distance_local
[afi
][safi
];
14009 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14013 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14014 * we should tell ZEBRA update the routes for a specific
14015 * AFI/SAFI to reflect changes in RIB.
14017 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
14018 safi_t update_safi
)
14023 FOREACH_AFI_SAFI (afi
, safi
) {
14024 if (!bgp_fibupd_safi(safi
))
14027 if (afi
!= update_afi
&& safi
!= update_safi
)
14030 if (BGP_DEBUG(zebra
, ZEBRA
))
14032 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14033 __func__
, afi
, safi
);
14034 bgp_zebra_announce_table(bgp
, afi
, safi
);
14038 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
14039 "distance bgp (1-255) (1-255) (1-255)",
14040 "Define an administrative distance\n"
14042 "Distance for routes external to the AS\n"
14043 "Distance for routes internal to the AS\n"
14044 "Distance for local routes\n")
14046 int idx_number
= 2;
14047 int idx_number_2
= 3;
14048 int idx_number_3
= 4;
14051 char xpath
[XPATH_MAXLEN
];
14053 afi
= bgp_node_afi(vty
);
14054 safi
= bgp_node_safi(vty
);
14057 xpath
, sizeof(xpath
),
14058 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14059 yang_afi_safi_value2identity(afi
, safi
),
14060 bgp_afi_safi_get_container_str(afi
, safi
));
14061 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
14063 xpath
, sizeof(xpath
),
14064 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
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
,
14068 argv
[idx_number_2
]->arg
);
14070 xpath
, sizeof(xpath
),
14071 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14072 yang_afi_safi_value2identity(afi
, safi
),
14073 bgp_afi_safi_get_container_str(afi
, safi
));
14075 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14076 argv
[idx_number_3
]->arg
);
14078 return nb_cli_apply_changes(vty
, NULL
);
14081 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
14082 "no distance bgp [(1-255) (1-255) (1-255)]",
14084 "Define an administrative distance\n"
14086 "Distance for routes external to the AS\n"
14087 "Distance for routes internal to the AS\n"
14088 "Distance for local routes\n")
14092 char xpath
[XPATH_MAXLEN
];
14094 afi
= bgp_node_afi(vty
);
14095 safi
= bgp_node_safi(vty
);
14098 xpath
, sizeof(xpath
),
14099 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14100 yang_afi_safi_value2identity(afi
, safi
),
14101 bgp_afi_safi_get_container_str(afi
, safi
));
14102 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14104 xpath
, sizeof(xpath
),
14105 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14106 yang_afi_safi_value2identity(afi
, safi
),
14107 bgp_afi_safi_get_container_str(afi
, safi
));
14108 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14110 xpath
, sizeof(xpath
),
14111 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14112 yang_afi_safi_value2identity(afi
, safi
),
14113 bgp_afi_safi_get_container_str(afi
, safi
));
14115 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14117 return nb_cli_apply_changes(vty
, NULL
);
14120 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
14121 struct lyd_node
*dnode
,
14122 bool show_defaults
)
14124 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
14126 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14127 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14128 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14130 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14134 DEFPY_YANG(bgp_distance_source
,
14135 bgp_distance_source_cmd
,
14136 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14138 "Define an administrative distance\n"
14140 "IPv4 source prefix\n"
14141 "IPv6 source prefix\n"
14142 "Access list name\n")
14146 char xpath
[XPATH_MAXLEN
];
14148 afi
= bgp_node_afi(vty
);
14149 safi
= bgp_node_safi(vty
);
14152 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14153 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14156 nb_cli_enqueue_change(vty
,
14157 "./access-list-policy-export",
14158 NB_OP_CREATE
, acl
);
14160 nb_cli_enqueue_change(vty
,
14161 "./access-list-policy-export",
14162 NB_OP_DESTROY
, NULL
);
14164 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14168 xpath
, sizeof(xpath
),
14169 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14170 yang_afi_safi_value2identity(afi
, safi
),
14171 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14173 return nb_cli_apply_changes(vty
, xpath
);
14176 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14177 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14179 vty_out(vty
, " distance %d %s %s\n",
14180 yang_dnode_get_uint8(dnode
, "./distance"),
14181 yang_dnode_get_string(dnode
, "./prefix"),
14182 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14183 ? yang_dnode_get_string(dnode
,
14184 "./access-list-policy-export")
14189 bgp_dampening
, bgp_dampening_cmd
,
14190 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14192 "BGP Specific commands\n"
14193 "Enable route-flap dampening\n"
14194 "Half-life time for the penalty\n"
14195 "Value to start reusing a route\n"
14196 "Value to start suppressing a route\n"
14197 "Maximum duration to suppress a stable route\n")
14201 char xpath
[XPATH_MAXLEN
];
14203 afi
= bgp_node_afi(vty
);
14204 safi
= bgp_node_safi(vty
);
14207 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14209 nb_cli_enqueue_change(vty
, "./reach-decay",
14210 NB_OP_MODIFY
, halflife_str
);
14211 nb_cli_enqueue_change(vty
, "./reuse-above",
14212 NB_OP_MODIFY
, reuse_str
);
14213 nb_cli_enqueue_change(vty
, "./suppress-above",
14214 NB_OP_MODIFY
, suppress_str
);
14215 nb_cli_enqueue_change(vty
, "./unreach-decay",
14216 NB_OP_MODIFY
, max_suppress_str
);
14218 nb_cli_enqueue_change(vty
, "./reach-decay",
14219 NB_OP_MODIFY
, halflife_str
);
14222 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14226 xpath
, sizeof(xpath
),
14227 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14228 yang_afi_safi_value2identity(afi
, safi
),
14229 bgp_afi_safi_get_container_str(afi
, safi
));
14231 return nb_cli_apply_changes(vty
, xpath
);
14234 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14235 struct lyd_node
*dnode
,
14236 bool show_defaults
)
14238 if (!yang_dnode_get_bool(dnode
, "./enable"))
14241 int half
= DEFAULT_HALF_LIFE
* 60;
14242 int reuse
= DEFAULT_REUSE
;
14243 int suppress
= DEFAULT_SUPPRESS
;
14246 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14247 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14248 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14249 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14251 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14252 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14253 vty_out(vty
, " bgp dampening\n");
14254 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14255 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14256 vty_out(vty
, " bgp dampening %u\n", half
);
14258 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14262 /* Display specified route of BGP table. */
14263 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14264 const char *ip_str
, afi_t afi
, safi_t safi
,
14265 struct prefix_rd
*prd
, int prefix_check
)
14268 struct prefix match
;
14269 struct bgp_dest
*dest
;
14270 struct bgp_dest
*rm
;
14271 struct bgp_path_info
*pi
;
14272 struct bgp_path_info
*pi_temp
;
14274 struct bgp_table
*table
;
14276 /* BGP structure lookup. */
14278 bgp
= bgp_lookup_by_name(view_name
);
14280 vty_out(vty
, "%% Can't find BGP instance %s\n",
14282 return CMD_WARNING
;
14285 bgp
= bgp_get_default();
14287 vty_out(vty
, "%% No BGP process is configured\n");
14288 return CMD_WARNING
;
14292 /* Check IP address argument. */
14293 ret
= str2prefix(ip_str
, &match
);
14295 vty_out(vty
, "%% address is malformed\n");
14296 return CMD_WARNING
;
14299 match
.family
= afi2family(afi
);
14301 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14302 || (safi
== SAFI_EVPN
)) {
14303 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14304 dest
= bgp_route_next(dest
)) {
14305 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14307 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14309 table
= bgp_dest_get_bgp_table_info(dest
);
14312 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
14315 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14318 || rm_p
->prefixlen
== match
.prefixlen
) {
14319 pi
= bgp_dest_get_bgp_path_info(rm
);
14321 if (pi
->extra
&& pi
->extra
->damp_info
) {
14322 pi_temp
= pi
->next
;
14323 bgp_damp_info_free(
14324 &pi
->extra
->damp_info
,
14325 &bgp
->damp
[afi
][safi
],
14333 bgp_dest_unlock_node(rm
);
14336 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
14338 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14341 || dest_p
->prefixlen
== match
.prefixlen
) {
14342 pi
= bgp_dest_get_bgp_path_info(dest
);
14344 if (pi
->extra
&& pi
->extra
->damp_info
) {
14345 pi_temp
= pi
->next
;
14346 struct bgp_damp_info
*bdi
=
14347 pi
->extra
->damp_info
;
14348 if (bdi
->lastrecord
14349 == BGP_RECORD_UPDATE
) {
14350 bgp_aggregate_increment(
14361 bgp_damp_info_free(
14362 &pi
->extra
->damp_info
,
14363 &bgp
->damp
[afi
][safi
],
14371 bgp_dest_unlock_node(dest
);
14375 return CMD_SUCCESS
;
14378 DEFUN (clear_ip_bgp_dampening
,
14379 clear_ip_bgp_dampening_cmd
,
14380 "clear ip bgp dampening",
14384 "Clear route flap dampening information\n")
14386 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14387 bgp_damp_info_clean(bgp
, &bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14389 return CMD_SUCCESS
;
14392 DEFUN (clear_ip_bgp_dampening_prefix
,
14393 clear_ip_bgp_dampening_prefix_cmd
,
14394 "clear ip bgp dampening A.B.C.D/M",
14398 "Clear route flap dampening information\n"
14401 int idx_ipv4_prefixlen
= 4;
14402 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14403 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14406 DEFUN (clear_ip_bgp_dampening_address
,
14407 clear_ip_bgp_dampening_address_cmd
,
14408 "clear ip bgp dampening A.B.C.D",
14412 "Clear route flap dampening information\n"
14413 "Network to clear damping information\n")
14416 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14417 SAFI_UNICAST
, NULL
, 0);
14420 DEFUN (clear_ip_bgp_dampening_address_mask
,
14421 clear_ip_bgp_dampening_address_mask_cmd
,
14422 "clear ip bgp dampening A.B.C.D A.B.C.D",
14426 "Clear route flap dampening information\n"
14427 "Network to clear damping information\n"
14431 int idx_ipv4_2
= 5;
14433 char prefix_str
[BUFSIZ
];
14435 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14436 prefix_str
, sizeof(prefix_str
));
14438 vty_out(vty
, "%% Inconsistent address and mask\n");
14439 return CMD_WARNING
;
14442 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14446 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14448 struct vty
*vty
= arg
;
14449 struct peer
*peer
= bucket
->data
;
14450 char buf
[SU_ADDRSTRLEN
];
14452 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14453 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14456 DEFUN (show_bgp_listeners
,
14457 show_bgp_listeners_cmd
,
14458 "show bgp listeners",
14461 "Display Listen Sockets and who created them\n")
14463 bgp_dump_listener_info(vty
);
14465 return CMD_SUCCESS
;
14468 DEFUN (show_bgp_peerhash
,
14469 show_bgp_peerhash_cmd
,
14470 "show bgp peerhash",
14473 "Display information about the BGP peerhash\n")
14475 struct list
*instances
= bm
->bgp
;
14476 struct listnode
*node
;
14479 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14480 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14481 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14485 return CMD_SUCCESS
;
14488 /* also used for encap safi */
14489 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14490 afi_t afi
, safi_t safi
)
14492 struct bgp_dest
*pdest
;
14493 struct bgp_dest
*dest
;
14494 struct bgp_table
*table
;
14495 const struct prefix
*p
;
14496 const struct prefix_rd
*prd
;
14497 struct bgp_static
*bgp_static
;
14498 mpls_label_t label
;
14499 char rdbuf
[RD_ADDRSTRLEN
];
14501 /* Network configuration. */
14502 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14503 pdest
= bgp_route_next(pdest
)) {
14504 table
= bgp_dest_get_bgp_table_info(pdest
);
14508 for (dest
= bgp_table_top(table
); dest
;
14509 dest
= bgp_route_next(dest
)) {
14510 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14511 if (bgp_static
== NULL
)
14514 p
= bgp_dest_get_prefix(dest
);
14515 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14518 /* "network" configuration display. */
14519 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14520 label
= decode_label(&bgp_static
->label
);
14522 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14523 if (safi
== SAFI_MPLS_VPN
)
14524 vty_out(vty
, " label %u", label
);
14526 if (bgp_static
->rmap
.name
)
14527 vty_out(vty
, " route-map %s",
14528 bgp_static
->rmap
.name
);
14530 if (bgp_static
->backdoor
)
14531 vty_out(vty
, " backdoor");
14533 vty_out(vty
, "\n");
14538 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14539 afi_t afi
, safi_t safi
)
14541 struct bgp_dest
*pdest
;
14542 struct bgp_dest
*dest
;
14543 struct bgp_table
*table
;
14544 const struct prefix
*p
;
14545 const struct prefix_rd
*prd
;
14546 struct bgp_static
*bgp_static
;
14547 char buf
[PREFIX_STRLEN
* 2];
14548 char buf2
[SU_ADDRSTRLEN
];
14549 char rdbuf
[RD_ADDRSTRLEN
];
14550 char esi_buf
[ESI_BYTES
];
14552 /* Network configuration. */
14553 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14554 pdest
= bgp_route_next(pdest
)) {
14555 table
= bgp_dest_get_bgp_table_info(pdest
);
14559 for (dest
= bgp_table_top(table
); dest
;
14560 dest
= bgp_route_next(dest
)) {
14561 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14562 if (bgp_static
== NULL
)
14565 char *macrouter
= NULL
;
14567 if (bgp_static
->router_mac
)
14568 macrouter
= prefix_mac2str(
14569 bgp_static
->router_mac
, NULL
, 0);
14570 if (bgp_static
->eth_s_id
)
14571 esi_to_str(bgp_static
->eth_s_id
,
14572 esi_buf
, sizeof(esi_buf
));
14573 p
= bgp_dest_get_prefix(dest
);
14574 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14576 /* "network" configuration display. */
14577 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14578 if (p
->u
.prefix_evpn
.route_type
== 5) {
14579 char local_buf
[PREFIX_STRLEN
];
14580 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14581 struct prefix_evpn
*)p
)
14585 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14586 local_buf
, PREFIX_STRLEN
);
14587 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14588 p
->u
.prefix_evpn
.prefix_addr
14589 .ip_prefix_length
);
14591 prefix2str(p
, buf
, sizeof(buf
));
14594 if (bgp_static
->gatewayIp
.family
== AF_INET
14595 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14596 inet_ntop(bgp_static
->gatewayIp
.family
,
14597 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14600 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14602 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14603 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14606 XFREE(MTYPE_TMP
, macrouter
);
14611 /* Configuration of static route announcement and aggregate
14613 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14616 struct bgp_dest
*dest
;
14617 const struct prefix
*p
;
14618 struct bgp_static
*bgp_static
;
14619 struct bgp_aggregate
*bgp_aggregate
;
14621 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14622 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14626 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14627 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14631 /* Network configuration. */
14632 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14633 dest
= bgp_route_next(dest
)) {
14634 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14635 if (bgp_static
== NULL
)
14638 p
= bgp_dest_get_prefix(dest
);
14640 vty_out(vty
, " network %pFX", p
);
14642 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14643 vty_out(vty
, " label-index %u",
14644 bgp_static
->label_index
);
14646 if (bgp_static
->rmap
.name
)
14647 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14649 if (bgp_static
->backdoor
)
14650 vty_out(vty
, " backdoor");
14652 vty_out(vty
, "\n");
14655 /* Aggregate-address configuration. */
14656 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14657 dest
= bgp_route_next(dest
)) {
14658 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14659 if (bgp_aggregate
== NULL
)
14662 p
= bgp_dest_get_prefix(dest
);
14664 vty_out(vty
, " aggregate-address %pFX", p
);
14666 if (bgp_aggregate
->as_set
)
14667 vty_out(vty
, " as-set");
14669 if (bgp_aggregate
->summary_only
)
14670 vty_out(vty
, " summary-only");
14672 if (bgp_aggregate
->rmap
.name
)
14673 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14675 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14676 vty_out(vty
, " origin %s",
14677 bgp_origin2str(bgp_aggregate
->origin
));
14679 if (bgp_aggregate
->match_med
)
14680 vty_out(vty
, " matching-MED-only");
14682 if (bgp_aggregate
->suppress_map_name
)
14683 vty_out(vty
, " suppress-map %s",
14684 bgp_aggregate
->suppress_map_name
);
14686 vty_out(vty
, "\n");
14690 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14693 struct bgp_dest
*dest
;
14694 struct bgp_distance
*bdistance
;
14696 /* Distance configuration. */
14697 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
14698 && bgp
->distance_local
[afi
][safi
]
14699 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
14700 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
14701 || bgp
->distance_local
[afi
][safi
]
14702 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
14703 vty_out(vty
, " distance bgp %d %d %d\n",
14704 bgp
->distance_ebgp
[afi
][safi
],
14705 bgp
->distance_ibgp
[afi
][safi
],
14706 bgp
->distance_local
[afi
][safi
]);
14709 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14710 dest
= bgp_route_next(dest
)) {
14711 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14712 if (bdistance
!= NULL
)
14713 vty_out(vty
, " distance %d %pBD %s\n",
14714 bdistance
->distance
, dest
,
14715 bdistance
->access_list
? bdistance
->access_list
14720 /* Allocate routing table structure and install commands. */
14721 void bgp_route_init(void)
14726 /* Init BGP distance table. */
14727 FOREACH_AFI_SAFI (afi
, safi
)
14728 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14730 /* IPv4 BGP commands. */
14731 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14732 install_element(BGP_NODE
, &bgp_network_cmd
);
14733 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14735 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14737 /* IPv4 unicast configuration. */
14738 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14739 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14740 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14742 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14744 /* IPv4 multicast configuration. */
14745 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14746 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14747 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14748 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14750 /* IPv4 labeled-unicast configuration. */
14751 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14752 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14754 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14755 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14756 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14757 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14758 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14759 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14760 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14761 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14763 install_element(VIEW_NODE
,
14764 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14765 install_element(VIEW_NODE
,
14766 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
14767 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
14768 install_element(VIEW_NODE
,
14769 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
14770 #ifdef KEEP_OLD_VPN_COMMANDS
14771 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
14772 #endif /* KEEP_OLD_VPN_COMMANDS */
14773 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
14774 install_element(VIEW_NODE
,
14775 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
14777 /* BGP dampening clear commands */
14778 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
14779 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
14781 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
14782 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
14785 install_element(ENABLE_NODE
,
14786 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
14787 #ifdef KEEP_OLD_VPN_COMMANDS
14788 install_element(ENABLE_NODE
,
14789 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
14790 #endif /* KEEP_OLD_VPN_COMMANDS */
14792 /* New config IPv6 BGP commands. */
14793 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
14794 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
14795 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
14797 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
14799 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
14801 /* IPv6 labeled unicast address family. */
14802 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
14803 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
14805 install_element(BGP_NODE
, &bgp_distance_cmd
);
14806 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
14807 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
14808 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
14809 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
14810 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
14811 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
14812 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
14813 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
14814 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
14815 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
14816 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
14817 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
14818 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
14819 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
14821 /* BGP dampening */
14822 install_element(BGP_NODE
, &bgp_dampening_cmd
);
14823 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
14824 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
14825 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
14826 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
14827 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
14828 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
14830 /* Large Communities */
14831 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
14832 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
14834 /* show bgp ipv4 flowspec detailed */
14835 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
14837 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
14838 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
14841 void bgp_route_finish(void)
14846 FOREACH_AFI_SAFI (afi
, safi
) {
14847 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
14848 bgp_distance_table
[afi
][safi
] = NULL
;