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 /* Extern from bgp_dump.c */
97 extern const char *bgp_origin_str
[];
98 extern const char *bgp_origin_long_str
[];
101 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
102 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
103 static const struct message bgp_pmsi_tnltype_str
[] = {
104 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
105 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
106 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
107 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
108 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
109 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
110 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
111 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
115 #define VRFID_NONE_STR "-"
117 DEFINE_HOOK(bgp_process
,
118 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
119 struct peer
*peer
, bool withdraw
),
120 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
122 /** Test if path is suppressed. */
123 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
125 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
128 return listcount(pi
->extra
->aggr_suppressors
) > 0;
131 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
132 safi_t safi
, const struct prefix
*p
,
133 struct prefix_rd
*prd
)
135 struct bgp_dest
*dest
;
136 struct bgp_dest
*pdest
= NULL
;
140 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
141 || (safi
== SAFI_EVPN
)) {
142 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
144 if (!bgp_dest_has_bgp_path_info_data(pdest
))
145 bgp_dest_set_bgp_table_info(
146 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
148 bgp_dest_unlock_node(pdest
);
149 table
= bgp_dest_get_bgp_table_info(pdest
);
152 dest
= bgp_node_get(table
, p
);
154 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
155 || (safi
== SAFI_EVPN
))
161 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
162 safi_t safi
, const struct prefix
*p
,
163 struct prefix_rd
*prd
)
165 struct bgp_dest
*dest
;
166 struct bgp_dest
*pdest
= NULL
;
171 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
172 || (safi
== SAFI_EVPN
)) {
173 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
177 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
178 bgp_dest_unlock_node(pdest
);
182 table
= bgp_dest_get_bgp_table_info(pdest
);
185 dest
= bgp_node_lookup(table
, p
);
190 /* Allocate bgp_path_info_extra */
191 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
193 struct bgp_path_info_extra
*new;
194 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
195 sizeof(struct bgp_path_info_extra
));
196 new->label
[0] = MPLS_INVALID_LABEL
;
198 new->bgp_fs_pbr
= NULL
;
199 new->bgp_fs_iprule
= NULL
;
203 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
205 struct bgp_path_info_extra
*e
;
207 if (!extra
|| !*extra
)
214 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
217 /* FIXME: since multiple e may have the same e->parent
218 * and e->parent->net is holding a refcount for each
219 * of them, we need to do some fudging here.
221 * WARNING: if bpi->net->lock drops to 0, bpi may be
222 * freed as well (because bpi->net was holding the
223 * last reference to bpi) => write after free!
227 bpi
= bgp_path_info_lock(bpi
);
228 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
229 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
232 bgp_path_info_unlock(bpi
);
234 bgp_path_info_unlock(e
->parent
);
239 bgp_unlock(e
->bgp_orig
);
241 if (e
->aggr_suppressors
)
242 list_delete(&e
->aggr_suppressors
);
245 bgp_evpn_path_es_info_free(e
->es_info
);
247 if ((*extra
)->bgp_fs_iprule
)
248 list_delete(&((*extra
)->bgp_fs_iprule
));
249 if ((*extra
)->bgp_fs_pbr
)
250 list_delete(&((*extra
)->bgp_fs_pbr
));
251 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
254 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
255 * allocated if required.
257 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
260 pi
->extra
= bgp_path_info_extra_new();
264 /* Free bgp route information. */
265 static void bgp_path_info_free(struct bgp_path_info
*path
)
267 bgp_attr_unintern(&path
->attr
);
269 bgp_unlink_nexthop(path
);
270 bgp_path_info_extra_free(&path
->extra
);
271 bgp_path_info_mpath_free(&path
->mpath
);
273 bgp_addpath_free_info_data(&path
->tx_addpath
,
274 &path
->net
->tx_addpath
);
276 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
278 XFREE(MTYPE_BGP_ROUTE
, path
);
281 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
287 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
289 assert(path
&& path
->lock
> 0);
292 if (path
->lock
== 0) {
294 zlog_debug ("%s: unlocked and freeing", __func__
);
295 zlog_backtrace (LOG_DEBUG
);
297 bgp_path_info_free(path
);
304 zlog_debug ("%s: unlocked to 1", __func__
);
305 zlog_backtrace (LOG_DEBUG
);
312 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
313 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
316 struct bgp_path_info
*old_pi
, *nextpi
;
317 bool set_flag
= false;
318 struct bgp
*bgp
= NULL
;
319 struct bgp_table
*table
= NULL
;
323 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
324 * then the route selection is deferred
326 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
329 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
330 if (BGP_DEBUG(update
, UPDATE_OUT
))
332 "Route %pBD is in workqueue and being processed, not deferred.",
338 table
= bgp_dest_table(dest
);
345 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
346 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
347 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
350 /* Route selection is deferred if there is a stale path which
351 * which indicates peer is in restart mode
353 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
354 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
357 /* If the peer is graceful restart capable and peer is
358 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
361 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
362 && BGP_PEER_RESTARTING_MODE(peer
)
364 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
372 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
375 if (set_flag
&& table
) {
376 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
377 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
378 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
379 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
380 if (BGP_DEBUG(update
, UPDATE_OUT
))
381 zlog_debug("DEFER route %pBD, dest %p", dest
,
389 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
391 struct bgp_path_info
*top
;
393 top
= bgp_dest_get_bgp_path_info(dest
);
399 bgp_dest_set_bgp_path_info(dest
, pi
);
401 bgp_path_info_lock(pi
);
402 bgp_dest_lock_node(dest
);
403 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
404 bgp_dest_set_defer_flag(dest
, false);
407 /* Do the actual removal of info from RIB, for use by bgp_process
408 completion callback *only* */
409 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
412 pi
->next
->prev
= pi
->prev
;
414 pi
->prev
->next
= pi
->next
;
416 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
418 bgp_path_info_mpath_dequeue(pi
);
419 bgp_path_info_unlock(pi
);
420 bgp_dest_unlock_node(dest
);
423 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
425 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
426 /* set of previous already took care of pcount */
427 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
430 /* undo the effects of a previous call to bgp_path_info_delete; typically
431 called when a route is deleted and then quickly re-added before the
432 deletion has been processed */
433 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
435 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
436 /* unset of previous already took care of pcount */
437 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
440 /* Adjust pcount as required */
441 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
443 struct bgp_table
*table
;
445 assert(dest
&& bgp_dest_table(dest
));
446 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
448 table
= bgp_dest_table(dest
);
450 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
453 if (!BGP_PATH_COUNTABLE(pi
)
454 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
456 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
458 /* slight hack, but more robust against errors. */
459 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
460 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
462 flog_err(EC_LIB_DEVELOPMENT
,
463 "Asked to decrement 0 prefix count for peer");
464 } else if (BGP_PATH_COUNTABLE(pi
)
465 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
466 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
467 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
471 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
472 struct bgp_path_info
*pi2
)
474 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
477 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
478 * This is here primarily to keep prefix-count in check.
480 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
483 SET_FLAG(pi
->flags
, flag
);
485 /* early bath if we know it's not a flag that changes countability state
487 if (!CHECK_FLAG(flag
,
488 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
491 bgp_pcount_adjust(dest
, pi
);
494 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
497 UNSET_FLAG(pi
->flags
, flag
);
499 /* early bath if we know it's not a flag that changes countability state
501 if (!CHECK_FLAG(flag
,
502 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
505 bgp_pcount_adjust(dest
, pi
);
508 /* Get MED value. If MED value is missing and "bgp bestpath
509 missing-as-worst" is specified, treat it as the worst value. */
510 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
512 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
515 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
522 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
524 if (pi
->addpath_rx_id
)
525 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
528 sprintf(buf
, "path %s", pi
->peer
->host
);
531 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
533 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
534 struct bgp_path_info
*exist
, int *paths_eq
,
535 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
536 char *pfx_buf
, afi_t afi
, safi_t safi
,
537 enum bgp_path_selection_reason
*reason
)
539 struct attr
*newattr
, *existattr
;
540 bgp_peer_sort_t new_sort
;
541 bgp_peer_sort_t exist_sort
;
547 uint32_t exist_weight
;
548 uint32_t newm
, existm
;
549 struct in_addr new_id
;
550 struct in_addr exist_id
;
553 int internal_as_route
;
556 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
557 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
559 uint32_t exist_mm_seq
;
566 bool new_origin
, exist_origin
;
572 *reason
= bgp_path_selection_none
;
574 zlog_debug("%s: new is NULL", pfx_buf
);
579 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
582 *reason
= bgp_path_selection_first
;
584 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
590 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
591 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
592 pfx_buf
, new_buf
, new->flags
, exist_buf
,
597 existattr
= exist
->attr
;
599 /* For EVPN routes, we cannot just go by local vs remote, we have to
600 * look at the MAC mobility sequence number, if present.
602 if (safi
== SAFI_EVPN
) {
603 /* This is an error condition described in RFC 7432 Section
605 * states that in this scenario "the PE MUST alert the operator"
607 * does not state what other action to take. In order to provide
609 * consistency in this scenario we are going to prefer the path
613 if (newattr
->sticky
!= existattr
->sticky
) {
616 bgp_dest_get_prefix(new->net
), pfx_buf
,
617 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
618 bgp_path_info_path_with_addpath_rx_str(new,
620 bgp_path_info_path_with_addpath_rx_str(
624 if (newattr
->sticky
&& !existattr
->sticky
) {
625 *reason
= bgp_path_selection_evpn_sticky_mac
;
628 "%s: %s wins over %s due to sticky MAC flag",
629 pfx_buf
, new_buf
, exist_buf
);
633 if (!newattr
->sticky
&& existattr
->sticky
) {
634 *reason
= bgp_path_selection_evpn_sticky_mac
;
637 "%s: %s loses to %s due to sticky MAC flag",
638 pfx_buf
, new_buf
, exist_buf
);
643 new_esi
= bgp_evpn_attr_get_esi(newattr
);
644 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
645 if (bgp_evpn_is_esi_valid(new_esi
) &&
646 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
652 /* If both paths have the same non-zero ES and
653 * one path is local it wins.
654 * PS: Note the local path wins even if the remote
655 * has the higher MM seq. The local path's
656 * MM seq will be fixed up to match the highest
657 * rem seq, subsequently.
660 char esi_buf
[ESI_STR_LEN
];
662 if (bgp_evpn_is_path_local(bgp
, new)) {
663 *reason
= bgp_path_selection_evpn_local_path
;
666 "%s: %s wins over %s as ES %s is same and local",
667 pfx_buf
, new_buf
, exist_buf
,
668 esi_to_str(new_esi
, esi_buf
,
672 if (bgp_evpn_is_path_local(bgp
, exist
)) {
673 *reason
= bgp_path_selection_evpn_local_path
;
676 "%s: %s loses to %s as ES %s is same and local",
677 pfx_buf
, new_buf
, exist_buf
,
678 esi_to_str(new_esi
, esi_buf
,
684 new_mm_seq
= mac_mobility_seqnum(newattr
);
685 exist_mm_seq
= mac_mobility_seqnum(existattr
);
687 if (new_mm_seq
> exist_mm_seq
) {
688 *reason
= bgp_path_selection_evpn_seq
;
691 "%s: %s wins over %s due to MM seq %u > %u",
692 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
697 if (new_mm_seq
< exist_mm_seq
) {
698 *reason
= bgp_path_selection_evpn_seq
;
701 "%s: %s loses to %s due to MM seq %u < %u",
702 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
707 /* if the sequence numbers and ESI are the same and one path
708 * is non-proxy it wins (over proxy)
710 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
711 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
712 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
713 old_proxy
!= new_proxy
) {
715 *reason
= bgp_path_selection_evpn_non_proxy
;
718 "%s: %s wins over %s, same seq/es and non-proxy",
719 pfx_buf
, new_buf
, exist_buf
);
723 *reason
= bgp_path_selection_evpn_non_proxy
;
726 "%s: %s loses to %s, same seq/es and non-proxy",
727 pfx_buf
, new_buf
, exist_buf
);
732 * if sequence numbers are the same path with the lowest IP
735 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
737 *reason
= bgp_path_selection_evpn_lower_ip
;
740 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
741 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
742 &new->attr
->nexthop
);
746 *reason
= bgp_path_selection_evpn_lower_ip
;
749 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
750 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
751 &new->attr
->nexthop
);
756 /* 1. Weight check. */
757 new_weight
= newattr
->weight
;
758 exist_weight
= existattr
->weight
;
760 if (new_weight
> exist_weight
) {
761 *reason
= bgp_path_selection_weight
;
763 zlog_debug("%s: %s wins over %s due to weight %d > %d",
764 pfx_buf
, new_buf
, exist_buf
, new_weight
,
769 if (new_weight
< exist_weight
) {
770 *reason
= bgp_path_selection_weight
;
772 zlog_debug("%s: %s loses to %s due to weight %d < %d",
773 pfx_buf
, new_buf
, exist_buf
, new_weight
,
778 /* 2. Local preference check. */
779 new_pref
= exist_pref
= bgp
->default_local_pref
;
781 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
782 new_pref
= newattr
->local_pref
;
783 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
784 exist_pref
= existattr
->local_pref
;
786 if (new_pref
> exist_pref
) {
787 *reason
= bgp_path_selection_local_pref
;
790 "%s: %s wins over %s due to localpref %d > %d",
791 pfx_buf
, new_buf
, exist_buf
, new_pref
,
796 if (new_pref
< exist_pref
) {
797 *reason
= bgp_path_selection_local_pref
;
800 "%s: %s loses to %s due to localpref %d < %d",
801 pfx_buf
, new_buf
, exist_buf
, new_pref
,
806 /* 3. Local route check. We prefer:
808 * - BGP_ROUTE_AGGREGATE
809 * - BGP_ROUTE_REDISTRIBUTE
811 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
812 new->sub_type
== BGP_ROUTE_IMPORTED
);
813 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
814 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
816 if (new_origin
&& !exist_origin
) {
817 *reason
= bgp_path_selection_local_route
;
820 "%s: %s wins over %s due to preferred BGP_ROUTE type",
821 pfx_buf
, new_buf
, exist_buf
);
825 if (!new_origin
&& exist_origin
) {
826 *reason
= bgp_path_selection_local_route
;
829 "%s: %s loses to %s due to preferred BGP_ROUTE type",
830 pfx_buf
, new_buf
, exist_buf
);
834 /* 4. AS path length check. */
835 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
836 int exist_hops
= aspath_count_hops(existattr
->aspath
);
837 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
839 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
842 aspath_hops
= aspath_count_hops(newattr
->aspath
);
843 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
845 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
846 *reason
= bgp_path_selection_confed_as_path
;
849 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
850 pfx_buf
, new_buf
, exist_buf
,
852 (exist_hops
+ exist_confeds
));
856 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
857 *reason
= bgp_path_selection_confed_as_path
;
860 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
861 pfx_buf
, new_buf
, exist_buf
,
863 (exist_hops
+ exist_confeds
));
867 int newhops
= aspath_count_hops(newattr
->aspath
);
869 if (newhops
< exist_hops
) {
870 *reason
= bgp_path_selection_as_path
;
873 "%s: %s wins over %s due to aspath hopcount %d < %d",
874 pfx_buf
, new_buf
, exist_buf
,
875 newhops
, exist_hops
);
879 if (newhops
> exist_hops
) {
880 *reason
= bgp_path_selection_as_path
;
883 "%s: %s loses to %s due to aspath hopcount %d > %d",
884 pfx_buf
, new_buf
, exist_buf
,
885 newhops
, exist_hops
);
891 /* 5. Origin check. */
892 if (newattr
->origin
< existattr
->origin
) {
893 *reason
= bgp_path_selection_origin
;
895 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
896 pfx_buf
, new_buf
, exist_buf
,
897 bgp_origin_long_str
[newattr
->origin
],
898 bgp_origin_long_str
[existattr
->origin
]);
902 if (newattr
->origin
> existattr
->origin
) {
903 *reason
= bgp_path_selection_origin
;
905 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
906 pfx_buf
, new_buf
, exist_buf
,
907 bgp_origin_long_str
[newattr
->origin
],
908 bgp_origin_long_str
[existattr
->origin
]);
913 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
914 && aspath_count_hops(existattr
->aspath
) == 0);
915 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
916 && aspath_count_confeds(existattr
->aspath
) > 0
917 && aspath_count_hops(newattr
->aspath
) == 0
918 && aspath_count_hops(existattr
->aspath
) == 0);
920 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
921 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
922 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
923 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
924 || internal_as_route
) {
925 new_med
= bgp_med_value(new->attr
, bgp
);
926 exist_med
= bgp_med_value(exist
->attr
, bgp
);
928 if (new_med
< exist_med
) {
929 *reason
= bgp_path_selection_med
;
932 "%s: %s wins over %s due to MED %d < %d",
933 pfx_buf
, new_buf
, exist_buf
, new_med
,
938 if (new_med
> exist_med
) {
939 *reason
= bgp_path_selection_med
;
942 "%s: %s loses to %s due to MED %d > %d",
943 pfx_buf
, new_buf
, exist_buf
, new_med
,
949 /* 7. Peer type check. */
950 new_sort
= new->peer
->sort
;
951 exist_sort
= exist
->peer
->sort
;
953 if (new_sort
== BGP_PEER_EBGP
954 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
955 *reason
= bgp_path_selection_peer
;
958 "%s: %s wins over %s due to eBGP peer > iBGP peer",
959 pfx_buf
, new_buf
, exist_buf
);
963 if (exist_sort
== BGP_PEER_EBGP
964 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
965 *reason
= bgp_path_selection_peer
;
968 "%s: %s loses to %s due to iBGP peer < eBGP peer",
969 pfx_buf
, new_buf
, exist_buf
);
973 /* 8. IGP metric check. */
977 newm
= new->extra
->igpmetric
;
979 existm
= exist
->extra
->igpmetric
;
984 "%s: %s wins over %s due to IGP metric %d < %d",
985 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
992 "%s: %s loses to %s due to IGP metric %d > %d",
993 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
997 /* 9. Same IGP metric. Compare the cluster list length as
998 representative of IGP hops metric. Rewrite the metric value
999 pair (newm, existm) with the cluster list length. Prefer the
1000 path with smaller cluster list length. */
1001 if (newm
== existm
) {
1002 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1003 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1004 && (mpath_cfg
== NULL
1006 mpath_cfg
->ibgp_flags
,
1007 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1008 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1009 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1011 if (newm
< existm
) {
1014 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1015 pfx_buf
, new_buf
, exist_buf
,
1020 if (newm
> existm
) {
1023 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1024 pfx_buf
, new_buf
, exist_buf
,
1031 /* 10. confed-external vs. confed-internal */
1032 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1033 if (new_sort
== BGP_PEER_CONFED
1034 && exist_sort
== BGP_PEER_IBGP
) {
1035 *reason
= bgp_path_selection_confed
;
1038 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1039 pfx_buf
, new_buf
, exist_buf
);
1043 if (exist_sort
== BGP_PEER_CONFED
1044 && new_sort
== BGP_PEER_IBGP
) {
1045 *reason
= bgp_path_selection_confed
;
1048 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1049 pfx_buf
, new_buf
, exist_buf
);
1054 /* 11. Maximum path check. */
1055 if (newm
== existm
) {
1056 /* If one path has a label but the other does not, do not treat
1057 * them as equals for multipath
1059 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1061 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1064 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1065 pfx_buf
, new_buf
, exist_buf
);
1066 } else if (CHECK_FLAG(bgp
->flags
,
1067 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1070 * For the two paths, all comparison steps till IGP
1072 * have succeeded - including AS_PATH hop count. Since
1074 * bestpath as-path multipath-relax' knob is on, we
1076 * an exact match of AS_PATH. Thus, mark the paths are
1078 * That will trigger both these paths to get into the
1086 "%s: %s and %s are equal via multipath-relax",
1087 pfx_buf
, new_buf
, exist_buf
);
1088 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1089 if (aspath_cmp(new->attr
->aspath
,
1090 exist
->attr
->aspath
)) {
1095 "%s: %s and %s are equal via matching aspaths",
1096 pfx_buf
, new_buf
, exist_buf
);
1098 } else if (new->peer
->as
== exist
->peer
->as
) {
1103 "%s: %s and %s are equal via same remote-as",
1104 pfx_buf
, new_buf
, exist_buf
);
1108 * TODO: If unequal cost ibgp multipath is enabled we can
1109 * mark the paths as equal here instead of returning
1114 "%s: %s wins over %s after IGP metric comparison",
1115 pfx_buf
, new_buf
, exist_buf
);
1118 "%s: %s loses to %s after IGP metric comparison",
1119 pfx_buf
, new_buf
, exist_buf
);
1121 *reason
= bgp_path_selection_igp_metric
;
1125 /* 12. If both paths are external, prefer the path that was received
1126 first (the oldest one). This step minimizes route-flap, since a
1127 newer path won't displace an older one, even if it was the
1128 preferred route based on the additional decision criteria below. */
1129 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1130 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1131 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1132 *reason
= bgp_path_selection_older
;
1135 "%s: %s wins over %s due to oldest external",
1136 pfx_buf
, new_buf
, exist_buf
);
1140 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1141 *reason
= bgp_path_selection_older
;
1144 "%s: %s loses to %s due to oldest external",
1145 pfx_buf
, new_buf
, exist_buf
);
1150 /* 13. Router-ID comparision. */
1151 /* If one of the paths is "stale", the corresponding peer router-id will
1152 * be 0 and would always win over the other path. If originator id is
1153 * used for the comparision, it will decide which path is better.
1155 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1156 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1158 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1159 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1160 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1162 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1164 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1165 *reason
= bgp_path_selection_router_id
;
1168 "%s: %s wins over %s due to Router-ID comparison",
1169 pfx_buf
, new_buf
, exist_buf
);
1173 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1174 *reason
= bgp_path_selection_router_id
;
1177 "%s: %s loses to %s due to Router-ID comparison",
1178 pfx_buf
, new_buf
, exist_buf
);
1182 /* 14. Cluster length comparision. */
1183 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1184 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1186 if (new_cluster
< exist_cluster
) {
1187 *reason
= bgp_path_selection_cluster_length
;
1190 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1191 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1196 if (new_cluster
> exist_cluster
) {
1197 *reason
= bgp_path_selection_cluster_length
;
1200 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1201 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1206 /* 15. Neighbor address comparision. */
1207 /* Do this only if neither path is "stale" as stale paths do not have
1208 * valid peer information (as the connection may or may not be up).
1210 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1211 *reason
= bgp_path_selection_stale
;
1214 "%s: %s wins over %s due to latter path being STALE",
1215 pfx_buf
, new_buf
, exist_buf
);
1219 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1220 *reason
= bgp_path_selection_stale
;
1223 "%s: %s loses to %s due to former path being STALE",
1224 pfx_buf
, new_buf
, exist_buf
);
1228 /* locally configured routes to advertise do not have su_remote */
1229 if (new->peer
->su_remote
== NULL
) {
1230 *reason
= bgp_path_selection_local_configured
;
1233 if (exist
->peer
->su_remote
== NULL
) {
1234 *reason
= bgp_path_selection_local_configured
;
1238 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1241 *reason
= bgp_path_selection_neighbor_ip
;
1244 "%s: %s loses to %s due to Neighor IP comparison",
1245 pfx_buf
, new_buf
, exist_buf
);
1250 *reason
= bgp_path_selection_neighbor_ip
;
1253 "%s: %s wins over %s due to Neighor IP comparison",
1254 pfx_buf
, new_buf
, exist_buf
);
1258 *reason
= bgp_path_selection_default
;
1260 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1261 pfx_buf
, new_buf
, exist_buf
);
1267 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1268 struct bgp_path_info
*exist
, int *paths_eq
)
1270 enum bgp_path_selection_reason reason
;
1271 char pfx_buf
[PREFIX2STR_BUFFER
];
1273 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1274 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1277 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1278 * is preferred, or 0 if they are the same (usually will only occur if
1279 * multipath is enabled
1280 * This version is compatible with */
1281 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1282 struct bgp_path_info
*exist
, char *pfx_buf
,
1283 afi_t afi
, safi_t safi
,
1284 enum bgp_path_selection_reason
*reason
)
1288 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1302 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1303 const struct prefix
*p
,
1304 struct attr
*attr
, afi_t afi
,
1307 struct bgp_filter
*filter
;
1308 enum filter_type ret
= FILTER_PERMIT
;
1310 filter
= &peer
->filter
[afi
][safi
];
1312 #define FILTER_EXIST_WARN(F, f, filter) \
1313 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1314 zlog_debug("%s: Could not find configured input %s-list %s!", \
1315 peer->host, #f, F##_IN_NAME(filter));
1317 if (DISTRIBUTE_IN_NAME(filter
)) {
1318 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1320 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1327 if (PREFIX_LIST_IN_NAME(filter
)) {
1328 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1330 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1337 if (FILTER_LIST_IN_NAME(filter
)) {
1338 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1340 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1341 == AS_FILTER_DENY
) {
1348 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1349 char pfxprint
[PREFIX2STR_BUFFER
];
1351 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1352 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1353 ret
== FILTER_PERMIT
? "permit" : "deny");
1357 #undef FILTER_EXIST_WARN
1360 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1361 const struct prefix
*p
,
1362 struct attr
*attr
, afi_t afi
,
1365 struct bgp_filter
*filter
;
1366 enum filter_type ret
= FILTER_PERMIT
;
1368 filter
= &peer
->filter
[afi
][safi
];
1370 #define FILTER_EXIST_WARN(F, f, filter) \
1371 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1372 zlog_debug("%s: Could not find configured output %s-list %s!", \
1373 peer->host, #f, F##_OUT_NAME(filter));
1375 if (DISTRIBUTE_OUT_NAME(filter
)) {
1376 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1378 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1385 if (PREFIX_LIST_OUT_NAME(filter
)) {
1386 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1388 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1395 if (FILTER_LIST_OUT_NAME(filter
)) {
1396 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1398 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1399 == AS_FILTER_DENY
) {
1405 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1406 char pfxprint
[PREFIX2STR_BUFFER
];
1408 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1409 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1410 ret
== FILTER_PERMIT
? "permit" : "deny");
1415 #undef FILTER_EXIST_WARN
1418 /* If community attribute includes no_export then return 1. */
1419 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1421 if (attr
->community
) {
1422 /* NO_ADVERTISE check. */
1423 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1426 /* NO_EXPORT check. */
1427 if (peer
->sort
== BGP_PEER_EBGP
1428 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1431 /* NO_EXPORT_SUBCONFED check. */
1432 if (peer
->sort
== BGP_PEER_EBGP
1433 || peer
->sort
== BGP_PEER_CONFED
)
1434 if (community_include(attr
->community
,
1435 COMMUNITY_NO_EXPORT_SUBCONFED
))
1441 /* Route reflection loop check. */
1442 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1444 struct in_addr cluster_id
;
1445 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1448 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1449 cluster_id
= peer
->bgp
->cluster_id
;
1451 cluster_id
= peer
->bgp
->router_id
;
1453 if (cluster_loop_check(cluster
, cluster_id
))
1459 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1460 struct attr
*attr
, afi_t afi
, safi_t safi
,
1461 const char *rmap_name
, mpls_label_t
*label
,
1462 uint32_t num_labels
, struct bgp_dest
*dest
)
1464 struct bgp_filter
*filter
;
1465 struct bgp_path_info rmap_path
= { 0 };
1466 struct bgp_path_info_extra extra
= { 0 };
1467 route_map_result_t ret
;
1468 struct route_map
*rmap
= NULL
;
1470 filter
= &peer
->filter
[afi
][safi
];
1472 /* Apply default weight value. */
1473 if (peer
->weight
[afi
][safi
])
1474 attr
->weight
= peer
->weight
[afi
][safi
];
1477 rmap
= route_map_lookup_by_name(rmap_name
);
1482 if (ROUTE_MAP_IN_NAME(filter
)) {
1483 rmap
= ROUTE_MAP_IN(filter
);
1490 /* Route map apply. */
1492 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1493 /* Duplicate current value to new strucutre for modification. */
1494 rmap_path
.peer
= peer
;
1495 rmap_path
.attr
= attr
;
1496 rmap_path
.extra
= &extra
;
1497 rmap_path
.net
= dest
;
1499 extra
.num_labels
= num_labels
;
1500 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1501 memcpy(extra
.label
, label
,
1502 num_labels
* sizeof(mpls_label_t
));
1504 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1506 /* Apply BGP route map to the attribute. */
1507 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1509 peer
->rmap_type
= 0;
1511 if (ret
== RMAP_DENYMATCH
)
1517 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1518 struct attr
*attr
, afi_t afi
, safi_t safi
,
1519 const char *rmap_name
)
1521 struct bgp_path_info rmap_path
;
1522 route_map_result_t ret
;
1523 struct route_map
*rmap
= NULL
;
1527 * So if we get to this point and have no rmap_name
1528 * we want to just show the output as it currently
1534 /* Apply default weight value. */
1535 if (peer
->weight
[afi
][safi
])
1536 attr
->weight
= peer
->weight
[afi
][safi
];
1538 rmap
= route_map_lookup_by_name(rmap_name
);
1541 * If we have a route map name and we do not find
1542 * the routemap that means we have an implicit
1548 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1549 /* Route map apply. */
1550 /* Duplicate current value to new strucutre for modification. */
1551 rmap_path
.peer
= peer
;
1552 rmap_path
.attr
= attr
;
1554 rmap_type
= peer
->rmap_type
;
1555 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1557 /* Apply BGP route map to the attribute. */
1558 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1560 peer
->rmap_type
= rmap_type
;
1562 if (ret
== RMAP_DENYMATCH
)
1564 * caller has multiple error paths with bgp_attr_flush()
1571 /* If this is an EBGP peer with remove-private-AS */
1572 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1573 struct peer
*peer
, struct attr
*attr
)
1575 if (peer
->sort
== BGP_PEER_EBGP
1576 && (peer_af_flag_check(peer
, afi
, safi
,
1577 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1578 || peer_af_flag_check(peer
, afi
, safi
,
1579 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1580 || peer_af_flag_check(peer
, afi
, safi
,
1581 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1582 || peer_af_flag_check(peer
, afi
, safi
,
1583 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1584 // Take action on the entire aspath
1585 if (peer_af_flag_check(peer
, afi
, safi
,
1586 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1587 || peer_af_flag_check(peer
, afi
, safi
,
1588 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1589 if (peer_af_flag_check(
1591 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1592 attr
->aspath
= aspath_replace_private_asns(
1593 attr
->aspath
, bgp
->as
, peer
->as
);
1595 // The entire aspath consists of private ASNs so create
1597 else if (aspath_private_as_check(attr
->aspath
))
1598 attr
->aspath
= aspath_empty_get();
1600 // There are some public and some private ASNs, remove
1603 attr
->aspath
= aspath_remove_private_asns(
1604 attr
->aspath
, peer
->as
);
1607 // 'all' was not specified so the entire aspath must be private
1609 // for us to do anything
1610 else if (aspath_private_as_check(attr
->aspath
)) {
1611 if (peer_af_flag_check(
1613 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1614 attr
->aspath
= aspath_replace_private_asns(
1615 attr
->aspath
, bgp
->as
, peer
->as
);
1617 attr
->aspath
= aspath_empty_get();
1622 /* If this is an EBGP peer with as-override */
1623 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1624 struct peer
*peer
, struct attr
*attr
)
1626 if (peer
->sort
== BGP_PEER_EBGP
1627 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1628 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1629 attr
->aspath
= aspath_replace_specific_asn(
1630 attr
->aspath
, peer
->as
, bgp
->as
);
1634 void bgp_attr_add_gshut_community(struct attr
*attr
)
1636 struct community
*old
;
1637 struct community
*new;
1638 struct community
*merge
;
1639 struct community
*gshut
;
1641 old
= attr
->community
;
1642 gshut
= community_str2com("graceful-shutdown");
1647 merge
= community_merge(community_dup(old
), gshut
);
1649 if (old
->refcnt
== 0)
1650 community_free(&old
);
1652 new = community_uniq_sort(merge
);
1653 community_free(&merge
);
1655 new = community_dup(gshut
);
1658 community_free(&gshut
);
1659 attr
->community
= new;
1660 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1662 /* When we add the graceful-shutdown community we must also
1663 * lower the local-preference */
1664 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1665 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1669 /* Notify BGP Conditional advertisement scanner process. */
1670 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1672 struct peer
*temp_peer
;
1673 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1674 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1675 afi_t afi
= SUBGRP_AFI(subgrp
);
1676 safi_t safi
= SUBGRP_SAFI(subgrp
);
1677 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1678 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1680 if (!ADVERTISE_MAP_NAME(filter
))
1683 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1684 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1687 if (peer
!= temp_peer
)
1690 temp_peer
->advmap_table_change
= true;
1696 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1698 if (family
== AF_INET
) {
1699 attr
->nexthop
.s_addr
= INADDR_ANY
;
1700 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1702 if (family
== AF_INET6
)
1703 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1704 if (family
== AF_EVPN
)
1705 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1708 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1709 struct update_subgroup
*subgrp
,
1710 const struct prefix
*p
, struct attr
*attr
,
1711 bool skip_rmap_check
)
1713 struct bgp_filter
*filter
;
1716 struct peer
*onlypeer
;
1718 struct attr
*piattr
;
1719 route_map_result_t ret
;
1724 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1725 bool nh_reset
= false;
1728 if (DISABLE_BGP_ANNOUNCE
)
1731 afi
= SUBGRP_AFI(subgrp
);
1732 safi
= SUBGRP_SAFI(subgrp
);
1733 peer
= SUBGRP_PEER(subgrp
);
1735 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1736 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1739 filter
= &peer
->filter
[afi
][safi
];
1740 bgp
= SUBGRP_INST(subgrp
);
1741 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1744 #ifdef ENABLE_BGP_VNC
1745 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1746 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1747 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1750 * direct and direct_ext type routes originate internally even
1751 * though they can have peer pointers that reference other
1754 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1760 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1761 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1762 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1763 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1765 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1770 /* With addpath we may be asked to TX all kinds of paths so make sure
1772 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1773 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1774 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1778 /* If this is not the bestpath then check to see if there is an enabled
1780 * feature that requires us to advertise it */
1781 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1782 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1787 /* Aggregate-address suppress check. */
1788 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1792 * If we are doing VRF 2 VRF leaking via the import
1793 * statement, we want to prevent the route going
1794 * off box as that the RT and RD created are localy
1795 * significant and globaly useless.
1797 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1798 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1801 /* If it's labeled safi, make sure the route has a valid label. */
1802 if (safi
== SAFI_LABELED_UNICAST
) {
1803 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1804 if (!bgp_is_valid_label(&label
)) {
1805 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1806 zlog_debug("u%" PRIu64
":s%" PRIu64
1807 " %pFX is filtered - no label (%p)",
1808 subgrp
->update_group
->id
, subgrp
->id
,
1814 /* Do not send back route to sender. */
1815 if (onlypeer
&& from
== onlypeer
) {
1819 /* Do not send the default route in the BGP table if the neighbor is
1820 * configured for default-originate */
1821 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1822 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1823 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1825 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1829 /* Transparency check. */
1830 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1831 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1836 /* If community is not disabled check the no-export and local. */
1837 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1838 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1839 zlog_debug("%s: community filter check fail for %pFX",
1844 /* If the attribute has originator-id and it is same as remote
1846 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1847 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1848 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1850 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1855 /* ORF prefix-list filter check */
1856 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1857 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1858 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1859 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1860 if (peer
->orf_plist
[afi
][safi
]) {
1861 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1863 if (bgp_debug_update(NULL
, p
,
1864 subgrp
->update_group
, 0))
1866 "%s [Update:SEND] %pFX is filtered via ORF",
1872 /* Output filter check. */
1873 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1874 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1875 zlog_debug("%s [Update:SEND] %pFX is filtered",
1880 /* AS path loop check. */
1881 if (onlypeer
&& onlypeer
->as_path_loop_detection
1882 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1883 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1885 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1886 onlypeer
->host
, onlypeer
->as
);
1890 /* If we're a CONFED we need to loop check the CONFED ID too */
1891 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1892 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1893 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1895 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1896 peer
->host
, bgp
->confed_id
);
1901 /* Route-Reflect check. */
1902 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1907 /* IBGP reflection check. */
1908 if (reflect
&& !samepeer_safe
) {
1909 /* A route from a Client peer. */
1910 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1911 PEER_FLAG_REFLECTOR_CLIENT
)) {
1912 /* Reflect to all the Non-Client peers and also to the
1913 Client peers other than the originator. Originator
1915 is already done. So there is noting to do. */
1916 /* no bgp client-to-client reflection check. */
1917 if (CHECK_FLAG(bgp
->flags
,
1918 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1919 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1920 PEER_FLAG_REFLECTOR_CLIENT
))
1923 /* A route from a Non-client peer. Reflect to all other
1925 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1926 PEER_FLAG_REFLECTOR_CLIENT
))
1931 /* For modify attribute, copy it to temporary structure. */
1934 /* If local-preference is not set. */
1935 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1936 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1937 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1938 attr
->local_pref
= bgp
->default_local_pref
;
1941 /* If originator-id is not set and the route is to be reflected,
1942 set the originator id */
1944 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1945 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1946 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1949 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1951 if (peer
->sort
== BGP_PEER_EBGP
1952 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1953 if (from
!= bgp
->peer_self
&& !transparent
1954 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1955 PEER_FLAG_MED_UNCHANGED
))
1957 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1960 /* Since the nexthop attribute can vary per peer, it is not explicitly
1962 * in announce check, only certain flags and length (or number of
1964 * -- for IPv6/MP_REACH) are set here in order to guide the update
1966 * code in setting the nexthop(s) on a per peer basis in
1968 * Typically, the source nexthop in the attribute is preserved but in
1970 * scenarios where we know it will always be overwritten, we reset the
1971 * nexthop to "0" in an attempt to achieve better Update packing. An
1972 * example of this is when a prefix from each of 2 IBGP peers needs to
1974 * announced to an EBGP peer (and they have the same attributes barring
1978 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1980 #define NEXTHOP_IS_V6 \
1981 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1982 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1983 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1984 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1986 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1988 * the peer (group) is configured to receive link-local nexthop
1990 * and it is available in the prefix OR we're not reflecting the route,
1991 * link-local nexthop address is valid and
1992 * the peer (group) to whom we're going to announce is on a shared
1994 * and this is either a self-originated route or the peer is EBGP.
1995 * By checking if nexthop LL address is valid we are sure that
1996 * we do not announce LL address as `::`.
1998 if (NEXTHOP_IS_V6
) {
1999 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2000 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2001 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2002 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2004 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2005 && peer
->shared_network
2006 && (from
== bgp
->peer_self
2007 || peer
->sort
== BGP_PEER_EBGP
))) {
2008 attr
->mp_nexthop_len
=
2009 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2012 /* Clear off link-local nexthop in source, whenever it is not
2014 * ensure more prefixes share the same attribute for
2017 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2018 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2019 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2022 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2023 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2025 /* Route map & unsuppress-map apply. */
2026 if (!skip_rmap_check
2027 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2028 struct bgp_path_info rmap_path
= {0};
2029 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2030 struct attr dummy_attr
= {0};
2032 /* Fill temp path_info */
2033 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2036 /* don't confuse inbound and outbound setting */
2037 RESET_FLAG(attr
->rmap_change_flags
);
2040 * The route reflector is not allowed to modify the attributes
2041 * of the reflected IBGP routes unless explicitly allowed.
2043 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2044 && !CHECK_FLAG(bgp
->flags
,
2045 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2047 rmap_path
.attr
= &dummy_attr
;
2050 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2052 if (bgp_path_suppressed(pi
))
2053 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2056 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2059 peer
->rmap_type
= 0;
2061 if (ret
== RMAP_DENYMATCH
) {
2062 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2064 "%s [Update:SEND] %pFX is filtered by route-map",
2067 bgp_attr_flush(attr
);
2072 /* RFC 8212 to prevent route leaks.
2073 * This specification intends to improve this situation by requiring the
2074 * explicit configuration of both BGP Import and Export Policies for any
2075 * External BGP (EBGP) session such as customers, peers, or
2076 * confederation boundaries for all enabled address families. Through
2077 * codification of the aforementioned requirement, operators will
2078 * benefit from consistent behavior across different BGP
2081 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2082 if (!bgp_outbound_policy_exists(peer
, filter
))
2085 /* draft-ietf-idr-deprecate-as-set-confed-set
2086 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2087 * Eventually, This document (if approved) updates RFC 4271
2088 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2089 * and obsoletes RFC 6472.
2091 if (peer
->bgp
->reject_as_sets
)
2092 if (aspath_check_as_sets(attr
->aspath
))
2095 /* Codification of AS 0 Processing */
2096 if (aspath_check_as_zero(attr
->aspath
))
2099 if (bgp_in_graceful_shutdown(bgp
)) {
2100 if (peer
->sort
== BGP_PEER_IBGP
2101 || peer
->sort
== BGP_PEER_CONFED
) {
2102 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2103 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2105 bgp_attr_add_gshut_community(attr
);
2109 /* After route-map has been applied, we check to see if the nexthop to
2110 * be carried in the attribute (that is used for the announcement) can
2111 * be cleared off or not. We do this in all cases where we would be
2112 * setting the nexthop to "ourselves". For IPv6, we only need to
2114 * the global nexthop here; the link-local nexthop would have been
2116 * already, and if not, it is required by the update formation code.
2117 * Also see earlier comments in this function.
2120 * If route-map has performed some operation on the nexthop or the peer
2121 * configuration says to pass it unchanged, we cannot reset the nexthop
2122 * here, so only attempt to do it if these aren't true. Note that the
2123 * route-map handler itself might have cleared the nexthop, if for
2125 * it is configured as 'peer-address'.
2127 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2128 piattr
->rmap_change_flags
)
2130 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2131 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2132 /* We can reset the nexthop, if setting (or forcing) it to
2134 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2135 PEER_FLAG_NEXTHOP_SELF
)
2136 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2137 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2139 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2140 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2141 subgroup_announce_reset_nhop(
2142 (peer_cap_enhe(peer
, afi
, safi
)
2148 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2149 /* Can also reset the nexthop if announcing to EBGP, but
2151 * no peer in the subgroup is on a shared subnet.
2152 * Note: 3rd party nexthop currently implemented for
2155 if ((p
->family
== AF_INET
) &&
2156 (!bgp_subgrp_multiaccess_check_v4(
2159 subgroup_announce_reset_nhop(
2160 (peer_cap_enhe(peer
, afi
, safi
)
2167 if ((p
->family
== AF_INET6
) &&
2168 (!bgp_subgrp_multiaccess_check_v6(
2169 piattr
->mp_nexthop_global
,
2171 subgroup_announce_reset_nhop(
2172 (peer_cap_enhe(peer
, afi
, safi
)
2181 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2183 * This flag is used for leaked vpn-vrf routes
2185 int family
= p
->family
;
2187 if (peer_cap_enhe(peer
, afi
, safi
))
2190 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2192 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2193 __func__
, family2str(family
));
2194 subgroup_announce_reset_nhop(family
, attr
);
2199 /* If IPv6/MP and nexthop does not have any override and happens
2201 * be a link-local address, reset it so that we don't pass along
2203 * source's link-local IPv6 address to recipients who may not be
2205 * the same interface.
2207 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2208 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2209 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2215 * When the next hop is set to ourselves, if all multipaths have
2216 * link-bandwidth announce the cumulative bandwidth as that makes
2217 * the most sense. However, don't modify if the link-bandwidth has
2218 * been explicitly set by user policy.
2221 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2222 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2223 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2224 attr
->ecommunity
= ecommunity_replace_linkbw(
2225 bgp
->as
, attr
->ecommunity
, cum_bw
);
2230 static int bgp_route_select_timer_expire(struct thread
*thread
)
2232 struct afi_safi_info
*info
;
2237 info
= THREAD_ARG(thread
);
2242 if (BGP_DEBUG(update
, UPDATE_OUT
))
2243 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2246 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2248 XFREE(MTYPE_TMP
, info
);
2250 /* Best path selection */
2251 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2254 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2255 struct bgp_maxpaths_cfg
*mpath_cfg
,
2256 struct bgp_path_info_pair
*result
, afi_t afi
,
2259 struct bgp_path_info
*new_select
;
2260 struct bgp_path_info
*old_select
;
2261 struct bgp_path_info
*pi
;
2262 struct bgp_path_info
*pi1
;
2263 struct bgp_path_info
*pi2
;
2264 struct bgp_path_info
*nextpi
= NULL
;
2265 int paths_eq
, do_mpath
, debug
;
2266 struct list mp_list
;
2267 char pfx_buf
[PREFIX2STR_BUFFER
];
2268 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2270 bgp_mp_list_init(&mp_list
);
2272 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2274 debug
= bgp_debug_bestpath(dest
);
2277 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2279 dest
->reason
= bgp_path_selection_none
;
2280 /* bgp deterministic-med */
2282 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2284 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2285 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2287 bgp_path_info_unset_flag(dest
, pi1
,
2288 BGP_PATH_DMED_SELECTED
);
2290 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2292 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2294 if (BGP_PATH_HOLDDOWN(pi1
))
2296 if (pi1
->peer
!= bgp
->peer_self
)
2297 if (pi1
->peer
->status
!= Established
)
2302 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2303 if (CHECK_FLAG(pi2
->flags
,
2304 BGP_PATH_DMED_CHECK
))
2306 if (BGP_PATH_HOLDDOWN(pi2
))
2308 if (pi2
->peer
!= bgp
->peer_self
2311 PEER_STATUS_NSF_WAIT
))
2312 if (pi2
->peer
->status
2316 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2318 && !aspath_cmp_left_confed(
2323 if (bgp_path_info_cmp(
2324 bgp
, pi2
, new_select
,
2325 &paths_eq
, mpath_cfg
, debug
,
2328 bgp_path_info_unset_flag(
2330 BGP_PATH_DMED_SELECTED
);
2334 bgp_path_info_set_flag(
2335 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2338 bgp_path_info_set_flag(dest
, new_select
,
2339 BGP_PATH_DMED_CHECK
);
2340 bgp_path_info_set_flag(dest
, new_select
,
2341 BGP_PATH_DMED_SELECTED
);
2344 bgp_path_info_path_with_addpath_rx_str(
2345 new_select
, path_buf
);
2347 "%pBD: %s is the bestpath from AS %u",
2349 aspath_get_first_as(
2350 new_select
->attr
->aspath
));
2355 /* Check old selected route and new selected route. */
2358 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2359 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2360 enum bgp_path_selection_reason reason
;
2362 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2365 if (BGP_PATH_HOLDDOWN(pi
)) {
2366 /* reap REMOVED routes, if needs be
2367 * selected route must stay for a while longer though
2369 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2370 && (pi
!= old_select
))
2371 bgp_path_info_reap(dest
, pi
);
2374 zlog_debug("%s: pi %p in holddown", __func__
,
2380 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2381 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2382 if (pi
->peer
->status
!= Established
) {
2386 "%s: pi %p non self peer %s not estab state",
2387 __func__
, pi
, pi
->peer
->host
);
2392 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2393 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2394 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2396 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2400 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2402 reason
= dest
->reason
;
2403 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2404 debug
, pfx_buf
, afi
, safi
,
2406 if (new_select
== NULL
&&
2407 reason
!= bgp_path_selection_none
)
2408 dest
->reason
= reason
;
2413 /* Now that we know which path is the bestpath see if any of the other
2415 * qualify as multipaths
2419 bgp_path_info_path_with_addpath_rx_str(new_select
,
2422 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2424 "%pBD: After path selection, newbest is %s oldbest was %s",
2426 old_select
? old_select
->peer
->host
: "NONE");
2429 if (do_mpath
&& new_select
) {
2430 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2431 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2434 bgp_path_info_path_with_addpath_rx_str(
2437 if (pi
== new_select
) {
2440 "%pBD: %s is the bestpath, add to the multipath list",
2442 bgp_mp_list_add(&mp_list
, pi
);
2446 if (BGP_PATH_HOLDDOWN(pi
))
2449 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2450 && !CHECK_FLAG(pi
->peer
->sflags
,
2451 PEER_STATUS_NSF_WAIT
))
2452 if (pi
->peer
->status
!= Established
)
2455 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2458 "%pBD: %s has the same nexthop as the bestpath, skip it",
2463 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2464 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2470 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2472 bgp_mp_list_add(&mp_list
, pi
);
2477 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2479 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2480 bgp_mp_list_clear(&mp_list
);
2482 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2484 result
->old
= old_select
;
2485 result
->new = new_select
;
2491 * A new route/change in bestpath of an existing route. Evaluate the path
2492 * for advertisement to the subgroup.
2494 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2495 struct bgp_path_info
*selected
,
2496 struct bgp_dest
*dest
,
2497 uint32_t addpath_tx_id
)
2499 const struct prefix
*p
;
2500 struct peer
*onlypeer
;
2507 p
= bgp_dest_get_prefix(dest
);
2508 afi
= SUBGRP_AFI(subgrp
);
2509 safi
= SUBGRP_SAFI(subgrp
);
2510 bgp
= SUBGRP_INST(subgrp
);
2511 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2514 if (BGP_DEBUG(update
, UPDATE_OUT
))
2515 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2517 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2518 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2519 PEER_STATUS_ORF_WAIT_REFRESH
))
2522 memset(&attr
, 0, sizeof(struct attr
));
2523 /* It's initialized in bgp_announce_check() */
2525 /* Announcement to the subgroup. If the route is filtered withdraw it.
2526 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2527 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2530 advertise
= bgp_check_advertise(bgp
, dest
);
2533 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2535 /* Route is selected, if the route is already installed
2536 * in FIB, then it is advertised
2539 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2542 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2546 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2548 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2553 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2554 * This is called at the end of route processing.
2556 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2558 struct bgp_path_info
*pi
;
2560 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2561 if (BGP_PATH_HOLDDOWN(pi
))
2563 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2564 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2569 * Has the route changed from the RIB's perspective? This is invoked only
2570 * if the route selection returns the same best route as earlier - to
2571 * determine if we need to update zebra or not.
2573 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2575 struct bgp_path_info
*mpinfo
;
2577 /* If this is multipath, check all selected paths for any nexthop
2578 * change or attribute change. Some attribute changes (e.g., community)
2579 * aren't of relevance to the RIB, but we'll update zebra to ensure
2580 * we handle the case of BGP nexthop change. This is the behavior
2581 * when the best path has an attribute change anyway.
2583 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2584 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2585 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2589 * If this is multipath, check all selected paths for any nexthop change
2591 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2592 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2593 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2594 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2598 /* Nothing has changed from the RIB's perspective. */
2602 struct bgp_process_queue
{
2604 STAILQ_HEAD(, bgp_dest
) pqueue
;
2605 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2607 unsigned int queued
;
2610 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2611 safi_t safi
, struct bgp_dest
*dest
,
2612 struct bgp_path_info
*new_select
,
2613 struct bgp_path_info
*old_select
)
2615 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2617 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2620 if (advertise_type5_routes(bgp
, afi
) && new_select
2621 && is_route_injectable_into_evpn(new_select
)) {
2623 /* apply the route-map */
2624 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2625 route_map_result_t ret
;
2626 struct bgp_path_info rmap_path
;
2627 struct bgp_path_info_extra rmap_path_extra
;
2628 struct attr dummy_attr
;
2630 dummy_attr
= *new_select
->attr
;
2632 /* Fill temp path_info */
2633 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2634 new_select
, new_select
->peer
,
2637 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2639 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2642 if (ret
== RMAP_DENYMATCH
) {
2643 bgp_attr_flush(&dummy_attr
);
2644 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2647 bgp_evpn_advertise_type5_route(
2648 bgp
, p
, &dummy_attr
, afi
, safi
);
2650 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2653 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2654 && is_route_injectable_into_evpn(old_select
))
2655 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2659 * old_select = The old best path
2660 * new_select = the new best path
2662 * if (!old_select && new_select)
2663 * We are sending new information on.
2665 * if (old_select && new_select) {
2666 * if (new_select != old_select)
2667 * We have a new best path send a change
2669 * We've received a update with new attributes that needs
2673 * if (old_select && !new_select)
2674 * We have no eligible route that we can announce or the rn
2677 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2678 afi_t afi
, safi_t safi
)
2680 struct bgp_path_info
*new_select
;
2681 struct bgp_path_info
*old_select
;
2682 struct bgp_path_info_pair old_and_new
;
2685 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2687 debug
= bgp_debug_bestpath(dest
);
2690 "%s: bgp delete in progress, ignoring event, p=%pBD",
2694 /* Is it end of initial update? (after startup) */
2696 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2697 sizeof(bgp
->update_delay_zebra_resume_time
));
2699 bgp
->main_zebra_update_hold
= 0;
2700 FOREACH_AFI_SAFI (afi
, safi
) {
2701 if (bgp_fibupd_safi(safi
))
2702 bgp_zebra_announce_table(bgp
, afi
, safi
);
2704 bgp
->main_peers_update_hold
= 0;
2706 bgp_start_routeadv(bgp
);
2710 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2712 debug
= bgp_debug_bestpath(dest
);
2714 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2715 afi2str(afi
), safi2str(safi
));
2717 /* The best path calculation for the route is deferred if
2718 * BGP_NODE_SELECT_DEFER is set
2720 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2721 if (BGP_DEBUG(update
, UPDATE_OUT
))
2722 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2726 /* Best path selection. */
2727 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2729 old_select
= old_and_new
.old
;
2730 new_select
= old_and_new
.new;
2732 /* Do we need to allocate or free labels?
2733 * Right now, since we only deal with per-prefix labels, it is not
2734 * necessary to do this upon changes to best path. Exceptions:
2735 * - label index has changed -> recalculate resulting label
2736 * - path_info sub_type changed -> switch to/from implicit-null
2737 * - no valid label (due to removed static label binding) -> get new one
2739 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2742 || bgp_label_index_differs(new_select
, old_select
)
2743 || new_select
->sub_type
!= old_select
->sub_type
2744 || !bgp_is_valid_label(&dest
->local_label
)) {
2745 /* Enforced penultimate hop popping:
2746 * implicit-null for local routes, aggregate
2747 * and redistributed routes
2749 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2750 || new_select
->sub_type
2751 == BGP_ROUTE_AGGREGATE
2752 || new_select
->sub_type
2753 == BGP_ROUTE_REDISTRIBUTE
) {
2756 BGP_NODE_REGISTERED_FOR_LABEL
)
2759 BGP_NODE_LABEL_REQUESTED
))
2760 bgp_unregister_for_label(dest
);
2761 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2762 &dest
->local_label
);
2763 bgp_set_valid_label(&dest
->local_label
);
2765 bgp_register_for_label(dest
,
2768 } else if (CHECK_FLAG(dest
->flags
,
2769 BGP_NODE_REGISTERED_FOR_LABEL
)
2770 || CHECK_FLAG(dest
->flags
,
2771 BGP_NODE_LABEL_REQUESTED
)) {
2772 bgp_unregister_for_label(dest
);
2774 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2775 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2776 bgp_unregister_for_label(dest
);
2781 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2782 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2783 old_select
, new_select
);
2785 /* If best route remains the same and this is not due to user-initiated
2786 * clear, see exactly what needs to be done.
2788 if (old_select
&& old_select
== new_select
2789 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2790 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2791 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2792 if (bgp_zebra_has_route_changed(old_select
)) {
2793 #ifdef ENABLE_BGP_VNC
2794 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2795 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2797 if (bgp_fibupd_safi(safi
)
2798 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2800 if (new_select
->type
== ZEBRA_ROUTE_BGP
2801 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2802 || new_select
->sub_type
2803 == BGP_ROUTE_IMPORTED
))
2805 bgp_zebra_announce(dest
, p
, old_select
,
2810 /* If there is a change of interest to peers, reannounce the
2812 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2813 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2814 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2815 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2817 /* unicast routes must also be annouced to
2818 * labeled-unicast update-groups */
2819 if (safi
== SAFI_UNICAST
)
2820 group_announce_route(bgp
, afi
,
2821 SAFI_LABELED_UNICAST
, dest
,
2824 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2825 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2828 /* advertise/withdraw type-5 routes */
2829 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2830 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2831 bgp_process_evpn_route_injection(
2832 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2834 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2835 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2836 bgp_zebra_clear_route_change_flags(dest
);
2837 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2841 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2843 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2845 /* bestpath has changed; bump version */
2846 if (old_select
|| new_select
) {
2847 bgp_bump_version(dest
);
2849 if (!bgp
->t_rmap_def_originate_eval
) {
2853 update_group_refresh_default_originate_route_map
,
2854 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2855 &bgp
->t_rmap_def_originate_eval
);
2860 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2863 zlog_debug("%s: setting SELECTED flag", __func__
);
2864 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2865 bgp_path_info_unset_flag(dest
, new_select
,
2866 BGP_PATH_ATTR_CHANGED
);
2867 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2868 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2871 #ifdef ENABLE_BGP_VNC
2872 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2873 if (old_select
!= new_select
) {
2875 vnc_import_bgp_exterior_del_route(bgp
, p
,
2877 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2880 vnc_import_bgp_exterior_add_route(bgp
, p
,
2882 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2888 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2890 /* unicast routes must also be annouced to labeled-unicast update-groups
2892 if (safi
== SAFI_UNICAST
)
2893 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2897 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2898 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2899 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2900 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2901 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2902 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2904 /* if this is an evpn imported type-5 prefix,
2905 * we need to withdraw the route first to clear
2906 * the nh neigh and the RMAC entry.
2909 is_route_parent_evpn(old_select
))
2910 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2912 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2914 /* Withdraw the route from the kernel. */
2915 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2916 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2917 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2918 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2920 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2924 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2927 /* Clear any route change flags. */
2928 bgp_zebra_clear_route_change_flags(dest
);
2930 /* Reap old select bgp_path_info, if it has been removed */
2931 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2932 bgp_path_info_reap(dest
, old_select
);
2934 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2938 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2939 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2941 struct bgp_dest
*dest
;
2943 struct afi_safi_info
*thread_info
;
2945 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
2946 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
2948 thread_info
= THREAD_ARG(t
);
2949 XFREE(MTYPE_TMP
, thread_info
);
2950 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2953 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2954 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2955 get_afi_safi_str(afi
, safi
, false),
2956 bgp
->gr_info
[afi
][safi
].gr_deferred
);
2959 /* Process the route list */
2960 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
2961 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
2962 dest
= bgp_route_next(dest
)) {
2963 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
2966 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2967 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
2968 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2970 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
2971 bgp_dest_unlock_node(dest
);
2976 /* Send EOR message when all routes are processed */
2977 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
2978 bgp_send_delayed_eor(bgp
);
2979 /* Send route processing complete message to RIB */
2980 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2981 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2985 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2987 thread_info
->afi
= afi
;
2988 thread_info
->safi
= safi
;
2989 thread_info
->bgp
= bgp
;
2991 /* If there are more routes to be processed, start the
2994 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2995 BGP_ROUTE_SELECT_DELAY
,
2996 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3000 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3002 struct bgp_process_queue
*pqnode
= data
;
3003 struct bgp
*bgp
= pqnode
->bgp
;
3004 struct bgp_table
*table
;
3005 struct bgp_dest
*dest
;
3008 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3009 bgp_process_main_one(bgp
, NULL
, 0, 0);
3010 /* should always have dedicated wq call */
3011 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3015 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3016 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3017 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3018 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3019 table
= bgp_dest_table(dest
);
3020 /* note, new DESTs may be added as part of processing */
3021 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3023 bgp_dest_unlock_node(dest
);
3024 bgp_table_unlock(table
);
3030 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3032 struct bgp_process_queue
*pqnode
= data
;
3034 bgp_unlock(pqnode
->bgp
);
3036 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3039 void bgp_process_queue_init(struct bgp
*bgp
)
3041 if (!bgp
->process_queue
) {
3044 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3045 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3048 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3049 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3050 bgp
->process_queue
->spec
.max_retries
= 0;
3051 bgp
->process_queue
->spec
.hold
= 50;
3052 /* Use a higher yield value of 50ms for main queue processing */
3053 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3056 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3058 struct bgp_process_queue
*pqnode
;
3060 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3061 sizeof(struct bgp_process_queue
));
3063 /* unlocked in bgp_processq_del */
3064 pqnode
->bgp
= bgp_lock(bgp
);
3065 STAILQ_INIT(&pqnode
->pqueue
);
3070 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3072 #define ARBITRARY_PROCESS_QLEN 10000
3073 struct work_queue
*wq
= bgp
->process_queue
;
3074 struct bgp_process_queue
*pqnode
;
3075 int pqnode_reuse
= 0;
3077 /* already scheduled for processing? */
3078 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3081 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3084 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3085 if (BGP_DEBUG(update
, UPDATE_OUT
))
3086 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3094 /* Add route nodes to an existing work queue item until reaching the
3095 limit only if is from the same BGP view and it's not an EOIU marker
3097 if (work_queue_item_count(wq
)) {
3098 struct work_queue_item
*item
= work_queue_last_item(wq
);
3099 pqnode
= item
->data
;
3101 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3102 || pqnode
->bgp
!= bgp
3103 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3104 pqnode
= bgp_processq_alloc(bgp
);
3108 pqnode
= bgp_processq_alloc(bgp
);
3109 /* all unlocked in bgp_process_wq */
3110 bgp_table_lock(bgp_dest_table(dest
));
3112 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3113 bgp_dest_lock_node(dest
);
3115 /* can't be enqueued twice */
3116 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3117 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3121 work_queue_add(wq
, pqnode
);
3126 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3128 struct bgp_process_queue
*pqnode
;
3130 if (bgp
->process_queue
== NULL
)
3133 pqnode
= bgp_processq_alloc(bgp
);
3135 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3136 work_queue_add(bgp
->process_queue
, pqnode
);
3139 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3143 peer
= THREAD_ARG(thread
);
3144 peer
->t_pmax_restart
= NULL
;
3146 if (bgp_debug_neighbor_events(peer
))
3148 "%s Maximum-prefix restart timer expired, restore peering",
3151 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3152 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3157 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3161 bool filtered
= false;
3162 struct bgp_dest
*dest
;
3163 struct bgp_adj_in
*ain
;
3164 struct attr attr
= {};
3165 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3167 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3168 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3169 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3173 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3177 if (bgp_input_modifier(
3178 peer
, rn_p
, &attr
, afi
, safi
,
3179 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3187 bgp_attr_undup(&attr
, ain
->attr
);
3194 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3198 iana_safi_t pkt_safi
;
3199 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3200 PEER_FLAG_MAX_PREFIX_FORCE
))
3201 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3202 + peer
->pcount
[afi
][safi
]
3203 : peer
->pcount
[afi
][safi
];
3205 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3208 if (pcount
> peer
->pmax
[afi
][safi
]) {
3209 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3210 PEER_STATUS_PREFIX_LIMIT
)
3215 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3216 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3217 peer
->pmax
[afi
][safi
]);
3218 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3220 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3221 PEER_FLAG_MAX_PREFIX_WARNING
))
3224 /* Convert AFI, SAFI to values for packet. */
3225 pkt_afi
= afi_int2iana(afi
);
3226 pkt_safi
= safi_int2iana(safi
);
3230 ndata
[0] = (pkt_afi
>> 8);
3232 ndata
[2] = pkt_safi
;
3233 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3234 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3235 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3236 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3238 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3239 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3240 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3244 /* Dynamic peers will just close their connection. */
3245 if (peer_dynamic_neighbor(peer
))
3248 /* restart timer start */
3249 if (peer
->pmax_restart
[afi
][safi
]) {
3250 peer
->v_pmax_restart
=
3251 peer
->pmax_restart
[afi
][safi
] * 60;
3253 if (bgp_debug_neighbor_events(peer
))
3255 "%s Maximum-prefix restart timer started for %d secs",
3256 peer
->host
, peer
->v_pmax_restart
);
3258 BGP_TIMER_ON(peer
->t_pmax_restart
,
3259 bgp_maximum_prefix_restart_timer
,
3260 peer
->v_pmax_restart
);
3265 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3266 PEER_STATUS_PREFIX_LIMIT
);
3269 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3270 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3271 PEER_STATUS_PREFIX_THRESHOLD
)
3276 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3277 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3278 peer
->pmax
[afi
][safi
]);
3279 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3280 PEER_STATUS_PREFIX_THRESHOLD
);
3282 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3283 PEER_STATUS_PREFIX_THRESHOLD
);
3287 /* Unconditionally remove the route from the RIB, without taking
3288 * damping into consideration (eg, because the session went down)
3290 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3291 struct peer
*peer
, afi_t afi
, safi_t safi
)
3294 struct bgp
*bgp
= NULL
;
3295 bool delete_route
= false;
3297 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3300 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3301 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3303 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3306 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3307 delete_route
= true;
3308 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3309 delete_route
= true;
3311 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3312 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3313 bgp
= pi
->peer
->bgp
;
3314 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3319 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3320 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3323 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3324 struct peer
*peer
, afi_t afi
, safi_t safi
,
3325 struct prefix_rd
*prd
)
3327 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3329 /* apply dampening, if result is suppressed, we'll be retaining
3330 * the bgp_path_info in the RIB for historical reference.
3332 if (peer
->sort
== BGP_PEER_EBGP
) {
3333 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3334 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3335 == BGP_DAMP_SUPPRESSED
) {
3336 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3343 #ifdef ENABLE_BGP_VNC
3344 if (safi
== SAFI_MPLS_VPN
) {
3345 struct bgp_dest
*pdest
= NULL
;
3346 struct bgp_table
*table
= NULL
;
3348 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3349 (struct prefix
*)prd
);
3350 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3351 table
= bgp_dest_get_bgp_table_info(pdest
);
3353 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3354 peer
->bgp
, prd
, table
, p
, pi
);
3356 bgp_dest_unlock_node(pdest
);
3358 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3359 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3361 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3362 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3367 /* If this is an EVPN route, process for un-import. */
3368 if (safi
== SAFI_EVPN
)
3369 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3371 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3374 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3375 struct peer
*peer
, struct attr
*attr
,
3376 struct bgp_dest
*dest
)
3378 struct bgp_path_info
*new;
3380 /* Make new BGP info. */
3381 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3383 new->instance
= instance
;
3384 new->sub_type
= sub_type
;
3387 new->uptime
= bgp_clock();
3392 static void overlay_index_update(struct attr
*attr
,
3393 union gw_addr
*gw_ip
)
3397 if (gw_ip
== NULL
) {
3398 struct bgp_route_evpn eo
;
3400 memset(&eo
, 0, sizeof(eo
));
3401 bgp_attr_set_evpn_overlay(attr
, &eo
);
3403 struct bgp_route_evpn eo
= {.gw_ip
= *gw_ip
};
3405 bgp_attr_set_evpn_overlay(attr
, &eo
);
3409 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3410 union gw_addr
*gw_ip
)
3412 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3413 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3419 if (afi
!= AFI_L2VPN
)
3422 path_gw_ip
= eo
->gw_ip
;
3424 if (gw_ip
== NULL
) {
3425 memset(&temp
, 0, sizeof(temp
));
3426 path_gw_ip_remote
= &temp
.ip
;
3428 path_gw_ip_remote
= gw_ip
;
3430 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3433 /* Check if received nexthop is valid or not. */
3434 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3435 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3436 struct bgp_dest
*dest
)
3439 bool is_bgp_static_route
=
3440 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3444 * Only validated for unicast and multicast currently.
3445 * Also valid for EVPN where the nexthop is an IP address.
3446 * If we are a bgp static route being checked then there is
3447 * no need to check to see if the nexthop is martian as
3448 * that it should be ok.
3450 if (is_bgp_static_route
||
3451 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3454 /* If NEXT_HOP is present, validate it. */
3455 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3456 if (attr
->nexthop
.s_addr
== INADDR_ANY
3457 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3458 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3462 /* If MP_NEXTHOP is present, validate it. */
3463 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3464 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3465 * it is not an IPv6 link-local address.
3467 * If we receive an UPDATE with nexthop length set to 32 bytes
3468 * we shouldn't discard an UPDATE if it's set to (::).
3469 * The link-local (2st) is validated along the code path later.
3471 if (attr
->mp_nexthop_len
) {
3472 switch (attr
->mp_nexthop_len
) {
3473 case BGP_ATTR_NHLEN_IPV4
:
3474 case BGP_ATTR_NHLEN_VPNV4
:
3475 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3477 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3478 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3482 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3483 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3484 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3485 &attr
->mp_nexthop_global
)
3486 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3487 || IN6_IS_ADDR_MULTICAST(
3488 &attr
->mp_nexthop_global
)
3489 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3492 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3493 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3494 || IN6_IS_ADDR_MULTICAST(
3495 &attr
->mp_nexthop_global
)
3496 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3509 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3511 struct community
*old
;
3512 struct community
*new;
3513 struct community
*merge
;
3514 struct community
*no_export
;
3516 old
= attr
->community
;
3517 no_export
= community_str2com("no-export");
3522 merge
= community_merge(community_dup(old
), no_export
);
3525 community_free(&old
);
3527 new = community_uniq_sort(merge
);
3528 community_free(&merge
);
3530 new = community_dup(no_export
);
3533 community_free(&no_export
);
3535 attr
->community
= new;
3536 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3539 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3540 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3541 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3542 uint32_t num_labels
, int soft_reconfig
,
3543 struct bgp_route_evpn
*evpn
)
3546 int aspath_loop_count
= 0;
3547 struct bgp_dest
*dest
;
3549 struct attr new_attr
;
3550 struct attr
*attr_new
;
3551 struct bgp_path_info
*pi
;
3552 struct bgp_path_info
*new;
3553 struct bgp_path_info_extra
*extra
;
3555 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3557 int do_loop_check
= 1;
3558 int has_valid_label
= 0;
3560 uint8_t pi_type
= 0;
3561 uint8_t pi_sub_type
= 0;
3563 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3564 char pfxprint
[PREFIX2STR_BUFFER
];
3566 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3567 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3571 #ifdef ENABLE_BGP_VNC
3572 int vnc_implicit_withdraw
= 0;
3576 memset(&new_attr
, 0, sizeof(struct attr
));
3577 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3578 new_attr
.label
= MPLS_INVALID_LABEL
;
3581 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3582 /* TODO: Check to see if we can get rid of "is_valid_label" */
3583 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3584 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3586 has_valid_label
= bgp_is_valid_label(label
);
3588 if (has_valid_label
)
3589 assert(label
!= NULL
);
3591 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3593 * Suppress fib is enabled
3594 * BGP_OPT_NO_FIB is not enabled
3595 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3596 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3598 if (BGP_SUPPRESS_FIB_ENABLED(bgp
) &&
3599 (sub_type
== BGP_ROUTE_NORMAL
) &&
3600 (!bgp_option_check(BGP_OPT_NO_FIB
)) &&
3601 (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3602 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3604 /* When peer's soft reconfiguration enabled. Record input packet in
3607 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3608 && peer
!= bgp
->peer_self
)
3609 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3611 /* Check previously received route. */
3612 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3613 if (pi
->peer
== peer
&& pi
->type
== type
3614 && pi
->sub_type
== sub_type
3615 && pi
->addpath_rx_id
== addpath_id
)
3618 /* AS path local-as loop check. */
3619 if (peer
->change_local_as
) {
3620 if (peer
->allowas_in
[afi
][safi
])
3621 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3622 else if (!CHECK_FLAG(peer
->flags
,
3623 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3624 aspath_loop_count
= 1;
3626 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3627 > aspath_loop_count
) {
3628 peer
->stat_pfx_aspath_loop
++;
3629 reason
= "as-path contains our own AS A;";
3634 /* If the peer is configured for "allowas-in origin" and the last ASN in
3636 * as-path is our ASN then we do not need to call aspath_loop_check
3638 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3639 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3642 /* AS path loop check. */
3643 if (do_loop_check
) {
3644 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3645 > peer
->allowas_in
[afi
][safi
]
3646 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3647 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3648 > peer
->allowas_in
[afi
][safi
])) {
3649 peer
->stat_pfx_aspath_loop
++;
3650 reason
= "as-path contains our own AS;";
3655 /* Route reflector originator ID check. */
3656 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3657 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3658 peer
->stat_pfx_originator_loop
++;
3659 reason
= "originator is us;";
3663 /* Route reflector cluster ID check. */
3664 if (bgp_cluster_filter(peer
, attr
)) {
3665 peer
->stat_pfx_cluster_loop
++;
3666 reason
= "reflected from the same cluster;";
3670 /* Apply incoming filter. */
3671 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3672 peer
->stat_pfx_filter
++;
3677 /* RFC 8212 to prevent route leaks.
3678 * This specification intends to improve this situation by requiring the
3679 * explicit configuration of both BGP Import and Export Policies for any
3680 * External BGP (EBGP) session such as customers, peers, or
3681 * confederation boundaries for all enabled address families. Through
3682 * codification of the aforementioned requirement, operators will
3683 * benefit from consistent behavior across different BGP
3686 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3687 if (!bgp_inbound_policy_exists(peer
,
3688 &peer
->filter
[afi
][safi
])) {
3689 reason
= "inbound policy missing";
3693 /* draft-ietf-idr-deprecate-as-set-confed-set
3694 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3695 * Eventually, This document (if approved) updates RFC 4271
3696 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3697 * and obsoletes RFC 6472.
3699 if (peer
->bgp
->reject_as_sets
)
3700 if (aspath_check_as_sets(attr
->aspath
)) {
3702 "as-path contains AS_SET or AS_CONFED_SET type;";
3708 /* Apply incoming route-map.
3709 * NB: new_attr may now contain newly allocated values from route-map
3711 * commands, so we need bgp_attr_flush in the error paths, until we
3713 * the attr (which takes over the memory references) */
3714 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3717 peer
->stat_pfx_filter
++;
3718 reason
= "route-map;";
3719 bgp_attr_flush(&new_attr
);
3723 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3724 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3725 /* remove from RIB previous entry */
3726 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3729 if (peer
->sort
== BGP_PEER_EBGP
) {
3732 * A BGP speaker receiving an announcement tagged with the
3733 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3734 * NO_EXPORT community as defined in RFC1997, or a
3735 * similar community, to prevent propagation of the
3736 * prefix outside the local AS. The community to prevent
3737 * propagation SHOULD be chosen according to the operator's
3740 if (new_attr
.community
3741 && community_include(new_attr
.community
,
3742 COMMUNITY_BLACKHOLE
))
3743 bgp_attr_add_no_export_community(&new_attr
);
3745 /* If we receive the graceful-shutdown community from an eBGP
3746 * peer we must lower local-preference */
3747 if (new_attr
.community
3748 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3749 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3750 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3752 /* If graceful-shutdown is configured then add the GSHUT
3753 * community to all paths received from eBGP peers */
3754 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3755 bgp_attr_add_gshut_community(&new_attr
);
3760 pi_sub_type
= pi
->sub_type
;
3763 /* next hop check. */
3764 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3765 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3767 peer
->stat_pfx_nh_invalid
++;
3768 reason
= "martian or self next-hop;";
3769 bgp_attr_flush(&new_attr
);
3773 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3774 peer
->stat_pfx_nh_invalid
++;
3775 reason
= "self mac;";
3779 /* Update Overlay Index */
3780 if (afi
== AFI_L2VPN
) {
3781 overlay_index_update(&new_attr
,
3782 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3785 attr_new
= bgp_attr_intern(&new_attr
);
3787 /* If maximum prefix count is configured and current prefix
3790 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3793 /* If the update is implicit withdraw. */
3795 pi
->uptime
= bgp_clock();
3796 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3798 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3800 /* Same attribute comes in. */
3801 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3803 && (!has_valid_label
3804 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3805 num_labels
* sizeof(mpls_label_t
))
3807 && (overlay_index_equal(
3809 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3810 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3811 && peer
->sort
== BGP_PEER_EBGP
3812 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3813 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3814 bgp_debug_rdpfxpath2str(
3815 afi
, safi
, prd
, p
, label
,
3816 num_labels
, addpath_id
? 1 : 0,
3817 addpath_id
, pfx_buf
,
3819 zlog_debug("%s rcvd %s", peer
->host
,
3823 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3824 != BGP_DAMP_SUPPRESSED
) {
3825 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3827 bgp_process(bgp
, dest
, afi
, safi
);
3829 } else /* Duplicate - odd */
3831 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3832 if (!peer
->rcvd_attr_printed
) {
3834 "%s rcvd UPDATE w/ attr: %s",
3836 peer
->rcvd_attr_str
);
3837 peer
->rcvd_attr_printed
= 1;
3840 bgp_debug_rdpfxpath2str(
3841 afi
, safi
, prd
, p
, label
,
3842 num_labels
, addpath_id
? 1 : 0,
3843 addpath_id
, pfx_buf
,
3846 "%s rcvd %s...duplicate ignored",
3847 peer
->host
, pfx_buf
);
3850 /* graceful restart STALE flag unset. */
3851 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3852 bgp_path_info_unset_flag(
3853 dest
, pi
, BGP_PATH_STALE
);
3854 bgp_dest_set_defer_flag(dest
, false);
3855 bgp_process(bgp
, dest
, afi
, safi
);
3859 bgp_dest_unlock_node(dest
);
3860 bgp_attr_unintern(&attr_new
);
3865 /* Withdraw/Announce before we fully processed the withdraw */
3866 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3867 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3868 bgp_debug_rdpfxpath2str(
3869 afi
, safi
, prd
, p
, label
, num_labels
,
3870 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3873 "%s rcvd %s, flapped quicker than processing",
3874 peer
->host
, pfx_buf
);
3877 bgp_path_info_restore(dest
, pi
);
3880 /* Received Logging. */
3881 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3882 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3883 num_labels
, addpath_id
? 1 : 0,
3884 addpath_id
, pfx_buf
,
3886 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3889 /* graceful restart STALE flag unset. */
3890 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3891 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3892 bgp_dest_set_defer_flag(dest
, false);
3895 /* The attribute is changed. */
3896 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3898 /* implicit withdraw, decrement aggregate and pcount here.
3899 * only if update is accepted, they'll increment below.
3901 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3903 /* Update bgp route dampening information. */
3904 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3905 && peer
->sort
== BGP_PEER_EBGP
) {
3906 /* This is implicit withdraw so we should update
3907 * dampening information.
3909 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3910 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3912 #ifdef ENABLE_BGP_VNC
3913 if (safi
== SAFI_MPLS_VPN
) {
3914 struct bgp_dest
*pdest
= NULL
;
3915 struct bgp_table
*table
= NULL
;
3917 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3918 (struct prefix
*)prd
);
3919 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3920 table
= bgp_dest_get_bgp_table_info(pdest
);
3922 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3923 bgp
, prd
, table
, p
, pi
);
3925 bgp_dest_unlock_node(pdest
);
3927 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3928 && (safi
== SAFI_UNICAST
)) {
3929 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3931 * Implicit withdraw case.
3933 ++vnc_implicit_withdraw
;
3934 vnc_import_bgp_del_route(bgp
, p
, pi
);
3935 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3940 /* Special handling for EVPN update of an existing route. If the
3941 * extended community attribute has changed, we need to
3943 * the route using its existing extended community. It will be
3944 * subsequently processed for import with the new extended
3947 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3950 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3952 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3955 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3956 attr_new
->ecommunity
);
3958 if (bgp_debug_update(peer
, p
, NULL
, 1))
3960 "Change in EXT-COMM, existing %s new %s",
3962 pi
->attr
->ecommunity
),
3964 attr_new
->ecommunity
));
3965 if (safi
== SAFI_EVPN
)
3966 bgp_evpn_unimport_route(
3967 bgp
, afi
, safi
, p
, pi
);
3968 else /* SAFI_MPLS_VPN */
3969 vpn_leak_to_vrf_withdraw(bgp
,
3975 /* Update to new attribute. */
3976 bgp_attr_unintern(&pi
->attr
);
3977 pi
->attr
= attr_new
;
3979 /* Update MPLS label */
3980 if (has_valid_label
) {
3981 extra
= bgp_path_info_extra_get(pi
);
3982 if (extra
->label
!= label
) {
3983 memcpy(&extra
->label
, label
,
3984 num_labels
* sizeof(mpls_label_t
));
3985 extra
->num_labels
= num_labels
;
3987 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3988 bgp_set_valid_label(&extra
->label
[0]);
3991 /* Update SRv6 SID */
3992 if (attr
->srv6_l3vpn
) {
3993 extra
= bgp_path_info_extra_get(pi
);
3994 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3995 sid_copy(&extra
->sid
[0],
3996 &attr
->srv6_l3vpn
->sid
);
3997 extra
->num_sids
= 1;
3999 } else if (attr
->srv6_vpn
) {
4000 extra
= bgp_path_info_extra_get(pi
);
4001 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4002 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4003 extra
->num_sids
= 1;
4007 #ifdef ENABLE_BGP_VNC
4008 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4009 && (safi
== SAFI_UNICAST
)) {
4010 if (vnc_implicit_withdraw
) {
4012 * Add back the route with its new attributes
4014 * The route is still selected, until the route
4016 * queued by bgp_process actually runs. We have
4018 * update to the VNC side immediately to avoid
4020 * configuration changes (e.g., route-map
4022 * trigger re-importation of the entire RIB.
4024 vnc_import_bgp_add_route(bgp
, p
, pi
);
4025 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4030 /* Update bgp route dampening information. */
4031 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4032 && peer
->sort
== BGP_PEER_EBGP
) {
4033 /* Now we do normal update dampening. */
4034 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4035 if (ret
== BGP_DAMP_SUPPRESSED
) {
4036 bgp_dest_unlock_node(dest
);
4041 /* Nexthop reachability check - for unicast and
4042 * labeled-unicast.. */
4043 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4044 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4045 || (safi
== SAFI_EVPN
&&
4046 bgp_evpn_is_prefix_nht_supported(p
))) {
4047 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4048 && peer
->ttl
== BGP_DEFAULT_TTL
4049 && !CHECK_FLAG(peer
->flags
,
4050 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4051 && !CHECK_FLAG(bgp
->flags
,
4052 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4057 struct bgp
*bgp_nexthop
= bgp
;
4059 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4060 bgp_nexthop
= pi
->extra
->bgp_orig
;
4062 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4064 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4065 safi
, pi
, NULL
, connected
)
4066 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4067 bgp_path_info_set_flag(dest
, pi
,
4070 if (BGP_DEBUG(nht
, NHT
)) {
4071 zlog_debug("%s(%pI4): NH unresolved",
4073 (in_addr_t
*)&attr_new
->nexthop
);
4075 bgp_path_info_unset_flag(dest
, pi
,
4079 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4081 #ifdef ENABLE_BGP_VNC
4082 if (safi
== SAFI_MPLS_VPN
) {
4083 struct bgp_dest
*pdest
= NULL
;
4084 struct bgp_table
*table
= NULL
;
4086 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4087 (struct prefix
*)prd
);
4088 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4089 table
= bgp_dest_get_bgp_table_info(pdest
);
4091 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4092 bgp
, prd
, table
, p
, pi
);
4094 bgp_dest_unlock_node(pdest
);
4098 /* If this is an EVPN route and some attribute has changed,
4100 * route for import. If the extended community has changed, we
4102 * have done the un-import earlier and the import would result
4104 * route getting injected into appropriate L2 VNIs. If it is
4106 * some other attribute change, the import will result in
4108 * the attributes for the route in the VNI(s).
4110 if (safi
== SAFI_EVPN
&& !same_attr
&&
4111 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4112 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4114 /* Process change. */
4115 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4117 bgp_process(bgp
, dest
, afi
, safi
);
4118 bgp_dest_unlock_node(dest
);
4120 if (SAFI_UNICAST
== safi
4121 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4122 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4124 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4126 if ((SAFI_MPLS_VPN
== safi
)
4127 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4129 vpn_leak_to_vrf_update(bgp
, pi
);
4132 #ifdef ENABLE_BGP_VNC
4133 if (SAFI_MPLS_VPN
== safi
) {
4134 mpls_label_t label_decoded
= decode_label(label
);
4136 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4137 type
, sub_type
, &label_decoded
);
4139 if (SAFI_ENCAP
== safi
) {
4140 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4141 type
, sub_type
, NULL
);
4146 } // End of implicit withdraw
4148 /* Received Logging. */
4149 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4150 if (!peer
->rcvd_attr_printed
) {
4151 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4152 peer
->rcvd_attr_str
);
4153 peer
->rcvd_attr_printed
= 1;
4156 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4157 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4159 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4162 /* Make new BGP info. */
4163 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4165 /* Update MPLS label */
4166 if (has_valid_label
) {
4167 extra
= bgp_path_info_extra_get(new);
4168 if (extra
->label
!= label
) {
4169 memcpy(&extra
->label
, label
,
4170 num_labels
* sizeof(mpls_label_t
));
4171 extra
->num_labels
= num_labels
;
4173 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4174 bgp_set_valid_label(&extra
->label
[0]);
4177 /* Update SRv6 SID */
4178 if (safi
== SAFI_MPLS_VPN
) {
4179 extra
= bgp_path_info_extra_get(new);
4180 if (attr
->srv6_l3vpn
) {
4181 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4182 extra
->num_sids
= 1;
4183 } else if (attr
->srv6_vpn
) {
4184 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4185 extra
->num_sids
= 1;
4189 /* Update Overlay Index */
4190 if (afi
== AFI_L2VPN
) {
4191 overlay_index_update(new->attr
,
4192 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4194 /* Nexthop reachability check. */
4195 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4196 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4197 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4198 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4199 && peer
->ttl
== BGP_DEFAULT_TTL
4200 && !CHECK_FLAG(peer
->flags
,
4201 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4202 && !CHECK_FLAG(bgp
->flags
,
4203 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4208 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4210 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4212 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4213 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4215 if (BGP_DEBUG(nht
, NHT
)) {
4216 char buf1
[INET6_ADDRSTRLEN
];
4218 (const void *)&attr_new
->nexthop
,
4219 buf1
, INET6_ADDRSTRLEN
);
4220 zlog_debug("%s(%s): NH unresolved", __func__
,
4223 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4226 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4229 new->addpath_rx_id
= addpath_id
;
4231 /* Increment prefix */
4232 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4234 /* Register new BGP information. */
4235 bgp_path_info_add(dest
, new);
4237 /* route_node_get lock */
4238 bgp_dest_unlock_node(dest
);
4240 #ifdef ENABLE_BGP_VNC
4241 if (safi
== SAFI_MPLS_VPN
) {
4242 struct bgp_dest
*pdest
= NULL
;
4243 struct bgp_table
*table
= NULL
;
4245 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4246 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4247 table
= bgp_dest_get_bgp_table_info(pdest
);
4249 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4250 bgp
, prd
, table
, p
, new);
4252 bgp_dest_unlock_node(pdest
);
4256 /* If this is an EVPN route, process for import. */
4257 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4258 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4260 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4262 /* Process change. */
4263 bgp_process(bgp
, dest
, afi
, safi
);
4265 if (SAFI_UNICAST
== safi
4266 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4267 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4268 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4270 if ((SAFI_MPLS_VPN
== safi
)
4271 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4273 vpn_leak_to_vrf_update(bgp
, new);
4275 #ifdef ENABLE_BGP_VNC
4276 if (SAFI_MPLS_VPN
== safi
) {
4277 mpls_label_t label_decoded
= decode_label(label
);
4279 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4280 sub_type
, &label_decoded
);
4282 if (SAFI_ENCAP
== safi
) {
4283 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4290 /* This BGP update is filtered. Log the reason then update BGP
4293 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4295 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4296 if (!peer
->rcvd_attr_printed
) {
4297 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4298 peer
->rcvd_attr_str
);
4299 peer
->rcvd_attr_printed
= 1;
4302 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4303 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4305 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4306 peer
->host
, pfx_buf
, reason
);
4310 /* If this is an EVPN route, un-import it as it is now filtered.
4312 if (safi
== SAFI_EVPN
)
4313 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4315 if (SAFI_UNICAST
== safi
4316 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4317 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4319 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4321 if ((SAFI_MPLS_VPN
== safi
)
4322 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4324 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4327 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4330 bgp_dest_unlock_node(dest
);
4332 #ifdef ENABLE_BGP_VNC
4334 * Filtered update is treated as an implicit withdrawal (see
4336 * a few lines above)
4338 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4339 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4347 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4348 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4349 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4350 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4353 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4354 struct bgp_dest
*dest
;
4355 struct bgp_path_info
*pi
;
4357 #ifdef ENABLE_BGP_VNC
4358 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4359 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4367 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4369 /* If peer is soft reconfiguration enabled. Record input packet for
4370 * further calculation.
4372 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4373 * routes that are filtered. This tanks out Quagga RS pretty badly due
4375 * the iteration over all RS clients.
4376 * Since we need to remove the entry from adj_in anyway, do that first
4378 * if there was no entry, we don't need to do anything more.
4380 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4381 && peer
!= bgp
->peer_self
)
4382 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4383 peer
->stat_pfx_dup_withdraw
++;
4385 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4386 bgp_debug_rdpfxpath2str(
4387 afi
, safi
, prd
, p
, label
, num_labels
,
4388 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4391 "%s withdrawing route %s not in adj-in",
4392 peer
->host
, pfx_buf
);
4394 bgp_dest_unlock_node(dest
);
4398 /* Lookup withdrawn route. */
4399 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4400 if (pi
->peer
== peer
&& pi
->type
== type
4401 && pi
->sub_type
== sub_type
4402 && pi
->addpath_rx_id
== addpath_id
)
4406 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4407 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4408 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4410 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4414 /* Withdraw specified route from routing table. */
4415 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4416 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4417 if (SAFI_UNICAST
== safi
4418 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4419 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4420 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4422 if ((SAFI_MPLS_VPN
== safi
)
4423 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4425 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4427 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4428 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4429 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4431 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4434 /* Unlock bgp_node_get() lock. */
4435 bgp_dest_unlock_node(dest
);
4440 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4443 struct update_subgroup
*subgrp
;
4444 subgrp
= peer_subgroup(peer
, afi
, safi
);
4445 subgroup_default_originate(subgrp
, withdraw
);
4450 * bgp_stop_announce_route_timer
4452 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4454 if (!paf
->t_announce_route
)
4457 thread_cancel(&paf
->t_announce_route
);
4461 * bgp_announce_route_timer_expired
4463 * Callback that is invoked when the route announcement timer for a
4466 static int bgp_announce_route_timer_expired(struct thread
*t
)
4468 struct peer_af
*paf
;
4471 paf
= THREAD_ARG(t
);
4474 if (peer
->status
!= Established
)
4477 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4480 peer_af_announce_route(paf
, 1);
4482 /* Notify BGP conditional advertisement scanner percess */
4483 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4489 * bgp_announce_route
4491 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4493 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4495 struct peer_af
*paf
;
4496 struct update_subgroup
*subgrp
;
4498 paf
= peer_af_find(peer
, afi
, safi
);
4501 subgrp
= PAF_SUBGRP(paf
);
4504 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4505 * or a refresh has already been triggered.
4507 if (!subgrp
|| paf
->t_announce_route
)
4511 * Start a timer to stagger/delay the announce. This serves
4512 * two purposes - announcement can potentially be combined for
4513 * multiple peers and the announcement doesn't happen in the
4516 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4517 (subgrp
->peer_count
== 1)
4518 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4519 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4520 &paf
->t_announce_route
);
4524 * Announce routes from all AF tables to a peer.
4526 * This should ONLY be called when there is a need to refresh the
4527 * routes to the peer based on a policy change for this peer alone
4528 * or a route refresh request received from the peer.
4529 * The operation will result in splitting the peer from its existing
4530 * subgroups and putting it in new subgroups.
4532 void bgp_announce_route_all(struct peer
*peer
)
4537 FOREACH_AFI_SAFI (afi
, safi
)
4538 bgp_announce_route(peer
, afi
, safi
);
4541 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4542 struct bgp_table
*table
,
4543 struct prefix_rd
*prd
)
4546 struct bgp_dest
*dest
;
4547 struct bgp_adj_in
*ain
;
4550 table
= peer
->bgp
->rib
[afi
][safi
];
4552 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4553 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4554 if (ain
->peer
!= peer
)
4557 struct bgp_path_info
*pi
;
4558 uint32_t num_labels
= 0;
4559 mpls_label_t
*label_pnt
= NULL
;
4560 struct bgp_route_evpn evpn
;
4562 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4564 if (pi
->peer
== peer
)
4567 if (pi
&& pi
->extra
)
4568 num_labels
= pi
->extra
->num_labels
;
4570 label_pnt
= &pi
->extra
->label
[0];
4573 bgp_attr_get_evpn_overlay(pi
->attr
),
4576 memset(&evpn
, 0, sizeof(evpn
));
4578 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4579 ain
->addpath_rx_id
, ain
->attr
, afi
,
4580 safi
, ZEBRA_ROUTE_BGP
,
4581 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4582 num_labels
, 1, &evpn
);
4585 bgp_dest_unlock_node(dest
);
4591 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4593 struct bgp_dest
*dest
;
4594 struct bgp_table
*table
;
4596 if (peer
->status
!= Established
)
4599 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4600 && (safi
!= SAFI_EVPN
))
4601 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4603 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4604 dest
= bgp_route_next(dest
)) {
4605 table
= bgp_dest_get_bgp_table_info(dest
);
4610 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4611 struct prefix_rd prd
;
4613 prd
.family
= AF_UNSPEC
;
4615 memcpy(&prd
.val
, p
->u
.val
, 8);
4617 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4622 struct bgp_clear_node_queue
{
4623 struct bgp_dest
*dest
;
4626 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4628 struct bgp_clear_node_queue
*cnq
= data
;
4629 struct bgp_dest
*dest
= cnq
->dest
;
4630 struct peer
*peer
= wq
->spec
.data
;
4631 struct bgp_path_info
*pi
;
4633 afi_t afi
= bgp_dest_table(dest
)->afi
;
4634 safi_t safi
= bgp_dest_table(dest
)->safi
;
4636 assert(dest
&& peer
);
4639 /* It is possible that we have multiple paths for a prefix from a peer
4640 * if that peer is using AddPath.
4642 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4643 if (pi
->peer
!= peer
)
4646 /* graceful restart STALE flag set. */
4647 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4648 && peer
->nsf
[afi
][safi
])
4649 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4650 PEER_STATUS_ENHANCED_REFRESH
))
4651 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4652 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4653 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4655 /* If this is an EVPN route, process for
4657 if (safi
== SAFI_EVPN
)
4658 bgp_evpn_unimport_route(
4660 bgp_dest_get_prefix(dest
), pi
);
4661 /* Handle withdraw for VRF route-leaking and L3VPN */
4662 if (SAFI_UNICAST
== safi
4663 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4664 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4665 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4668 if (SAFI_MPLS_VPN
== safi
&&
4669 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4670 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4673 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4679 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4681 struct bgp_clear_node_queue
*cnq
= data
;
4682 struct bgp_dest
*dest
= cnq
->dest
;
4683 struct bgp_table
*table
= bgp_dest_table(dest
);
4685 bgp_dest_unlock_node(dest
);
4686 bgp_table_unlock(table
);
4687 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4690 static void bgp_clear_node_complete(struct work_queue
*wq
)
4692 struct peer
*peer
= wq
->spec
.data
;
4694 /* Tickle FSM to start moving again */
4695 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4697 peer_unlock(peer
); /* bgp_clear_route */
4700 static void bgp_clear_node_queue_init(struct peer
*peer
)
4702 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4704 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4705 #undef CLEAR_QUEUE_NAME_LEN
4707 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4708 peer
->clear_node_queue
->spec
.hold
= 10;
4709 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4710 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4711 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4712 peer
->clear_node_queue
->spec
.max_retries
= 0;
4714 /* we only 'lock' this peer reference when the queue is actually active
4716 peer
->clear_node_queue
->spec
.data
= peer
;
4719 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4720 struct bgp_table
*table
)
4722 struct bgp_dest
*dest
;
4723 int force
= peer
->bgp
->process_queue
? 0 : 1;
4726 table
= peer
->bgp
->rib
[afi
][safi
];
4728 /* If still no table => afi/safi isn't configured at all or smth. */
4732 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4733 struct bgp_path_info
*pi
, *next
;
4734 struct bgp_adj_in
*ain
;
4735 struct bgp_adj_in
*ain_next
;
4737 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4738 * queued for every clearing peer, regardless of whether it is
4739 * relevant to the peer at hand.
4741 * Overview: There are 3 different indices which need to be
4742 * scrubbed, potentially, when a peer is removed:
4744 * 1 peer's routes visible via the RIB (ie accepted routes)
4745 * 2 peer's routes visible by the (optional) peer's adj-in index
4746 * 3 other routes visible by the peer's adj-out index
4748 * 3 there is no hurry in scrubbing, once the struct peer is
4749 * removed from bgp->peer, we could just GC such deleted peer's
4750 * adj-outs at our leisure.
4752 * 1 and 2 must be 'scrubbed' in some way, at least made
4753 * invisible via RIB index before peer session is allowed to be
4754 * brought back up. So one needs to know when such a 'search' is
4759 * - there'd be a single global queue or a single RIB walker
4760 * - rather than tracking which route_nodes still need to be
4761 * examined on a peer basis, we'd track which peers still
4764 * Given that our per-peer prefix-counts now should be reliable,
4765 * this may actually be achievable. It doesn't seem to be a huge
4766 * problem at this time,
4768 * It is possible that we have multiple paths for a prefix from
4770 * if that peer is using AddPath.
4774 ain_next
= ain
->next
;
4776 if (ain
->peer
== peer
) {
4777 bgp_adj_in_remove(dest
, ain
);
4778 bgp_dest_unlock_node(dest
);
4784 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4786 if (pi
->peer
!= peer
)
4790 bgp_path_info_reap(dest
, pi
);
4792 struct bgp_clear_node_queue
*cnq
;
4794 /* both unlocked in bgp_clear_node_queue_del */
4795 bgp_table_lock(bgp_dest_table(dest
));
4796 bgp_dest_lock_node(dest
);
4798 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4799 sizeof(struct bgp_clear_node_queue
));
4801 work_queue_add(peer
->clear_node_queue
, cnq
);
4809 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4811 struct bgp_dest
*dest
;
4812 struct bgp_table
*table
;
4814 if (peer
->clear_node_queue
== NULL
)
4815 bgp_clear_node_queue_init(peer
);
4817 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4818 * Idle until it receives a Clearing_Completed event. This protects
4819 * against peers which flap faster than we can we clear, which could
4822 * a) race with routes from the new session being installed before
4823 * clear_route_node visits the node (to delete the route of that
4825 * b) resource exhaustion, clear_route_node likely leads to an entry
4826 * on the process_main queue. Fast-flapping could cause that queue
4830 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4831 * the unlock will happen upon work-queue completion; other wise, the
4832 * unlock happens at the end of this function.
4834 if (!peer
->clear_node_queue
->thread
)
4837 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4838 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4840 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4841 dest
= bgp_route_next(dest
)) {
4842 table
= bgp_dest_get_bgp_table_info(dest
);
4846 bgp_clear_route_table(peer
, afi
, safi
, table
);
4849 /* unlock if no nodes got added to the clear-node-queue. */
4850 if (!peer
->clear_node_queue
->thread
)
4854 void bgp_clear_route_all(struct peer
*peer
)
4859 FOREACH_AFI_SAFI (afi
, safi
)
4860 bgp_clear_route(peer
, afi
, safi
);
4862 #ifdef ENABLE_BGP_VNC
4863 rfapiProcessPeerDown(peer
);
4867 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4869 struct bgp_table
*table
;
4870 struct bgp_dest
*dest
;
4871 struct bgp_adj_in
*ain
;
4872 struct bgp_adj_in
*ain_next
;
4874 table
= peer
->bgp
->rib
[afi
][safi
];
4876 /* It is possible that we have multiple paths for a prefix from a peer
4877 * if that peer is using AddPath.
4879 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4883 ain_next
= ain
->next
;
4885 if (ain
->peer
== peer
) {
4886 bgp_adj_in_remove(dest
, ain
);
4887 bgp_dest_unlock_node(dest
);
4895 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4897 struct bgp_dest
*dest
;
4898 struct bgp_path_info
*pi
;
4899 struct bgp_table
*table
;
4901 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4902 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4903 dest
= bgp_route_next(dest
)) {
4904 struct bgp_dest
*rm
;
4906 /* look for neighbor in tables */
4907 table
= bgp_dest_get_bgp_table_info(dest
);
4911 for (rm
= bgp_table_top(table
); rm
;
4912 rm
= bgp_route_next(rm
))
4913 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4915 if (pi
->peer
!= peer
)
4917 if (!CHECK_FLAG(pi
->flags
,
4921 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4926 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4927 dest
= bgp_route_next(dest
))
4928 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4930 if (pi
->peer
!= peer
)
4932 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4934 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4940 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4942 struct bgp_dest
*dest
, *ndest
;
4943 struct bgp_path_info
*pi
;
4944 struct bgp_table
*table
;
4946 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4947 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4948 dest
= bgp_route_next(dest
)) {
4949 table
= bgp_dest_get_bgp_table_info(dest
);
4953 for (ndest
= bgp_table_top(table
); ndest
;
4954 ndest
= bgp_route_next(ndest
)) {
4955 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
4957 if (pi
->peer
!= peer
)
4961 peer
->af_sflags
[afi
][safi
],
4962 PEER_STATUS_ENHANCED_REFRESH
))
4963 && !CHECK_FLAG(pi
->flags
,
4967 BGP_PATH_UNUSEABLE
)) {
4968 if (bgp_debug_neighbor_events(
4971 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4975 bgp_dest_get_prefix(
4978 bgp_path_info_set_flag(
4986 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4987 dest
= bgp_route_next(dest
)) {
4988 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4990 if (pi
->peer
!= peer
)
4993 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4994 PEER_STATUS_ENHANCED_REFRESH
))
4995 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4996 && !CHECK_FLAG(pi
->flags
,
4997 BGP_PATH_UNUSEABLE
)) {
4998 if (bgp_debug_neighbor_events(peer
))
5000 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5004 bgp_dest_get_prefix(
5007 bgp_path_info_set_flag(dest
, pi
,
5015 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5017 if (peer
->sort
== BGP_PEER_IBGP
)
5020 if (peer
->sort
== BGP_PEER_EBGP
5021 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5022 || FILTER_LIST_OUT_NAME(filter
)
5023 || DISTRIBUTE_OUT_NAME(filter
)))
5028 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5030 if (peer
->sort
== BGP_PEER_IBGP
)
5033 if (peer
->sort
== BGP_PEER_EBGP
5034 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5035 || FILTER_LIST_IN_NAME(filter
)
5036 || DISTRIBUTE_IN_NAME(filter
)))
5041 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5044 struct bgp_dest
*dest
;
5045 struct bgp_path_info
*pi
;
5046 struct bgp_path_info
*next
;
5048 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5049 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5050 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5054 /* Unimport EVPN routes from VRFs */
5055 if (safi
== SAFI_EVPN
)
5056 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5059 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5060 && pi
->type
== ZEBRA_ROUTE_BGP
5061 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5062 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5063 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5065 if (bgp_fibupd_safi(safi
))
5066 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5069 bgp_path_info_reap(dest
, pi
);
5073 /* Delete all kernel routes. */
5074 void bgp_cleanup_routes(struct bgp
*bgp
)
5077 struct bgp_dest
*dest
;
5078 struct bgp_table
*table
;
5080 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5081 if (afi
== AFI_L2VPN
)
5083 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5086 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5088 if (afi
!= AFI_L2VPN
) {
5090 safi
= SAFI_MPLS_VPN
;
5091 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5092 dest
= bgp_route_next(dest
)) {
5093 table
= bgp_dest_get_bgp_table_info(dest
);
5094 if (table
!= NULL
) {
5095 bgp_cleanup_table(bgp
, table
, safi
);
5096 bgp_table_finish(&table
);
5097 bgp_dest_set_bgp_table_info(dest
, NULL
);
5098 bgp_dest_unlock_node(dest
);
5102 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5103 dest
= bgp_route_next(dest
)) {
5104 table
= bgp_dest_get_bgp_table_info(dest
);
5105 if (table
!= NULL
) {
5106 bgp_cleanup_table(bgp
, table
, safi
);
5107 bgp_table_finish(&table
);
5108 bgp_dest_set_bgp_table_info(dest
, NULL
);
5109 bgp_dest_unlock_node(dest
);
5114 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5115 dest
= bgp_route_next(dest
)) {
5116 table
= bgp_dest_get_bgp_table_info(dest
);
5117 if (table
!= NULL
) {
5118 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5119 bgp_table_finish(&table
);
5120 bgp_dest_set_bgp_table_info(dest
, NULL
);
5121 bgp_dest_unlock_node(dest
);
5126 void bgp_reset(void)
5129 bgp_zclient_reset();
5130 access_list_reset();
5131 prefix_list_reset();
5134 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5136 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5137 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5138 PEER_CAP_ADDPATH_AF_TX_RCV
));
5141 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5143 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5144 struct bgp_nlri
*packet
)
5153 int addpath_encoded
;
5154 uint32_t addpath_id
;
5157 lim
= pnt
+ packet
->length
;
5159 safi
= packet
->safi
;
5161 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5163 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5164 syntactic validity. If the field is syntactically incorrect,
5165 then the Error Subcode is set to Invalid Network Field. */
5166 for (; pnt
< lim
; pnt
+= psize
) {
5167 /* Clear prefix structure. */
5168 memset(&p
, 0, sizeof(struct prefix
));
5170 if (addpath_encoded
) {
5172 /* When packet overflow occurs return immediately. */
5173 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5174 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5176 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5177 addpath_id
= ntohl(addpath_id
);
5178 pnt
+= BGP_ADDPATH_ID_LEN
;
5181 /* Fetch prefix length. */
5182 p
.prefixlen
= *pnt
++;
5183 /* afi/safi validity already verified by caller,
5184 * bgp_update_receive */
5185 p
.family
= afi2family(afi
);
5187 /* Prefix length check. */
5188 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5191 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5192 peer
->host
, p
.prefixlen
, packet
->afi
);
5193 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5196 /* Packet size overflow check. */
5197 psize
= PSIZE(p
.prefixlen
);
5199 /* When packet overflow occur return immediately. */
5200 if (pnt
+ psize
> lim
) {
5203 "%s [Error] Update packet error (prefix length %d overflows packet)",
5204 peer
->host
, p
.prefixlen
);
5205 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5208 /* Defensive coding, double-check the psize fits in a struct
5210 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5213 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5214 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5215 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5218 /* Fetch prefix from NLRI packet. */
5219 memcpy(p
.u
.val
, pnt
, psize
);
5221 /* Check address. */
5222 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5223 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5224 /* From RFC4271 Section 6.3:
5226 * If a prefix in the NLRI field is semantically
5228 * (e.g., an unexpected multicast IP address),
5230 * be logged locally, and the prefix SHOULD be
5235 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5236 peer
->host
, &p
.u
.prefix4
);
5241 /* Check address. */
5242 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5243 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5248 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5250 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5255 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5260 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5262 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5269 /* Normal process. */
5271 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5272 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5273 NULL
, NULL
, 0, 0, NULL
);
5275 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5276 safi
, ZEBRA_ROUTE_BGP
,
5277 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5280 /* Do not send BGP notification twice when maximum-prefix count
5282 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5283 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5285 /* Address family configuration mismatch. */
5287 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5290 /* Packet length consistency check. */
5294 "%s [Error] Update packet error (prefix length mismatch with total length)",
5296 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5299 return BGP_NLRI_PARSE_OK
;
5302 static struct bgp_static
*bgp_static_new(void)
5304 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5307 static void bgp_static_free(struct bgp_static
*bgp_static
)
5309 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5310 route_map_counter_decrement(bgp_static
->rmap
.map
);
5312 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5313 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5316 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5317 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5319 struct bgp_dest
*dest
;
5320 struct bgp_path_info
*pi
;
5321 struct bgp_path_info
*new;
5322 struct bgp_path_info rmap_path
;
5324 struct attr
*attr_new
;
5325 route_map_result_t ret
;
5326 #ifdef ENABLE_BGP_VNC
5327 int vnc_implicit_withdraw
= 0;
5332 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5334 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5336 attr
.nexthop
= bgp_static
->igpnexthop
;
5337 attr
.med
= bgp_static
->igpmetric
;
5338 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5340 if (bgp_static
->atomic
)
5341 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5343 /* Store label index, if required. */
5344 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5345 attr
.label_index
= bgp_static
->label_index
;
5346 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5349 /* Apply route-map. */
5350 if (bgp_static
->rmap
.name
) {
5351 struct attr attr_tmp
= attr
;
5353 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5354 rmap_path
.peer
= bgp
->peer_self
;
5355 rmap_path
.attr
= &attr_tmp
;
5357 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5359 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5361 bgp
->peer_self
->rmap_type
= 0;
5363 if (ret
== RMAP_DENYMATCH
) {
5364 /* Free uninterned attribute. */
5365 bgp_attr_flush(&attr_tmp
);
5367 /* Unintern original. */
5368 aspath_unintern(&attr
.aspath
);
5369 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5373 if (bgp_in_graceful_shutdown(bgp
))
5374 bgp_attr_add_gshut_community(&attr_tmp
);
5376 attr_new
= bgp_attr_intern(&attr_tmp
);
5379 if (bgp_in_graceful_shutdown(bgp
))
5380 bgp_attr_add_gshut_community(&attr
);
5382 attr_new
= bgp_attr_intern(&attr
);
5385 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5386 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5387 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5391 if (attrhash_cmp(pi
->attr
, attr_new
)
5392 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5393 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5394 bgp_dest_unlock_node(dest
);
5395 bgp_attr_unintern(&attr_new
);
5396 aspath_unintern(&attr
.aspath
);
5399 /* The attribute is changed. */
5400 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5402 /* Rewrite BGP route information. */
5403 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5404 bgp_path_info_restore(dest
, pi
);
5406 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5407 #ifdef ENABLE_BGP_VNC
5408 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5409 && (safi
== SAFI_UNICAST
)) {
5410 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5412 * Implicit withdraw case.
5413 * We have to do this before pi is
5416 ++vnc_implicit_withdraw
;
5417 vnc_import_bgp_del_route(bgp
, p
, pi
);
5418 vnc_import_bgp_exterior_del_route(
5423 bgp_attr_unintern(&pi
->attr
);
5424 pi
->attr
= attr_new
;
5425 pi
->uptime
= bgp_clock();
5426 #ifdef ENABLE_BGP_VNC
5427 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5428 && (safi
== SAFI_UNICAST
)) {
5429 if (vnc_implicit_withdraw
) {
5430 vnc_import_bgp_add_route(bgp
, p
, pi
);
5431 vnc_import_bgp_exterior_add_route(
5437 /* Nexthop reachability check. */
5438 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5439 && (safi
== SAFI_UNICAST
5440 || safi
== SAFI_LABELED_UNICAST
)) {
5442 struct bgp
*bgp_nexthop
= bgp
;
5444 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5445 bgp_nexthop
= pi
->extra
->bgp_orig
;
5447 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5448 afi
, safi
, pi
, NULL
,
5450 bgp_path_info_set_flag(dest
, pi
,
5453 if (BGP_DEBUG(nht
, NHT
)) {
5454 char buf1
[INET6_ADDRSTRLEN
];
5455 inet_ntop(p
->family
,
5459 "%s(%s): Route not in table, not advertising",
5462 bgp_path_info_unset_flag(
5463 dest
, pi
, BGP_PATH_VALID
);
5466 /* Delete the NHT structure if any, if we're
5468 * enabling/disabling import check. We
5469 * deregister the route
5470 * from NHT to avoid overloading NHT and the
5471 * process interaction
5473 bgp_unlink_nexthop(pi
);
5474 bgp_path_info_set_flag(dest
, pi
,
5477 /* Process change. */
5478 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5479 bgp_process(bgp
, dest
, afi
, safi
);
5481 if (SAFI_UNICAST
== safi
5482 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5484 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5485 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5489 bgp_dest_unlock_node(dest
);
5490 aspath_unintern(&attr
.aspath
);
5495 /* Make new BGP info. */
5496 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5498 /* Nexthop reachability check. */
5499 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5500 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5501 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0))
5502 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5504 if (BGP_DEBUG(nht
, NHT
)) {
5505 char buf1
[INET6_ADDRSTRLEN
];
5506 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5509 "%s(%s): Route not in table, not advertising",
5512 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5515 /* Delete the NHT structure if any, if we're toggling between
5516 * enabling/disabling import check. We deregister the route
5517 * from NHT to avoid overloading NHT and the process interaction
5519 bgp_unlink_nexthop(new);
5521 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5524 /* Aggregate address increment. */
5525 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5527 /* Register new BGP information. */
5528 bgp_path_info_add(dest
, new);
5530 /* route_node_get lock */
5531 bgp_dest_unlock_node(dest
);
5533 /* Process change. */
5534 bgp_process(bgp
, dest
, afi
, safi
);
5536 if (SAFI_UNICAST
== safi
5537 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5538 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5539 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5542 /* Unintern original. */
5543 aspath_unintern(&attr
.aspath
);
5546 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5549 struct bgp_dest
*dest
;
5550 struct bgp_path_info
*pi
;
5552 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5554 /* Check selected route and self inserted route. */
5555 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5556 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5557 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5560 /* Withdraw static BGP route from routing table. */
5562 if (SAFI_UNICAST
== safi
5563 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5564 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5565 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5567 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5568 bgp_unlink_nexthop(pi
);
5569 bgp_path_info_delete(dest
, pi
);
5570 bgp_process(bgp
, dest
, afi
, safi
);
5573 /* Unlock bgp_node_lookup. */
5574 bgp_dest_unlock_node(dest
);
5578 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5580 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5581 afi_t afi
, safi_t safi
,
5582 struct prefix_rd
*prd
)
5584 struct bgp_dest
*dest
;
5585 struct bgp_path_info
*pi
;
5587 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5589 /* Check selected route and self inserted route. */
5590 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5591 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5592 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5595 /* Withdraw static BGP route from routing table. */
5597 #ifdef ENABLE_BGP_VNC
5598 rfapiProcessWithdraw(
5599 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5600 1); /* Kill, since it is an administrative change */
5602 if (SAFI_MPLS_VPN
== safi
5603 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5604 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5606 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5607 bgp_path_info_delete(dest
, pi
);
5608 bgp_process(bgp
, dest
, afi
, safi
);
5611 /* Unlock bgp_node_lookup. */
5612 bgp_dest_unlock_node(dest
);
5615 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5616 struct bgp_static
*bgp_static
, afi_t afi
,
5619 struct bgp_dest
*dest
;
5620 struct bgp_path_info
*new;
5621 struct attr
*attr_new
;
5622 struct attr attr
= {0};
5623 struct bgp_path_info
*pi
;
5624 #ifdef ENABLE_BGP_VNC
5625 mpls_label_t label
= 0;
5627 uint32_t num_labels
= 0;
5632 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5634 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5637 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5639 attr
.nexthop
= bgp_static
->igpnexthop
;
5640 attr
.med
= bgp_static
->igpmetric
;
5641 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5643 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5644 || (safi
== SAFI_ENCAP
)) {
5645 if (afi
== AFI_IP
) {
5646 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5647 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5650 if (afi
== AFI_L2VPN
) {
5651 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5653 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5654 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5655 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5656 sizeof(struct in6_addr
));
5657 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5658 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5659 struct bgp_encap_type_vxlan bet
;
5660 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5661 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5662 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5664 if (bgp_static
->router_mac
) {
5665 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5668 /* Apply route-map. */
5669 if (bgp_static
->rmap
.name
) {
5670 struct attr attr_tmp
= attr
;
5671 struct bgp_path_info rmap_path
;
5672 route_map_result_t ret
;
5674 rmap_path
.peer
= bgp
->peer_self
;
5675 rmap_path
.attr
= &attr_tmp
;
5677 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5679 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5681 bgp
->peer_self
->rmap_type
= 0;
5683 if (ret
== RMAP_DENYMATCH
) {
5684 /* Free uninterned attribute. */
5685 bgp_attr_flush(&attr_tmp
);
5687 /* Unintern original. */
5688 aspath_unintern(&attr
.aspath
);
5689 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5694 attr_new
= bgp_attr_intern(&attr_tmp
);
5696 attr_new
= bgp_attr_intern(&attr
);
5699 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5700 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5701 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5705 memset(&add
, 0, sizeof(union gw_addr
));
5706 if (attrhash_cmp(pi
->attr
, attr_new
)
5707 && overlay_index_equal(afi
, pi
, &add
)
5708 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5709 bgp_dest_unlock_node(dest
);
5710 bgp_attr_unintern(&attr_new
);
5711 aspath_unintern(&attr
.aspath
);
5714 /* The attribute is changed. */
5715 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5717 /* Rewrite BGP route information. */
5718 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5719 bgp_path_info_restore(dest
, pi
);
5721 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5722 bgp_attr_unintern(&pi
->attr
);
5723 pi
->attr
= attr_new
;
5724 pi
->uptime
= bgp_clock();
5725 #ifdef ENABLE_BGP_VNC
5727 label
= decode_label(&pi
->extra
->label
[0]);
5730 /* Process change. */
5731 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5732 bgp_process(bgp
, dest
, afi
, safi
);
5734 if (SAFI_MPLS_VPN
== safi
5735 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5736 vpn_leak_to_vrf_update(bgp
, pi
);
5738 #ifdef ENABLE_BGP_VNC
5739 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5740 pi
->attr
, afi
, safi
, pi
->type
,
5741 pi
->sub_type
, &label
);
5743 bgp_dest_unlock_node(dest
);
5744 aspath_unintern(&attr
.aspath
);
5750 /* Make new BGP info. */
5751 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5753 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5754 new->extra
= bgp_path_info_extra_new();
5756 new->extra
->label
[0] = bgp_static
->label
;
5757 new->extra
->num_labels
= num_labels
;
5759 #ifdef ENABLE_BGP_VNC
5760 label
= decode_label(&bgp_static
->label
);
5763 /* Aggregate address increment. */
5764 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5766 /* Register new BGP information. */
5767 bgp_path_info_add(dest
, new);
5768 /* route_node_get lock */
5769 bgp_dest_unlock_node(dest
);
5771 /* Process change. */
5772 bgp_process(bgp
, dest
, afi
, safi
);
5774 if (SAFI_MPLS_VPN
== safi
5775 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5776 vpn_leak_to_vrf_update(bgp
, new);
5778 #ifdef ENABLE_BGP_VNC
5779 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5780 safi
, new->type
, new->sub_type
, &label
);
5783 /* Unintern original. */
5784 aspath_unintern(&attr
.aspath
);
5787 /* Configure static BGP network. When user don't run zebra, static
5788 route should be installed as valid. */
5789 int bgp_static_set(struct bgp
*bgp
, const char *negate
, struct prefix
*pfx
,
5790 afi_t afi
, safi_t safi
, const char *rmap
, int backdoor
,
5791 uint32_t label_index
, char *errmsg
, size_t errmsg_len
)
5794 struct bgp_static
*bgp_static
;
5795 struct bgp_dest
*dest
;
5796 uint8_t need_update
= 0;
5798 prefix_copy(&p
, pfx
);
5803 /* Set BGP static route configuration. */
5804 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5807 snprintf(errmsg
, errmsg_len
,
5808 "Can't find static route specified\n");
5812 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5814 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5815 && (label_index
!= bgp_static
->label_index
)) {
5816 snprintf(errmsg
, errmsg_len
,
5817 "label-index doesn't match static route\n");
5821 if ((rmap
&& bgp_static
->rmap
.name
)
5822 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5823 snprintf(errmsg
, errmsg_len
,
5824 "route-map name doesn't match static route\n");
5828 /* Update BGP RIB. */
5829 if (!bgp_static
->backdoor
)
5830 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5832 /* Clear configuration. */
5833 bgp_static_free(bgp_static
);
5834 bgp_dest_set_bgp_static_info(dest
, NULL
);
5835 bgp_dest_unlock_node(dest
);
5836 bgp_dest_unlock_node(dest
);
5839 /* Set BGP static route configuration. */
5840 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5841 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5843 /* Configuration change. */
5844 /* Label index cannot be changed. */
5845 if (bgp_static
->label_index
!= label_index
) {
5846 snprintf(errmsg
, errmsg_len
,
5847 "cannot change label-index\n");
5851 /* Check previous routes are installed into BGP. */
5852 if (bgp_static
->valid
5853 && bgp_static
->backdoor
!= backdoor
)
5856 bgp_static
->backdoor
= backdoor
;
5859 XFREE(MTYPE_ROUTE_MAP_NAME
,
5860 bgp_static
->rmap
.name
);
5861 route_map_counter_decrement(
5862 bgp_static
->rmap
.map
);
5863 bgp_static
->rmap
.name
=
5864 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5865 bgp_static
->rmap
.map
=
5866 route_map_lookup_by_name(rmap
);
5867 route_map_counter_increment(
5868 bgp_static
->rmap
.map
);
5870 XFREE(MTYPE_ROUTE_MAP_NAME
,
5871 bgp_static
->rmap
.name
);
5872 route_map_counter_decrement(
5873 bgp_static
->rmap
.map
);
5874 bgp_static
->rmap
.map
= NULL
;
5875 bgp_static
->valid
= 0;
5877 bgp_dest_unlock_node(dest
);
5879 /* New configuration. */
5880 bgp_static
= bgp_static_new();
5881 bgp_static
->backdoor
= backdoor
;
5882 bgp_static
->valid
= 0;
5883 bgp_static
->igpmetric
= 0;
5884 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5885 bgp_static
->label_index
= label_index
;
5888 XFREE(MTYPE_ROUTE_MAP_NAME
,
5889 bgp_static
->rmap
.name
);
5890 route_map_counter_decrement(
5891 bgp_static
->rmap
.map
);
5892 bgp_static
->rmap
.name
=
5893 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5894 bgp_static
->rmap
.map
=
5895 route_map_lookup_by_name(rmap
);
5896 route_map_counter_increment(
5897 bgp_static
->rmap
.map
);
5899 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5902 bgp_static
->valid
= 1;
5904 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5906 if (!bgp_static
->backdoor
)
5907 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5913 void bgp_static_add(struct bgp
*bgp
)
5917 struct bgp_dest
*dest
;
5918 struct bgp_dest
*rm
;
5919 struct bgp_table
*table
;
5920 struct bgp_static
*bgp_static
;
5922 FOREACH_AFI_SAFI (afi
, safi
)
5923 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5924 dest
= bgp_route_next(dest
)) {
5925 if (!bgp_dest_has_bgp_path_info_data(dest
))
5928 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5929 || (safi
== SAFI_EVPN
)) {
5930 table
= bgp_dest_get_bgp_table_info(dest
);
5932 for (rm
= bgp_table_top(table
); rm
;
5933 rm
= bgp_route_next(rm
)) {
5935 bgp_dest_get_bgp_static_info(
5937 bgp_static_update_safi(
5938 bgp
, bgp_dest_get_prefix(rm
),
5939 bgp_static
, afi
, safi
);
5943 bgp
, bgp_dest_get_prefix(dest
),
5944 bgp_dest_get_bgp_static_info(dest
), afi
,
5950 /* Called from bgp_delete(). Delete all static routes from the BGP
5952 void bgp_static_delete(struct bgp
*bgp
)
5956 struct bgp_dest
*dest
;
5957 struct bgp_dest
*rm
;
5958 struct bgp_table
*table
;
5959 struct bgp_static
*bgp_static
;
5961 FOREACH_AFI_SAFI (afi
, safi
)
5962 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5963 dest
= bgp_route_next(dest
)) {
5964 if (!bgp_dest_has_bgp_path_info_data(dest
))
5967 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5968 || (safi
== SAFI_EVPN
)) {
5969 table
= bgp_dest_get_bgp_table_info(dest
);
5971 for (rm
= bgp_table_top(table
); rm
;
5972 rm
= bgp_route_next(rm
)) {
5974 bgp_dest_get_bgp_static_info(
5979 bgp_static_withdraw_safi(
5980 bgp
, bgp_dest_get_prefix(rm
),
5982 (struct prefix_rd
*)
5983 bgp_dest_get_prefix(
5985 bgp_static_free(bgp_static
);
5986 bgp_dest_set_bgp_static_info(rm
,
5988 bgp_dest_unlock_node(rm
);
5991 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5992 bgp_static_withdraw(bgp
,
5993 bgp_dest_get_prefix(dest
),
5995 bgp_static_free(bgp_static
);
5996 bgp_dest_set_bgp_static_info(dest
, NULL
);
5997 bgp_dest_unlock_node(dest
);
6002 void bgp_static_redo_import_check(struct bgp
*bgp
)
6006 struct bgp_dest
*dest
;
6007 struct bgp_dest
*rm
;
6008 struct bgp_table
*table
;
6009 struct bgp_static
*bgp_static
;
6011 /* Use this flag to force reprocessing of the route */
6012 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6013 FOREACH_AFI_SAFI (afi
, safi
) {
6014 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6015 dest
= bgp_route_next(dest
)) {
6016 if (!bgp_dest_has_bgp_path_info_data(dest
))
6019 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6020 || (safi
== SAFI_EVPN
)) {
6021 table
= bgp_dest_get_bgp_table_info(dest
);
6023 for (rm
= bgp_table_top(table
); rm
;
6024 rm
= bgp_route_next(rm
)) {
6026 bgp_dest_get_bgp_static_info(
6028 bgp_static_update_safi(
6029 bgp
, bgp_dest_get_prefix(rm
),
6030 bgp_static
, afi
, safi
);
6033 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6034 bgp_static_update(bgp
,
6035 bgp_dest_get_prefix(dest
),
6036 bgp_static
, afi
, safi
);
6040 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6043 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6046 struct bgp_table
*table
;
6047 struct bgp_dest
*dest
;
6048 struct bgp_path_info
*pi
;
6050 /* Do not install the aggregate route if BGP is in the
6051 * process of termination.
6053 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6054 || (bgp
->peer_self
== NULL
))
6057 table
= bgp
->rib
[afi
][safi
];
6058 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6059 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6060 if (pi
->peer
== bgp
->peer_self
6061 && ((pi
->type
== ZEBRA_ROUTE_BGP
6062 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6063 || (pi
->type
!= ZEBRA_ROUTE_BGP
6065 == BGP_ROUTE_REDISTRIBUTE
))) {
6066 bgp_aggregate_decrement(
6067 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6069 bgp_unlink_nexthop(pi
);
6070 bgp_path_info_delete(dest
, pi
);
6071 bgp_process(bgp
, dest
, afi
, safi
);
6078 * Purge all networks and redistributed routes from routing table.
6079 * Invoked upon the instance going down.
6081 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6086 FOREACH_AFI_SAFI (afi
, safi
)
6087 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6092 * Currently this is used to set static routes for VPN and ENCAP.
6093 * I think it can probably be factored with bgp_static_set.
6095 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6096 const char *ip_str
, const char *rd_str
,
6097 const char *label_str
, const char *rmap_str
,
6098 int evpn_type
, const char *esi
, const char *gwip
,
6099 const char *ethtag
, const char *routermac
)
6101 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6104 struct prefix_rd prd
;
6105 struct bgp_dest
*pdest
;
6106 struct bgp_dest
*dest
;
6107 struct bgp_table
*table
;
6108 struct bgp_static
*bgp_static
;
6109 mpls_label_t label
= MPLS_INVALID_LABEL
;
6110 struct prefix gw_ip
;
6112 /* validate ip prefix */
6113 ret
= str2prefix(ip_str
, &p
);
6115 vty_out(vty
, "%% Malformed prefix\n");
6116 return CMD_WARNING_CONFIG_FAILED
;
6119 if ((afi
== AFI_L2VPN
)
6120 && (bgp_build_evpn_prefix(evpn_type
,
6121 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6122 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6123 return CMD_WARNING_CONFIG_FAILED
;
6126 ret
= str2prefix_rd(rd_str
, &prd
);
6128 vty_out(vty
, "%% Malformed rd\n");
6129 return CMD_WARNING_CONFIG_FAILED
;
6133 unsigned long label_val
;
6134 label_val
= strtoul(label_str
, NULL
, 10);
6135 encode_label(label_val
, &label
);
6138 if (safi
== SAFI_EVPN
) {
6139 if (esi
&& str2esi(esi
, NULL
) == 0) {
6140 vty_out(vty
, "%% Malformed ESI\n");
6141 return CMD_WARNING_CONFIG_FAILED
;
6143 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6144 vty_out(vty
, "%% Malformed Router MAC\n");
6145 return CMD_WARNING_CONFIG_FAILED
;
6148 memset(&gw_ip
, 0, sizeof(struct prefix
));
6149 ret
= str2prefix(gwip
, &gw_ip
);
6151 vty_out(vty
, "%% Malformed GatewayIp\n");
6152 return CMD_WARNING_CONFIG_FAILED
;
6154 if ((gw_ip
.family
== AF_INET
6155 && is_evpn_prefix_ipaddr_v6(
6156 (struct prefix_evpn
*)&p
))
6157 || (gw_ip
.family
== AF_INET6
6158 && is_evpn_prefix_ipaddr_v4(
6159 (struct prefix_evpn
*)&p
))) {
6161 "%% GatewayIp family differs with IP prefix\n");
6162 return CMD_WARNING_CONFIG_FAILED
;
6166 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6167 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6168 bgp_dest_set_bgp_table_info(pdest
,
6169 bgp_table_init(bgp
, afi
, safi
));
6170 table
= bgp_dest_get_bgp_table_info(pdest
);
6172 dest
= bgp_node_get(table
, &p
);
6174 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6175 vty_out(vty
, "%% Same network configuration exists\n");
6176 bgp_dest_unlock_node(dest
);
6178 /* New configuration. */
6179 bgp_static
= bgp_static_new();
6180 bgp_static
->backdoor
= 0;
6181 bgp_static
->valid
= 0;
6182 bgp_static
->igpmetric
= 0;
6183 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6184 bgp_static
->label
= label
;
6185 bgp_static
->prd
= prd
;
6188 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6189 route_map_counter_decrement(bgp_static
->rmap
.map
);
6190 bgp_static
->rmap
.name
=
6191 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6192 bgp_static
->rmap
.map
=
6193 route_map_lookup_by_name(rmap_str
);
6194 route_map_counter_increment(bgp_static
->rmap
.map
);
6197 if (safi
== SAFI_EVPN
) {
6199 bgp_static
->eth_s_id
=
6202 str2esi(esi
, bgp_static
->eth_s_id
);
6205 bgp_static
->router_mac
=
6206 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6207 (void)prefix_str2mac(routermac
,
6208 bgp_static
->router_mac
);
6211 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6213 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6215 bgp_static
->valid
= 1;
6216 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6222 /* Configure static BGP network. */
6223 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6224 const char *ip_str
, const char *rd_str
,
6225 const char *label_str
, int evpn_type
, const char *esi
,
6226 const char *gwip
, const char *ethtag
)
6228 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6231 struct prefix_rd prd
;
6232 struct bgp_dest
*pdest
;
6233 struct bgp_dest
*dest
;
6234 struct bgp_table
*table
;
6235 struct bgp_static
*bgp_static
;
6236 mpls_label_t label
= MPLS_INVALID_LABEL
;
6238 /* Convert IP prefix string to struct prefix. */
6239 ret
= str2prefix(ip_str
, &p
);
6241 vty_out(vty
, "%% Malformed prefix\n");
6242 return CMD_WARNING_CONFIG_FAILED
;
6245 if ((afi
== AFI_L2VPN
)
6246 && (bgp_build_evpn_prefix(evpn_type
,
6247 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6248 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6249 return CMD_WARNING_CONFIG_FAILED
;
6251 ret
= str2prefix_rd(rd_str
, &prd
);
6253 vty_out(vty
, "%% Malformed rd\n");
6254 return CMD_WARNING_CONFIG_FAILED
;
6258 unsigned long label_val
;
6259 label_val
= strtoul(label_str
, NULL
, 10);
6260 encode_label(label_val
, &label
);
6263 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6264 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6265 bgp_dest_set_bgp_table_info(pdest
,
6266 bgp_table_init(bgp
, afi
, safi
));
6268 bgp_dest_unlock_node(pdest
);
6269 table
= bgp_dest_get_bgp_table_info(pdest
);
6271 dest
= bgp_node_lookup(table
, &p
);
6274 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6276 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6277 bgp_static_free(bgp_static
);
6278 bgp_dest_set_bgp_static_info(dest
, NULL
);
6279 bgp_dest_unlock_node(dest
);
6280 bgp_dest_unlock_node(dest
);
6282 vty_out(vty
, "%% Can't find the route\n");
6287 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6288 const char *rmap_name
)
6290 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6291 struct bgp_rmap
*rmap
;
6293 rmap
= &bgp
->table_map
[afi
][safi
];
6295 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6296 route_map_counter_decrement(rmap
->map
);
6297 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6298 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6299 route_map_counter_increment(rmap
->map
);
6301 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6302 route_map_counter_decrement(rmap
->map
);
6306 if (bgp_fibupd_safi(safi
))
6307 bgp_zebra_announce_table(bgp
, afi
, safi
);
6312 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6313 const char *rmap_name
)
6315 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6316 struct bgp_rmap
*rmap
;
6318 rmap
= &bgp
->table_map
[afi
][safi
];
6319 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6320 route_map_counter_decrement(rmap
->map
);
6323 if (bgp_fibupd_safi(safi
))
6324 bgp_zebra_announce_table(bgp
, afi
, safi
);
6329 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6332 if (bgp
->table_map
[afi
][safi
].name
) {
6333 vty_out(vty
, " table-map %s\n",
6334 bgp
->table_map
[afi
][safi
].name
);
6338 DEFUN (bgp_table_map
,
6341 "BGP table to RIB route download filter\n"
6342 "Name of the route map\n")
6345 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6346 argv
[idx_word
]->arg
);
6348 DEFUN (no_bgp_table_map
,
6349 no_bgp_table_map_cmd
,
6350 "no table-map WORD",
6352 "BGP table to RIB route download filter\n"
6353 "Name of the route map\n")
6356 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6357 argv
[idx_word
]->arg
);
6360 DEFPY_YANG (bgp_network
, bgp_network_cmd
,
6362 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6363 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6364 backdoor$backdoor}]",
6366 "Specify a network to announce via BGP\n"
6371 "Route-map to modify the attributes\n"
6372 "Name of the route map\n"
6373 "Label index to associate with the prefix\n"
6374 "Label index value\n"
6375 "Specify a BGP backdoor route\n")
6377 char addr_prefix_str
[PREFIX_STRLEN
];
6378 char base_xpath
[XPATH_MAXLEN
];
6385 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6388 vty_out(vty
, "%% Inconsistent address and mask\n");
6389 return CMD_WARNING_CONFIG_FAILED
;
6393 afi
= bgp_node_afi(vty
);
6394 safi
= bgp_node_safi(vty
);
6397 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6399 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6402 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6403 NB_OP_CREATE
, map_name
);
6405 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6406 NB_OP_DESTROY
, NULL
);
6408 if (label_index_str
)
6409 nb_cli_enqueue_change(vty
, "./label-index",
6410 NB_OP_MODIFY
, label_index_str
);
6412 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6413 backdoor
? "true" : "false");
6417 base_xpath
, sizeof(base_xpath
),
6418 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6419 yang_afi_safi_value2identity(afi
, safi
),
6420 bgp_afi_safi_get_container_str(afi
, safi
),
6421 address_str
? addr_prefix_str
: prefix_str
);
6423 return nb_cli_apply_changes(vty
, base_xpath
);
6426 DEFPY_YANG (ipv6_bgp_network
,
6427 ipv6_bgp_network_cmd
,
6428 "[no] network X:X::X:X/M$prefix \
6429 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6431 "Specify a network to announce via BGP\n"
6433 "Route-map to modify the attributes\n"
6434 "Name of the route map\n"
6435 "Label index to associate with the prefix\n"
6436 "Label index value\n")
6438 char base_xpath
[XPATH_MAXLEN
];
6442 afi
= bgp_node_afi(vty
);
6443 safi
= bgp_node_safi(vty
);
6446 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6448 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6451 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6452 NB_OP_MODIFY
, map_name
);
6454 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6455 NB_OP_DESTROY
, NULL
);
6457 if (label_index_str
)
6458 nb_cli_enqueue_change(vty
, "./label-index",
6459 NB_OP_MODIFY
, label_index_str
);
6463 base_xpath
, sizeof(base_xpath
),
6464 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6465 yang_afi_safi_value2identity(afi
, safi
),
6466 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6468 return nb_cli_apply_changes(vty
, base_xpath
);
6471 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6472 struct lyd_node
*dnode
,
6475 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6477 if (yang_dnode_exists(dnode
, "./label-index"))
6478 vty_out(vty
, " label-index %s",
6479 yang_dnode_get_string(dnode
, "./label-index"));
6481 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6482 vty_out(vty
, " route-map %s",
6483 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6485 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6486 vty_out(vty
, " backdoor");
6491 static struct bgp_aggregate
*bgp_aggregate_new(void)
6493 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6496 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6498 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6499 route_map_counter_decrement(aggregate
->suppress_map
);
6500 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6501 route_map_counter_decrement(aggregate
->rmap
.map
);
6502 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6506 * Helper function to avoid repeated code: prepare variables for a
6507 * `route_map_apply` call.
6509 * \returns `true` on route map match, otherwise `false`.
6511 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6512 struct bgp_aggregate
*aggregate
,
6513 struct bgp_path_info
*pi
)
6515 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6516 route_map_result_t rmr
= RMAP_DENYMATCH
;
6517 struct bgp_path_info rmap_path
= {};
6518 struct attr attr
= {};
6520 /* No route map entries created, just don't match. */
6521 if (aggregate
->suppress_map
== NULL
)
6524 /* Call route map matching and return result. */
6525 attr
.aspath
= aspath_empty();
6526 rmap_path
.peer
= bgp
->peer_self
;
6527 rmap_path
.attr
= &attr
;
6529 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6530 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6531 bgp
->peer_self
->rmap_type
= 0;
6533 bgp_attr_flush(&attr
);
6535 return rmr
== RMAP_PERMITMATCH
;
6538 /** Test whether the aggregation has suppressed this path or not. */
6539 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6540 struct bgp_path_info
*pi
)
6542 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6545 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6549 * Suppress this path and keep the reference.
6551 * \returns `true` if needs processing otherwise `false`.
6553 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6554 struct bgp_path_info
*pi
)
6556 struct bgp_path_info_extra
*pie
;
6558 /* Path is already suppressed by this aggregation. */
6559 if (aggr_suppress_exists(aggregate
, pi
))
6562 pie
= bgp_path_info_extra_get(pi
);
6564 /* This is the first suppression, allocate memory and list it. */
6565 if (pie
->aggr_suppressors
== NULL
)
6566 pie
->aggr_suppressors
= list_new();
6568 listnode_add(pie
->aggr_suppressors
, aggregate
);
6570 /* Only mark for processing if suppressed. */
6571 if (listcount(pie
->aggr_suppressors
) == 1) {
6572 if (BGP_DEBUG(update
, UPDATE_OUT
))
6573 zlog_debug("aggregate-address suppressing: %pFX",
6574 bgp_dest_get_prefix(pi
->net
));
6576 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6584 * Unsuppress this path and remove the reference.
6586 * \returns `true` if needs processing otherwise `false`.
6588 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6589 struct bgp_path_info
*pi
)
6591 /* Path wasn't suppressed. */
6592 if (!aggr_suppress_exists(aggregate
, pi
))
6595 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6597 /* Unsuppress and free extra memory if last item. */
6598 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6599 if (BGP_DEBUG(update
, UPDATE_OUT
))
6600 zlog_debug("aggregate-address unsuppressing: %pFX",
6601 bgp_dest_get_prefix(pi
->net
));
6603 list_delete(&pi
->extra
->aggr_suppressors
);
6604 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6611 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6612 struct aspath
*aspath
,
6613 struct community
*comm
,
6614 struct ecommunity
*ecomm
,
6615 struct lcommunity
*lcomm
)
6617 static struct aspath
*ae
= NULL
;
6620 ae
= aspath_empty();
6625 if (origin
!= pi
->attr
->origin
)
6628 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6631 if (!community_cmp(pi
->attr
->community
, comm
))
6634 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6637 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6640 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6646 static void bgp_aggregate_install(
6647 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6648 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6649 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6650 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6652 struct bgp_dest
*dest
;
6653 struct bgp_table
*table
;
6654 struct bgp_path_info
*pi
, *orig
, *new;
6657 table
= bgp
->rib
[afi
][safi
];
6659 dest
= bgp_node_get(table
, p
);
6661 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6662 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6663 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6667 * If we have paths with different MEDs, then don't install
6668 * (or uninstall) the aggregate route.
6670 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6671 goto uninstall_aggregate_route
;
6673 if (aggregate
->count
> 0) {
6675 * If the aggregate information has not changed
6676 * no need to re-install it again.
6678 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6679 ecommunity
, lcommunity
)) {
6680 bgp_dest_unlock_node(dest
);
6683 aspath_free(aspath
);
6685 community_free(&community
);
6687 ecommunity_free(&ecommunity
);
6689 lcommunity_free(&lcommunity
);
6695 * Mark the old as unusable
6698 bgp_path_info_delete(dest
, pi
);
6700 attr
= bgp_attr_aggregate_intern(
6701 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6702 aggregate
, atomic_aggregate
, p
);
6705 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6706 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6707 zlog_debug("%s: %pFX null attribute", __func__
,
6712 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6713 bgp
->peer_self
, attr
, dest
);
6715 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6717 bgp_path_info_add(dest
, new);
6718 bgp_process(bgp
, dest
, afi
, safi
);
6720 uninstall_aggregate_route
:
6721 for (pi
= orig
; pi
; pi
= pi
->next
)
6722 if (pi
->peer
== bgp
->peer_self
6723 && pi
->type
== ZEBRA_ROUTE_BGP
6724 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6727 /* Withdraw static BGP route from routing table. */
6729 bgp_path_info_delete(dest
, pi
);
6730 bgp_process(bgp
, dest
, afi
, safi
);
6734 bgp_dest_unlock_node(dest
);
6738 * Check if the current path has different MED than other known paths.
6740 * \returns `true` if the MED matched the others else `false`.
6742 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6743 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6745 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6747 /* This is the first route being analyzed. */
6748 if (!aggregate
->med_initialized
) {
6749 aggregate
->med_initialized
= true;
6750 aggregate
->med_mismatched
= false;
6751 aggregate
->med_matched_value
= cur_med
;
6753 /* Check if routes with different MED showed up. */
6754 if (cur_med
!= aggregate
->med_matched_value
)
6755 aggregate
->med_mismatched
= true;
6758 return !aggregate
->med_mismatched
;
6762 * Initializes and tests all routes in the aggregate address path for MED
6765 * \returns `true` if all MEDs are the same otherwise `false`.
6767 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6768 struct bgp
*bgp
, const struct prefix
*p
,
6769 afi_t afi
, safi_t safi
)
6771 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6772 const struct prefix
*dest_p
;
6773 struct bgp_dest
*dest
, *top
;
6774 struct bgp_path_info
*pi
;
6775 bool med_matched
= true;
6777 aggregate
->med_initialized
= false;
6779 top
= bgp_node_get(table
, p
);
6780 for (dest
= bgp_node_get(table
, p
); dest
;
6781 dest
= bgp_route_next_until(dest
, top
)) {
6782 dest_p
= bgp_dest_get_prefix(dest
);
6783 if (dest_p
->prefixlen
<= p
->prefixlen
)
6786 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6787 if (BGP_PATH_HOLDDOWN(pi
))
6789 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6791 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6792 med_matched
= false;
6799 bgp_dest_unlock_node(top
);
6805 * Toggles the route suppression status for this aggregate address
6808 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6809 struct bgp
*bgp
, const struct prefix
*p
,
6810 afi_t afi
, safi_t safi
, bool suppress
)
6812 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6813 const struct prefix
*dest_p
;
6814 struct bgp_dest
*dest
, *top
;
6815 struct bgp_path_info
*pi
;
6816 bool toggle_suppression
;
6818 /* We've found a different MED we must revert any suppressed routes. */
6819 top
= bgp_node_get(table
, p
);
6820 for (dest
= bgp_node_get(table
, p
); dest
;
6821 dest
= bgp_route_next_until(dest
, top
)) {
6822 dest_p
= bgp_dest_get_prefix(dest
);
6823 if (dest_p
->prefixlen
<= p
->prefixlen
)
6826 toggle_suppression
= false;
6827 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6828 if (BGP_PATH_HOLDDOWN(pi
))
6830 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6833 /* We are toggling suppression back. */
6835 /* Suppress route if not suppressed already. */
6836 if (aggr_suppress_path(aggregate
, pi
))
6837 toggle_suppression
= true;
6841 /* Install route if there is no more suppression. */
6842 if (aggr_unsuppress_path(aggregate
, pi
))
6843 toggle_suppression
= true;
6846 if (toggle_suppression
)
6847 bgp_process(bgp
, dest
, afi
, safi
);
6849 bgp_dest_unlock_node(top
);
6853 * Aggregate address MED matching incremental test: this function is called
6854 * when the initial aggregation occurred and we are only testing a single
6857 * In addition to testing and setting the MED validity it also installs back
6858 * suppressed routes (if summary is configured).
6860 * Must not be called in `bgp_aggregate_route`.
6862 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6863 struct bgp
*bgp
, const struct prefix
*p
,
6864 afi_t afi
, safi_t safi
,
6865 struct bgp_path_info
*pi
, bool is_adding
)
6867 /* MED matching disabled. */
6868 if (!aggregate
->match_med
)
6871 /* Aggregation with different MED, nothing to do. */
6872 if (aggregate
->med_mismatched
)
6876 * Test the current entry:
6878 * is_adding == true: if the new entry doesn't match then we must
6879 * install all suppressed routes.
6881 * is_adding == false: if the entry being removed was the last
6882 * unmatching entry then we can suppress all routes.
6885 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6886 && aggregate
->summary_only
)
6887 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6890 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6892 /* No mismatches, just quit. */
6893 if (!aggregate
->med_mismatched
)
6896 /* Route summarization is disabled. */
6897 if (!aggregate
->summary_only
)
6900 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6903 /* Update an aggregate as routes are added/removed from the BGP table */
6904 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6905 safi_t safi
, struct bgp_aggregate
*aggregate
)
6907 struct bgp_table
*table
;
6908 struct bgp_dest
*top
;
6909 struct bgp_dest
*dest
;
6911 struct aspath
*aspath
= NULL
;
6912 struct community
*community
= NULL
;
6913 struct ecommunity
*ecommunity
= NULL
;
6914 struct lcommunity
*lcommunity
= NULL
;
6915 struct bgp_path_info
*pi
;
6916 unsigned long match
= 0;
6917 uint8_t atomic_aggregate
= 0;
6919 /* If the bgp instance is being deleted or self peer is deleted
6920 * then do not create aggregate route
6922 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6923 || (bgp
->peer_self
== NULL
))
6926 /* Initialize and test routes for MED difference. */
6927 if (aggregate
->match_med
)
6928 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6931 * Reset aggregate count: we might've been called from route map
6932 * update so in that case we must retest all more specific routes.
6934 * \see `bgp_route_map_process_update`.
6936 aggregate
->count
= 0;
6937 aggregate
->incomplete_origin_count
= 0;
6938 aggregate
->incomplete_origin_count
= 0;
6939 aggregate
->egp_origin_count
= 0;
6941 /* ORIGIN attribute: If at least one route among routes that are
6942 aggregated has ORIGIN with the value INCOMPLETE, then the
6943 aggregated route must have the ORIGIN attribute with the value
6944 INCOMPLETE. Otherwise, if at least one route among routes that
6945 are aggregated has ORIGIN with the value EGP, then the aggregated
6946 route must have the origin attribute with the value EGP. In all
6947 other case the value of the ORIGIN attribute of the aggregated
6948 route is INTERNAL. */
6949 origin
= BGP_ORIGIN_IGP
;
6951 table
= bgp
->rib
[afi
][safi
];
6953 top
= bgp_node_get(table
, p
);
6954 for (dest
= bgp_node_get(table
, p
); dest
;
6955 dest
= bgp_route_next_until(dest
, top
)) {
6956 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6958 if (dest_p
->prefixlen
<= p
->prefixlen
)
6961 /* If suppress fib is enabled and route not installed
6962 * in FIB, skip the route
6964 if (!bgp_check_advertise(bgp
, dest
))
6969 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6970 if (BGP_PATH_HOLDDOWN(pi
))
6974 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6975 atomic_aggregate
= 1;
6977 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6981 * summary-only aggregate route suppress
6982 * aggregated route announcements.
6985 * Don't create summaries if MED didn't match
6986 * otherwise neither the specific routes and the
6987 * aggregation will be announced.
6989 if (aggregate
->summary_only
6990 && AGGREGATE_MED_VALID(aggregate
)) {
6991 if (aggr_suppress_path(aggregate
, pi
))
6996 * Suppress more specific routes that match the route
7000 * Don't suppress routes if MED matching is enabled and
7001 * it mismatched otherwise we might end up with no
7002 * routes for this path.
7004 if (aggregate
->suppress_map_name
7005 && AGGREGATE_MED_VALID(aggregate
)
7006 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7007 if (aggr_suppress_path(aggregate
, pi
))
7014 * If at least one route among routes that are
7015 * aggregated has ORIGIN with the value INCOMPLETE,
7016 * then the aggregated route MUST have the ORIGIN
7017 * attribute with the value INCOMPLETE. Otherwise, if
7018 * at least one route among routes that are aggregated
7019 * has ORIGIN with the value EGP, then the aggregated
7020 * route MUST have the ORIGIN attribute with the value
7023 switch (pi
->attr
->origin
) {
7024 case BGP_ORIGIN_INCOMPLETE
:
7025 aggregate
->incomplete_origin_count
++;
7027 case BGP_ORIGIN_EGP
:
7028 aggregate
->egp_origin_count
++;
7036 if (!aggregate
->as_set
)
7040 * as-set aggregate route generate origin, as path,
7041 * and community aggregation.
7043 /* Compute aggregate route's as-path.
7045 bgp_compute_aggregate_aspath_hash(aggregate
,
7048 /* Compute aggregate route's community.
7050 if (pi
->attr
->community
)
7051 bgp_compute_aggregate_community_hash(
7053 pi
->attr
->community
);
7055 /* Compute aggregate route's extended community.
7057 if (pi
->attr
->ecommunity
)
7058 bgp_compute_aggregate_ecommunity_hash(
7060 pi
->attr
->ecommunity
);
7062 /* Compute aggregate route's large community.
7064 if (pi
->attr
->lcommunity
)
7065 bgp_compute_aggregate_lcommunity_hash(
7067 pi
->attr
->lcommunity
);
7070 bgp_process(bgp
, dest
, afi
, safi
);
7072 if (aggregate
->as_set
) {
7073 bgp_compute_aggregate_aspath_val(aggregate
);
7074 bgp_compute_aggregate_community_val(aggregate
);
7075 bgp_compute_aggregate_ecommunity_val(aggregate
);
7076 bgp_compute_aggregate_lcommunity_val(aggregate
);
7080 bgp_dest_unlock_node(top
);
7083 if (aggregate
->incomplete_origin_count
> 0)
7084 origin
= BGP_ORIGIN_INCOMPLETE
;
7085 else if (aggregate
->egp_origin_count
> 0)
7086 origin
= BGP_ORIGIN_EGP
;
7088 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7089 origin
= aggregate
->origin
;
7091 if (aggregate
->as_set
) {
7092 if (aggregate
->aspath
)
7093 /* Retrieve aggregate route's as-path.
7095 aspath
= aspath_dup(aggregate
->aspath
);
7097 if (aggregate
->community
)
7098 /* Retrieve aggregate route's community.
7100 community
= community_dup(aggregate
->community
);
7102 if (aggregate
->ecommunity
)
7103 /* Retrieve aggregate route's ecommunity.
7105 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7107 if (aggregate
->lcommunity
)
7108 /* Retrieve aggregate route's lcommunity.
7110 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7113 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7114 ecommunity
, lcommunity
, atomic_aggregate
,
7118 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7119 safi_t safi
, struct bgp_aggregate
*aggregate
)
7121 struct bgp_table
*table
;
7122 struct bgp_dest
*top
;
7123 struct bgp_dest
*dest
;
7124 struct bgp_path_info
*pi
;
7125 unsigned long match
;
7127 table
= bgp
->rib
[afi
][safi
];
7129 /* If routes exists below this node, generate aggregate routes. */
7130 top
= bgp_node_get(table
, p
);
7131 for (dest
= bgp_node_get(table
, p
); dest
;
7132 dest
= bgp_route_next_until(dest
, top
)) {
7133 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7135 if (dest_p
->prefixlen
<= p
->prefixlen
)
7139 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7140 if (BGP_PATH_HOLDDOWN(pi
))
7143 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7146 if (aggregate
->summary_only
&& pi
->extra
7147 && AGGREGATE_MED_VALID(aggregate
)) {
7148 if (aggr_unsuppress_path(aggregate
, pi
))
7152 if (aggregate
->suppress_map_name
7153 && AGGREGATE_MED_VALID(aggregate
)
7154 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7155 if (aggr_unsuppress_path(aggregate
, pi
))
7161 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7162 aggregate
->incomplete_origin_count
--;
7163 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7164 aggregate
->egp_origin_count
--;
7166 if (aggregate
->as_set
) {
7167 /* Remove as-path from aggregate.
7169 bgp_remove_aspath_from_aggregate_hash(
7173 if (pi
->attr
->community
)
7174 /* Remove community from aggregate.
7176 bgp_remove_comm_from_aggregate_hash(
7178 pi
->attr
->community
);
7180 if (pi
->attr
->ecommunity
)
7181 /* Remove ecommunity from aggregate.
7183 bgp_remove_ecomm_from_aggregate_hash(
7185 pi
->attr
->ecommunity
);
7187 if (pi
->attr
->lcommunity
)
7188 /* Remove lcommunity from aggregate.
7190 bgp_remove_lcomm_from_aggregate_hash(
7192 pi
->attr
->lcommunity
);
7196 /* If this node was suppressed, process the change. */
7198 bgp_process(bgp
, dest
, afi
, safi
);
7200 if (aggregate
->as_set
) {
7201 aspath_free(aggregate
->aspath
);
7202 aggregate
->aspath
= NULL
;
7203 if (aggregate
->community
)
7204 community_free(&aggregate
->community
);
7205 if (aggregate
->ecommunity
)
7206 ecommunity_free(&aggregate
->ecommunity
);
7207 if (aggregate
->lcommunity
)
7208 lcommunity_free(&aggregate
->lcommunity
);
7211 bgp_dest_unlock_node(top
);
7214 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7215 const struct prefix
*aggr_p
,
7216 struct bgp_path_info
*pinew
, afi_t afi
,
7218 struct bgp_aggregate
*aggregate
)
7221 struct aspath
*aspath
= NULL
;
7222 uint8_t atomic_aggregate
= 0;
7223 struct community
*community
= NULL
;
7224 struct ecommunity
*ecommunity
= NULL
;
7225 struct lcommunity
*lcommunity
= NULL
;
7227 /* If the bgp instance is being deleted or self peer is deleted
7228 * then do not create aggregate route
7230 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7231 || (bgp
->peer_self
== NULL
))
7234 /* ORIGIN attribute: If at least one route among routes that are
7235 * aggregated has ORIGIN with the value INCOMPLETE, then the
7236 * aggregated route must have the ORIGIN attribute with the value
7237 * INCOMPLETE. Otherwise, if at least one route among routes that
7238 * are aggregated has ORIGIN with the value EGP, then the aggregated
7239 * route must have the origin attribute with the value EGP. In all
7240 * other case the value of the ORIGIN attribute of the aggregated
7241 * route is INTERNAL.
7243 origin
= BGP_ORIGIN_IGP
;
7248 * This must be called before `summary` check to avoid
7249 * "suppressing" twice.
7251 if (aggregate
->match_med
)
7252 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7255 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7256 aggr_suppress_path(aggregate
, pinew
);
7258 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7259 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7260 aggr_suppress_path(aggregate
, pinew
);
7262 switch (pinew
->attr
->origin
) {
7263 case BGP_ORIGIN_INCOMPLETE
:
7264 aggregate
->incomplete_origin_count
++;
7266 case BGP_ORIGIN_EGP
:
7267 aggregate
->egp_origin_count
++;
7275 if (aggregate
->incomplete_origin_count
> 0)
7276 origin
= BGP_ORIGIN_INCOMPLETE
;
7277 else if (aggregate
->egp_origin_count
> 0)
7278 origin
= BGP_ORIGIN_EGP
;
7280 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7281 origin
= aggregate
->origin
;
7283 if (aggregate
->as_set
) {
7284 /* Compute aggregate route's as-path.
7286 bgp_compute_aggregate_aspath(aggregate
,
7287 pinew
->attr
->aspath
);
7289 /* Compute aggregate route's community.
7291 if (pinew
->attr
->community
)
7292 bgp_compute_aggregate_community(
7294 pinew
->attr
->community
);
7296 /* Compute aggregate route's extended community.
7298 if (pinew
->attr
->ecommunity
)
7299 bgp_compute_aggregate_ecommunity(
7301 pinew
->attr
->ecommunity
);
7303 /* Compute aggregate route's large community.
7305 if (pinew
->attr
->lcommunity
)
7306 bgp_compute_aggregate_lcommunity(
7308 pinew
->attr
->lcommunity
);
7310 /* Retrieve aggregate route's as-path.
7312 if (aggregate
->aspath
)
7313 aspath
= aspath_dup(aggregate
->aspath
);
7315 /* Retrieve aggregate route's community.
7317 if (aggregate
->community
)
7318 community
= community_dup(aggregate
->community
);
7320 /* Retrieve aggregate route's ecommunity.
7322 if (aggregate
->ecommunity
)
7323 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7325 /* Retrieve aggregate route's lcommunity.
7327 if (aggregate
->lcommunity
)
7328 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7331 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7332 aspath
, community
, ecommunity
,
7333 lcommunity
, atomic_aggregate
, aggregate
);
7336 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7338 struct bgp_path_info
*pi
,
7339 struct bgp_aggregate
*aggregate
,
7340 const struct prefix
*aggr_p
)
7343 struct aspath
*aspath
= NULL
;
7344 uint8_t atomic_aggregate
= 0;
7345 struct community
*community
= NULL
;
7346 struct ecommunity
*ecommunity
= NULL
;
7347 struct lcommunity
*lcommunity
= NULL
;
7348 unsigned long match
= 0;
7350 /* If the bgp instance is being deleted or self peer is deleted
7351 * then do not create aggregate route
7353 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7354 || (bgp
->peer_self
== NULL
))
7357 if (BGP_PATH_HOLDDOWN(pi
))
7360 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7363 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7364 if (aggr_unsuppress_path(aggregate
, pi
))
7367 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7368 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7369 if (aggr_unsuppress_path(aggregate
, pi
))
7373 * This must be called after `summary`, `suppress-map` check to avoid
7374 * "unsuppressing" twice.
7376 if (aggregate
->match_med
)
7377 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7380 if (aggregate
->count
> 0)
7383 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7384 aggregate
->incomplete_origin_count
--;
7385 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7386 aggregate
->egp_origin_count
--;
7388 if (aggregate
->as_set
) {
7389 /* Remove as-path from aggregate.
7391 bgp_remove_aspath_from_aggregate(aggregate
,
7394 if (pi
->attr
->community
)
7395 /* Remove community from aggregate.
7397 bgp_remove_community_from_aggregate(
7399 pi
->attr
->community
);
7401 if (pi
->attr
->ecommunity
)
7402 /* Remove ecommunity from aggregate.
7404 bgp_remove_ecommunity_from_aggregate(
7406 pi
->attr
->ecommunity
);
7408 if (pi
->attr
->lcommunity
)
7409 /* Remove lcommunity from aggregate.
7411 bgp_remove_lcommunity_from_aggregate(
7413 pi
->attr
->lcommunity
);
7416 /* If this node was suppressed, process the change. */
7418 bgp_process(bgp
, pi
->net
, afi
, safi
);
7420 origin
= BGP_ORIGIN_IGP
;
7421 if (aggregate
->incomplete_origin_count
> 0)
7422 origin
= BGP_ORIGIN_INCOMPLETE
;
7423 else if (aggregate
->egp_origin_count
> 0)
7424 origin
= BGP_ORIGIN_EGP
;
7426 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7427 origin
= aggregate
->origin
;
7429 if (aggregate
->as_set
) {
7430 /* Retrieve aggregate route's as-path.
7432 if (aggregate
->aspath
)
7433 aspath
= aspath_dup(aggregate
->aspath
);
7435 /* Retrieve aggregate route's community.
7437 if (aggregate
->community
)
7438 community
= community_dup(aggregate
->community
);
7440 /* Retrieve aggregate route's ecommunity.
7442 if (aggregate
->ecommunity
)
7443 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7445 /* Retrieve aggregate route's lcommunity.
7447 if (aggregate
->lcommunity
)
7448 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7451 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7452 aspath
, community
, ecommunity
,
7453 lcommunity
, atomic_aggregate
, aggregate
);
7456 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7457 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7459 struct bgp_dest
*child
;
7460 struct bgp_dest
*dest
;
7461 struct bgp_aggregate
*aggregate
;
7462 struct bgp_table
*table
;
7464 table
= bgp
->aggregate
[afi
][safi
];
7466 /* No aggregates configured. */
7467 if (bgp_table_top_nolock(table
) == NULL
)
7470 if (p
->prefixlen
== 0)
7473 if (BGP_PATH_HOLDDOWN(pi
))
7476 /* If suppress fib is enabled and route not installed
7477 * in FIB, do not update the aggregate route
7479 if (!bgp_check_advertise(bgp
, pi
->net
))
7482 child
= bgp_node_get(table
, p
);
7484 /* Aggregate address configuration check. */
7485 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7486 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7488 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7489 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7490 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7494 bgp_dest_unlock_node(child
);
7497 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7498 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7500 struct bgp_dest
*child
;
7501 struct bgp_dest
*dest
;
7502 struct bgp_aggregate
*aggregate
;
7503 struct bgp_table
*table
;
7505 table
= bgp
->aggregate
[afi
][safi
];
7507 /* No aggregates configured. */
7508 if (bgp_table_top_nolock(table
) == NULL
)
7511 if (p
->prefixlen
== 0)
7514 child
= bgp_node_get(table
, p
);
7516 /* Aggregate address configuration check. */
7517 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7518 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7520 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7521 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7522 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7526 bgp_dest_unlock_node(child
);
7529 /* Aggregate route attribute. */
7530 #define AGGREGATE_SUMMARY_ONLY 1
7531 #define AGGREGATE_AS_SET 1
7532 #define AGGREGATE_AS_UNSET 0
7534 static const char *bgp_origin2str(uint8_t origin
)
7537 case BGP_ORIGIN_IGP
:
7539 case BGP_ORIGIN_EGP
:
7541 case BGP_ORIGIN_INCOMPLETE
:
7542 return "incomplete";
7547 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7548 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7550 struct bgp_dest
*dest
;
7551 struct bgp_aggregate
*aggregate
;
7553 /* If the bgp instance is being deleted or self peer is deleted
7554 * then do not create aggregate route
7556 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7557 || (bgp
->peer_self
== NULL
))
7561 /* Old configuration check. */
7562 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7564 snprintf(errmsg
, errmsg_len
,
7565 "There is no aggregate-address configuration.\n");
7569 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7570 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7571 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7574 /* Unlock aggregate address configuration. */
7575 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7577 if (aggregate
->community
)
7578 community_free(&aggregate
->community
);
7580 if (aggregate
->community_hash
) {
7581 /* Delete all communities in the hash.
7583 hash_clean(aggregate
->community_hash
,
7584 bgp_aggr_community_remove
);
7585 /* Free up the community_hash.
7587 hash_free(aggregate
->community_hash
);
7590 if (aggregate
->ecommunity
)
7591 ecommunity_free(&aggregate
->ecommunity
);
7593 if (aggregate
->ecommunity_hash
) {
7594 /* Delete all ecommunities in the hash.
7596 hash_clean(aggregate
->ecommunity_hash
,
7597 bgp_aggr_ecommunity_remove
);
7598 /* Free up the ecommunity_hash.
7600 hash_free(aggregate
->ecommunity_hash
);
7603 if (aggregate
->lcommunity
)
7604 lcommunity_free(&aggregate
->lcommunity
);
7606 if (aggregate
->lcommunity_hash
) {
7607 /* Delete all lcommunities in the hash.
7609 hash_clean(aggregate
->lcommunity_hash
,
7610 bgp_aggr_lcommunity_remove
);
7611 /* Free up the lcommunity_hash.
7613 hash_free(aggregate
->lcommunity_hash
);
7616 if (aggregate
->aspath
)
7617 aspath_free(aggregate
->aspath
);
7619 if (aggregate
->aspath_hash
) {
7620 /* Delete all as-paths in the hash.
7622 hash_clean(aggregate
->aspath_hash
,
7623 bgp_aggr_aspath_remove
);
7624 /* Free up the aspath_hash.
7626 hash_free(aggregate
->aspath_hash
);
7629 bgp_aggregate_free(aggregate
);
7630 bgp_dest_unlock_node(dest
);
7631 bgp_dest_unlock_node(dest
);
7636 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7637 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7638 uint8_t as_set
, uint8_t origin
, bool match_med
,
7639 const char *suppress_map
,
7640 char *errmsg
, size_t errmsg_len
)
7643 struct bgp_dest
*dest
;
7644 struct bgp_aggregate
*aggregate
;
7645 uint8_t as_set_new
= as_set
;
7646 char buf
[PREFIX2STR_BUFFER
];
7648 if (suppress_map
&& summary_only
) {
7649 snprintf(errmsg
, errmsg_len
,
7650 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7656 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7657 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7660 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7661 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7665 /* Old configuration check. */
7666 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7667 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7670 snprintf(errmsg
, errmsg_len
,
7671 "There is already same aggregate network.\n");
7672 /* try to remove the old entry */
7673 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7676 snprintf(errmsg
, errmsg_len
,
7677 "Error deleting aggregate.\n");
7678 bgp_dest_unlock_node(dest
);
7683 /* Make aggregate address structure. */
7684 aggregate
= bgp_aggregate_new();
7685 aggregate
->summary_only
= summary_only
;
7686 aggregate
->match_med
= match_med
;
7688 /* Network operators MUST NOT locally generate any new
7689 * announcements containing AS_SET or AS_CONFED_SET. If they have
7690 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7691 * SHOULD withdraw those routes and re-announce routes for the
7692 * aggregate or component prefixes (i.e., the more-specific routes
7693 * subsumed by the previously aggregated route) without AS_SET
7694 * or AS_CONFED_SET in the updates.
7696 if (bgp
->reject_as_sets
) {
7697 if (as_set
== AGGREGATE_AS_SET
) {
7698 as_set_new
= AGGREGATE_AS_UNSET
;
7700 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7704 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7708 aggregate
->as_set
= as_set_new
;
7709 aggregate
->safi
= safi
;
7710 /* Override ORIGIN attribute if defined.
7711 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7712 * to IGP which is not what rfc4271 says.
7713 * This enables the same behavior, optionally.
7715 aggregate
->origin
= origin
;
7718 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7719 route_map_counter_decrement(aggregate
->rmap
.map
);
7720 aggregate
->rmap
.name
=
7721 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7722 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7723 route_map_counter_increment(aggregate
->rmap
.map
);
7727 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7728 route_map_counter_decrement(aggregate
->suppress_map
);
7730 aggregate
->suppress_map_name
=
7731 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7732 aggregate
->suppress_map
=
7733 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7734 route_map_counter_increment(aggregate
->suppress_map
);
7737 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7739 /* Aggregate address insert into BGP routing table. */
7740 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
7746 aggregate_addressv4
, aggregate_addressv4_cmd
,
7747 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7749 "|summary-only$summary_only"
7750 "|route-map WORD$rmap_name"
7751 "|origin <egp|igp|incomplete>$origin_s"
7752 "|matching-MED-only$match_med"
7753 "|suppress-map WORD$suppress_map"
7756 "Configure BGP aggregate entries\n"
7757 "Aggregate prefix\n"
7758 "Aggregate address\n"
7760 "Generate AS set path information\n"
7761 "Filter more specific routes from updates\n"
7762 "Apply route map to aggregate network\n"
7767 "Unknown heritage\n"
7768 "Only aggregate routes with matching MED\n"
7769 "Suppress the selected more specific routes\n"
7770 "Route map with the route selectors\n")
7772 char base_xpath
[XPATH_MAXLEN
];
7773 safi_t safi
= bgp_node_safi(vty
);
7774 char prefix_buf
[PREFIX2STR_BUFFER
];
7777 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
)
7779 vty_out(vty
, "%% Inconsistent address and mask\n");
7780 return CMD_WARNING_CONFIG_FAILED
;
7783 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
7786 if (!no
&& origin_s
)
7787 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7789 if (!no
&& as_set_s
)
7790 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7792 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7794 if (!no
&& summary_only
)
7795 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7798 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7801 if (!no
&& match_med
)
7802 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7804 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7808 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7811 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
7812 NB_OP_DESTROY
, NULL
);
7815 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7818 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7822 base_xpath
, sizeof(base_xpath
),
7823 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7824 yang_afi_safi_value2identity(AFI_IP
, safi
),
7825 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
7828 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7830 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7832 return nb_cli_apply_changes(vty
, base_xpath
);
7835 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
7836 "[no] aggregate-address X:X::X:X/M$prefix {"
7838 "|summary-only$summary_only"
7839 "|route-map WORD$rmap_name"
7840 "|origin <egp|igp|incomplete>$origin_s"
7841 "|matching-MED-only$match_med"
7842 "|suppress-map WORD$suppress_map"
7845 "Configure BGP aggregate entries\n"
7846 "Aggregate prefix\n"
7847 "Generate AS set path information\n"
7848 "Filter more specific routes from updates\n"
7849 "Apply route map to aggregate network\n"
7854 "Unknown heritage\n"
7855 "Only aggregate routes with matching MED\n"
7856 "Suppress the selected more specific routes\n"
7857 "Route map with the route selectors\n")
7859 char base_xpath
[XPATH_MAXLEN
];
7860 safi_t safi
= bgp_node_safi(vty
);
7862 if (!no
&& origin_s
)
7863 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7865 if (!no
&& as_set_s
)
7866 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7868 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7870 if (!no
&& summary_only
)
7871 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7874 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7877 if (!no
&& match_med
)
7878 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7880 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7884 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7888 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7891 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7895 base_xpath
, sizeof(base_xpath
),
7896 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7897 yang_afi_safi_value2identity(AFI_IP6
, safi
),
7898 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
7901 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7903 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7905 return nb_cli_apply_changes(vty
, base_xpath
);
7908 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7909 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
7913 vty_out(vty
, " aggregate-address %s",
7914 yang_dnode_get_string(dnode
, "./prefix"));
7916 if (yang_dnode_get_bool(dnode
, "./as-set"))
7917 vty_out(vty
, " as-set");
7919 if (yang_dnode_get_bool(dnode
, "./summary-only"))
7920 vty_out(vty
, " summary-only");
7922 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
7923 vty_out(vty
, " route-map %s",
7924 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
7926 origin
= yang_dnode_get_enum(dnode
, "./origin");
7927 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
7928 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
7930 if (yang_dnode_get_bool(dnode
, "./match-med"))
7931 vty_out(vty
, " matching-MED-only");
7936 /* Redistribute route treatment. */
7937 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7938 const union g_addr
*nexthop
, ifindex_t ifindex
,
7939 enum nexthop_types_t nhtype
, uint32_t metric
,
7940 uint8_t type
, unsigned short instance
,
7943 struct bgp_path_info
*new;
7944 struct bgp_path_info
*bpi
;
7945 struct bgp_path_info rmap_path
;
7946 struct bgp_dest
*bn
;
7948 struct attr
*new_attr
;
7950 route_map_result_t ret
;
7951 struct bgp_redist
*red
;
7953 /* Make default attribute. */
7954 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7956 * This must not be NULL to satisfy Coverity SA
7958 assert(attr
.aspath
);
7961 case NEXTHOP_TYPE_IFINDEX
:
7963 case NEXTHOP_TYPE_IPV4
:
7964 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7965 attr
.nexthop
= nexthop
->ipv4
;
7967 case NEXTHOP_TYPE_IPV6
:
7968 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7969 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7970 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7972 case NEXTHOP_TYPE_BLACKHOLE
:
7973 switch (p
->family
) {
7975 attr
.nexthop
.s_addr
= INADDR_ANY
;
7978 memset(&attr
.mp_nexthop_global
, 0,
7979 sizeof(attr
.mp_nexthop_global
));
7980 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7985 attr
.nh_ifindex
= ifindex
;
7988 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7991 afi
= family2afi(p
->family
);
7993 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7995 struct attr attr_new
;
7997 /* Copy attribute for modification. */
8000 if (red
->redist_metric_flag
)
8001 attr_new
.med
= red
->redist_metric
;
8003 /* Apply route-map. */
8004 if (red
->rmap
.name
) {
8005 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8006 rmap_path
.peer
= bgp
->peer_self
;
8007 rmap_path
.attr
= &attr_new
;
8009 SET_FLAG(bgp
->peer_self
->rmap_type
,
8010 PEER_RMAP_TYPE_REDISTRIBUTE
);
8012 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8014 bgp
->peer_self
->rmap_type
= 0;
8016 if (ret
== RMAP_DENYMATCH
) {
8017 /* Free uninterned attribute. */
8018 bgp_attr_flush(&attr_new
);
8020 /* Unintern original. */
8021 aspath_unintern(&attr
.aspath
);
8022 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8027 if (bgp_in_graceful_shutdown(bgp
))
8028 bgp_attr_add_gshut_community(&attr_new
);
8030 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8031 SAFI_UNICAST
, p
, NULL
);
8033 new_attr
= bgp_attr_intern(&attr_new
);
8035 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8036 if (bpi
->peer
== bgp
->peer_self
8037 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8041 /* Ensure the (source route) type is updated. */
8043 if (attrhash_cmp(bpi
->attr
, new_attr
)
8044 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8045 bgp_attr_unintern(&new_attr
);
8046 aspath_unintern(&attr
.aspath
);
8047 bgp_dest_unlock_node(bn
);
8050 /* The attribute is changed. */
8051 bgp_path_info_set_flag(bn
, bpi
,
8052 BGP_PATH_ATTR_CHANGED
);
8054 /* Rewrite BGP route information. */
8055 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8056 bgp_path_info_restore(bn
, bpi
);
8058 bgp_aggregate_decrement(
8059 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8060 bgp_attr_unintern(&bpi
->attr
);
8061 bpi
->attr
= new_attr
;
8062 bpi
->uptime
= bgp_clock();
8064 /* Process change. */
8065 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8067 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8068 bgp_dest_unlock_node(bn
);
8069 aspath_unintern(&attr
.aspath
);
8071 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8073 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8075 vpn_leak_from_vrf_update(
8076 bgp_get_default(), bgp
, bpi
);
8082 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8083 bgp
->peer_self
, new_attr
, bn
);
8084 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8086 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8087 bgp_path_info_add(bn
, new);
8088 bgp_dest_unlock_node(bn
);
8089 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8091 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8092 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8094 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8098 /* Unintern original. */
8099 aspath_unintern(&attr
.aspath
);
8102 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8103 unsigned short instance
)
8106 struct bgp_dest
*dest
;
8107 struct bgp_path_info
*pi
;
8108 struct bgp_redist
*red
;
8110 afi
= family2afi(p
->family
);
8112 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8114 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8115 SAFI_UNICAST
, p
, NULL
);
8117 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8118 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8122 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8123 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8125 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8128 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8129 bgp_path_info_delete(dest
, pi
);
8130 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8132 bgp_dest_unlock_node(dest
);
8136 /* Withdraw specified route type's route. */
8137 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8138 unsigned short instance
)
8140 struct bgp_dest
*dest
;
8141 struct bgp_path_info
*pi
;
8142 struct bgp_table
*table
;
8144 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8146 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8147 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8148 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8149 && pi
->instance
== instance
)
8153 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8154 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8156 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8159 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8160 pi
, afi
, SAFI_UNICAST
);
8161 bgp_path_info_delete(dest
, pi
);
8162 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8167 /* Static function to display route. */
8168 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
8169 json_object
*json
, bool wide
)
8175 if (p
->family
== AF_INET
) {
8177 len
= vty_out(vty
, "%pFX", p
);
8179 json_object_string_add(json
, "prefix",
8180 inet_ntop(p
->family
,
8183 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8184 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8185 json_object_string_add(json
, "network", buf2
);
8187 } else if (p
->family
== AF_ETHERNET
) {
8188 len
= vty_out(vty
, "%pFX", p
);
8189 } else if (p
->family
== AF_EVPN
) {
8191 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8193 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8194 } else if (p
->family
== AF_FLOWSPEC
) {
8195 route_vty_out_flowspec(vty
, p
, NULL
,
8197 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8198 NLRI_STRING_FORMAT_MIN
, json
);
8201 len
= vty_out(vty
, "%pFX", p
);
8203 json_object_string_add(json
, "prefix",
8204 inet_ntop(p
->family
,
8207 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8208 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8209 json_object_string_add(json
, "network", buf2
);
8214 len
= wide
? (45 - len
) : (17 - len
);
8216 vty_out(vty
, "\n%*s", 20, " ");
8218 vty_out(vty
, "%*s", len
, " ");
8222 enum bgp_display_type
{
8227 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8230 case bgp_path_selection_none
:
8231 return "Nothing to Select";
8232 case bgp_path_selection_first
:
8233 return "First path received";
8234 case bgp_path_selection_evpn_sticky_mac
:
8235 return "EVPN Sticky Mac";
8236 case bgp_path_selection_evpn_seq
:
8237 return "EVPN sequence number";
8238 case bgp_path_selection_evpn_lower_ip
:
8239 return "EVPN lower IP";
8240 case bgp_path_selection_evpn_local_path
:
8241 return "EVPN local ES path";
8242 case bgp_path_selection_evpn_non_proxy
:
8243 return "EVPN non proxy";
8244 case bgp_path_selection_weight
:
8246 case bgp_path_selection_local_pref
:
8247 return "Local Pref";
8248 case bgp_path_selection_local_route
:
8249 return "Local Route";
8250 case bgp_path_selection_confed_as_path
:
8251 return "Confederation based AS Path";
8252 case bgp_path_selection_as_path
:
8254 case bgp_path_selection_origin
:
8256 case bgp_path_selection_med
:
8258 case bgp_path_selection_peer
:
8260 case bgp_path_selection_confed
:
8261 return "Confed Peer Type";
8262 case bgp_path_selection_igp_metric
:
8263 return "IGP Metric";
8264 case bgp_path_selection_older
:
8265 return "Older Path";
8266 case bgp_path_selection_router_id
:
8268 case bgp_path_selection_cluster_length
:
8269 return "Cluser length";
8270 case bgp_path_selection_stale
:
8271 return "Path Staleness";
8272 case bgp_path_selection_local_configured
:
8273 return "Locally configured route";
8274 case bgp_path_selection_neighbor_ip
:
8275 return "Neighbor IP";
8276 case bgp_path_selection_default
:
8277 return "Nothing left to compare";
8279 return "Invalid (internal error)";
8282 /* Print the short form route status for a bgp_path_info */
8283 static void route_vty_short_status_out(struct vty
*vty
,
8284 struct bgp_path_info
*path
,
8285 json_object
*json_path
)
8289 /* Route status display. */
8290 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8291 json_object_boolean_true_add(json_path
, "removed");
8293 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8294 json_object_boolean_true_add(json_path
, "stale");
8296 if (path
->extra
&& bgp_path_suppressed(path
))
8297 json_object_boolean_true_add(json_path
, "suppressed");
8299 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8300 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8301 json_object_boolean_true_add(json_path
, "valid");
8304 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8305 json_object_boolean_true_add(json_path
, "history");
8307 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8308 json_object_boolean_true_add(json_path
, "damped");
8310 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8311 json_object_boolean_true_add(json_path
, "bestpath");
8312 json_object_string_add(json_path
, "selectionReason",
8313 bgp_path_selection_reason2str(
8314 path
->net
->reason
));
8317 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8318 json_object_boolean_true_add(json_path
, "multipath");
8320 /* Internal route. */
8321 if ((path
->peer
->as
)
8322 && (path
->peer
->as
== path
->peer
->local_as
))
8323 json_object_string_add(json_path
, "pathFrom",
8326 json_object_string_add(json_path
, "pathFrom",
8332 /* Route status display. */
8333 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8335 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8337 else if (bgp_path_suppressed(path
))
8339 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8340 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8346 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8348 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8350 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8352 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8357 /* Internal route. */
8358 if (path
->peer
&& (path
->peer
->as
)
8359 && (path
->peer
->as
== path
->peer
->local_as
))
8365 static char *bgp_nexthop_hostname(struct peer
*peer
,
8366 struct bgp_nexthop_cache
*bnc
)
8369 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8370 return peer
->hostname
;
8374 /* called from terminal list command */
8375 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8376 struct bgp_path_info
*path
, int display
, safi_t safi
,
8377 json_object
*json_paths
, bool wide
)
8380 struct attr
*attr
= path
->attr
;
8381 json_object
*json_path
= NULL
;
8382 json_object
*json_nexthops
= NULL
;
8383 json_object
*json_nexthop_global
= NULL
;
8384 json_object
*json_nexthop_ll
= NULL
;
8385 json_object
*json_ext_community
= NULL
;
8386 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8388 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8389 bool nexthop_othervrf
= false;
8390 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8391 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8392 char *nexthop_hostname
=
8393 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8394 char esi_buf
[ESI_STR_LEN
];
8397 json_path
= json_object_new_object();
8399 /* short status lead text */
8400 route_vty_short_status_out(vty
, path
, json_path
);
8403 /* print prefix and mask */
8405 route_vty_out_route(p
, vty
, json_path
, wide
);
8407 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8409 route_vty_out_route(p
, vty
, json_path
, wide
);
8413 * If vrf id of nexthop is different from that of prefix,
8414 * set up printable string to append
8416 if (path
->extra
&& path
->extra
->bgp_orig
) {
8417 const char *self
= "";
8422 nexthop_othervrf
= true;
8423 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8425 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8426 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8427 "@%s%s", VRFID_NONE_STR
, self
);
8429 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8430 path
->extra
->bgp_orig
->vrf_id
, self
);
8432 if (path
->extra
->bgp_orig
->inst_type
8433 != BGP_INSTANCE_TYPE_DEFAULT
)
8435 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8437 const char *self
= "";
8442 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8446 * For ENCAP and EVPN routes, nexthop address family is not
8447 * neccessarily the same as the prefix address family.
8448 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8449 * EVPN routes are also exchanged with a MP nexthop. Currently,
8451 * is only IPv4, the value will be present in either
8453 * attr->mp_nexthop_global_in
8455 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8458 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8462 snprintf(nexthop
, sizeof(nexthop
), "%s",
8463 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8467 snprintf(nexthop
, sizeof(nexthop
), "%s",
8468 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8472 snprintf(nexthop
, sizeof(nexthop
), "?");
8477 json_nexthop_global
= json_object_new_object();
8479 json_object_string_add(json_nexthop_global
, "ip",
8482 if (path
->peer
->hostname
)
8483 json_object_string_add(json_nexthop_global
,
8485 path
->peer
->hostname
);
8487 json_object_string_add(json_nexthop_global
, "afi",
8488 (af
== AF_INET
) ? "ipv4"
8490 json_object_boolean_true_add(json_nexthop_global
,
8493 if (nexthop_hostname
)
8494 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8495 nexthop_hostname
, vrf_id_str
);
8497 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8499 len
= wide
? (41 - len
) : (16 - len
);
8501 vty_out(vty
, "\n%*s", 36, " ");
8503 vty_out(vty
, "%*s", len
, " ");
8505 } else if (safi
== SAFI_EVPN
) {
8507 char buf
[BUFSIZ
] = {0};
8509 json_nexthop_global
= json_object_new_object();
8511 json_object_string_add(json_nexthop_global
, "ip",
8513 &attr
->nexthop
, buf
,
8516 if (path
->peer
->hostname
)
8517 json_object_string_add(json_nexthop_global
,
8519 path
->peer
->hostname
);
8521 json_object_string_add(json_nexthop_global
, "afi",
8523 json_object_boolean_true_add(json_nexthop_global
,
8526 if (nexthop_hostname
)
8527 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8528 nexthop_hostname
, vrf_id_str
);
8530 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8533 len
= wide
? (41 - len
) : (16 - len
);
8535 vty_out(vty
, "\n%*s", 36, " ");
8537 vty_out(vty
, "%*s", len
, " ");
8539 } else if (safi
== SAFI_FLOWSPEC
) {
8540 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8542 char buf
[BUFSIZ
] = {0};
8544 json_nexthop_global
= json_object_new_object();
8546 json_object_string_add(json_nexthop_global
,
8548 json_object_string_add(
8549 json_nexthop_global
, "ip",
8550 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8553 if (path
->peer
->hostname
)
8554 json_object_string_add(
8555 json_nexthop_global
, "hostname",
8556 path
->peer
->hostname
);
8558 json_object_boolean_true_add(
8559 json_nexthop_global
,
8562 if (nexthop_hostname
)
8563 len
= vty_out(vty
, "%pI4(%s)%s",
8568 len
= vty_out(vty
, "%pI4%s",
8572 len
= wide
? (41 - len
) : (16 - len
);
8574 vty_out(vty
, "\n%*s", 36, " ");
8576 vty_out(vty
, "%*s", len
, " ");
8579 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8581 char buf
[BUFSIZ
] = {0};
8583 json_nexthop_global
= json_object_new_object();
8585 json_object_string_add(json_nexthop_global
, "ip",
8587 &attr
->nexthop
, buf
,
8590 if (path
->peer
->hostname
)
8591 json_object_string_add(json_nexthop_global
,
8593 path
->peer
->hostname
);
8595 json_object_string_add(json_nexthop_global
, "afi",
8597 json_object_boolean_true_add(json_nexthop_global
,
8600 if (nexthop_hostname
)
8601 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8602 nexthop_hostname
, vrf_id_str
);
8604 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8607 len
= wide
? (41 - len
) : (16 - len
);
8609 vty_out(vty
, "\n%*s", 36, " ");
8611 vty_out(vty
, "%*s", len
, " ");
8616 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8620 json_nexthop_global
= json_object_new_object();
8621 json_object_string_add(
8622 json_nexthop_global
, "ip",
8623 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8626 if (path
->peer
->hostname
)
8627 json_object_string_add(json_nexthop_global
,
8629 path
->peer
->hostname
);
8631 json_object_string_add(json_nexthop_global
, "afi",
8633 json_object_string_add(json_nexthop_global
, "scope",
8636 /* We display both LL & GL if both have been
8638 if ((attr
->mp_nexthop_len
8639 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8640 || (path
->peer
->conf_if
)) {
8641 json_nexthop_ll
= json_object_new_object();
8642 json_object_string_add(
8643 json_nexthop_ll
, "ip",
8645 &attr
->mp_nexthop_local
, buf
,
8648 if (path
->peer
->hostname
)
8649 json_object_string_add(
8650 json_nexthop_ll
, "hostname",
8651 path
->peer
->hostname
);
8653 json_object_string_add(json_nexthop_ll
, "afi",
8655 json_object_string_add(json_nexthop_ll
, "scope",
8658 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8659 &attr
->mp_nexthop_local
)
8661 && !attr
->mp_nexthop_prefer_global
)
8662 json_object_boolean_true_add(
8663 json_nexthop_ll
, "used");
8665 json_object_boolean_true_add(
8666 json_nexthop_global
, "used");
8668 json_object_boolean_true_add(
8669 json_nexthop_global
, "used");
8671 /* Display LL if LL/Global both in table unless
8672 * prefer-global is set */
8673 if (((attr
->mp_nexthop_len
8674 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8675 && !attr
->mp_nexthop_prefer_global
)
8676 || (path
->peer
->conf_if
)) {
8677 if (path
->peer
->conf_if
) {
8678 len
= vty_out(vty
, "%s",
8679 path
->peer
->conf_if
);
8680 /* len of IPv6 addr + max len of def
8682 len
= wide
? (41 - len
) : (16 - len
);
8685 vty_out(vty
, "\n%*s", 36, " ");
8687 vty_out(vty
, "%*s", len
, " ");
8689 if (nexthop_hostname
)
8692 &attr
->mp_nexthop_local
,
8698 &attr
->mp_nexthop_local
,
8701 len
= wide
? (41 - len
) : (16 - len
);
8704 vty_out(vty
, "\n%*s", 36, " ");
8706 vty_out(vty
, "%*s", len
, " ");
8709 if (nexthop_hostname
)
8710 len
= vty_out(vty
, "%pI6(%s)%s",
8711 &attr
->mp_nexthop_global
,
8715 len
= vty_out(vty
, "%pI6%s",
8716 &attr
->mp_nexthop_global
,
8719 len
= wide
? (41 - len
) : (16 - len
);
8722 vty_out(vty
, "\n%*s", 36, " ");
8724 vty_out(vty
, "%*s", len
, " ");
8730 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8732 json_object_int_add(json_path
, "metric", attr
->med
);
8734 vty_out(vty
, "%7u", attr
->med
);
8736 vty_out(vty
, "%10u", attr
->med
);
8737 else if (!json_paths
) {
8739 vty_out(vty
, "%*s", 7, " ");
8741 vty_out(vty
, "%*s", 10, " ");
8745 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8747 json_object_int_add(json_path
, "locPrf",
8750 vty_out(vty
, "%7u", attr
->local_pref
);
8751 else if (!json_paths
)
8755 json_object_int_add(json_path
, "weight", attr
->weight
);
8757 vty_out(vty
, "%7u ", attr
->weight
);
8761 json_object_string_add(
8762 json_path
, "peerId",
8763 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8769 json_object_string_add(json_path
, "path",
8772 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8777 json_object_string_add(json_path
, "origin",
8778 bgp_origin_long_str
[attr
->origin
]);
8780 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8783 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8784 json_object_string_add(json_path
, "esi",
8785 esi_to_str(&attr
->esi
,
8786 esi_buf
, sizeof(esi_buf
)));
8788 if (safi
== SAFI_EVPN
&&
8789 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8790 json_ext_community
= json_object_new_object();
8791 json_object_string_add(json_ext_community
,
8793 attr
->ecommunity
->str
);
8794 json_object_object_add(json_path
,
8795 "extendedCommunity",
8796 json_ext_community
);
8800 json_object_boolean_true_add(json_path
,
8801 "announceNexthopSelf");
8802 if (nexthop_othervrf
) {
8803 json_object_string_add(json_path
, "nhVrfName",
8806 json_object_int_add(json_path
, "nhVrfId",
8807 ((nexthop_vrfid
== VRF_UNKNOWN
)
8809 : (int)nexthop_vrfid
));
8814 if (json_nexthop_global
|| json_nexthop_ll
) {
8815 json_nexthops
= json_object_new_array();
8817 if (json_nexthop_global
)
8818 json_object_array_add(json_nexthops
,
8819 json_nexthop_global
);
8821 if (json_nexthop_ll
)
8822 json_object_array_add(json_nexthops
,
8825 json_object_object_add(json_path
, "nexthops",
8829 json_object_array_add(json_paths
, json_path
);
8833 if (safi
== SAFI_EVPN
) {
8834 struct bgp_path_es_info
*path_es_info
= NULL
;
8837 path_es_info
= path
->extra
->es_info
;
8839 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8840 /* XXX - add these params to the json out */
8841 vty_out(vty
, "%*s", 20, " ");
8842 vty_out(vty
, "ESI:%s",
8843 esi_to_str(&attr
->esi
, esi_buf
,
8845 if (path_es_info
&& path_es_info
->es
)
8846 vty_out(vty
, " VNI: %u",
8851 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8852 vty_out(vty
, "%*s", 20, " ");
8853 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8857 #ifdef ENABLE_BGP_VNC
8858 /* prints an additional line, indented, with VNC info, if
8860 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8861 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8866 /* called from terminal list command */
8867 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8868 struct attr
*attr
, safi_t safi
, bool use_json
,
8869 json_object
*json_ar
, bool wide
)
8871 json_object
*json_status
= NULL
;
8872 json_object
*json_net
= NULL
;
8876 /* Route status display. */
8878 json_status
= json_object_new_object();
8879 json_net
= json_object_new_object();
8886 /* print prefix and mask */
8888 if (safi
== SAFI_EVPN
)
8889 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8890 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8891 json_object_string_add(
8892 json_net
, "addrPrefix",
8893 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8895 json_object_int_add(json_net
, "prefixLen",
8897 prefix2str(p
, buff
, PREFIX_STRLEN
);
8898 json_object_string_add(json_net
, "network", buff
);
8901 route_vty_out_route(p
, vty
, NULL
, wide
);
8903 /* Print attribute */
8906 char buf
[BUFSIZ
] = {0};
8908 if (p
->family
== AF_INET
8909 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8910 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8911 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8912 json_object_string_add(
8913 json_net
, "nextHop",
8916 &attr
->mp_nexthop_global_in
,
8919 json_object_string_add(
8920 json_net
, "nextHop",
8922 &attr
->nexthop
, buf
,
8924 } else if (p
->family
== AF_INET6
8925 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8928 json_object_string_add(
8929 json_net
, "nextHopGlobal",
8931 &attr
->mp_nexthop_global
, buf
,
8933 } else if (p
->family
== AF_EVPN
8934 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8935 char buf
[BUFSIZ
] = {0};
8937 json_object_string_add(
8938 json_net
, "nextHop",
8940 &attr
->mp_nexthop_global_in
,
8945 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8946 json_object_int_add(json_net
, "metric",
8949 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8950 json_object_int_add(json_net
, "locPrf",
8953 json_object_int_add(json_net
, "weight", attr
->weight
);
8957 json_object_string_add(json_net
, "path",
8961 json_object_string_add(json_net
, "bgpOriginCode",
8962 bgp_origin_str
[attr
->origin
]);
8964 if (p
->family
== AF_INET
8965 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8966 || safi
== SAFI_EVPN
8967 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8968 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8969 || safi
== SAFI_EVPN
)
8970 vty_out(vty
, "%-16pI4",
8971 &attr
->mp_nexthop_global_in
);
8973 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
8975 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
8976 } else if (p
->family
== AF_INET6
8977 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8983 &attr
->mp_nexthop_global
, buf
,
8985 len
= wide
? (41 - len
) : (16 - len
);
8987 vty_out(vty
, "\n%*s", 36, " ");
8989 vty_out(vty
, "%*s", len
, " ");
8992 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8994 vty_out(vty
, "%7u", attr
->med
);
8996 vty_out(vty
, "%10u", attr
->med
);
9002 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9003 vty_out(vty
, "%7u", attr
->local_pref
);
9007 vty_out(vty
, "%7u ", attr
->weight
);
9011 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9014 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9018 json_object_boolean_true_add(json_status
, "*");
9019 json_object_boolean_true_add(json_status
, ">");
9020 json_object_object_add(json_net
, "appliedStatusSymbols",
9023 prefix2str(p
, buff
, PREFIX_STRLEN
);
9024 json_object_object_add(json_ar
, buff
, json_net
);
9029 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9030 struct bgp_path_info
*path
, int display
, safi_t safi
,
9033 json_object
*json_out
= NULL
;
9035 mpls_label_t label
= MPLS_INVALID_LABEL
;
9041 json_out
= json_object_new_object();
9043 /* short status lead text */
9044 route_vty_short_status_out(vty
, path
, json_out
);
9046 /* print prefix and mask */
9049 route_vty_out_route(p
, vty
, NULL
, false);
9051 vty_out(vty
, "%*s", 17, " ");
9054 /* Print attribute */
9056 if (((p
->family
== AF_INET
)
9057 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9058 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9059 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9060 char buf
[BUFSIZ
] = {0};
9062 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9063 || safi
== SAFI_EVPN
) {
9065 json_object_string_add(
9066 json_out
, "mpNexthopGlobalIn",
9068 &attr
->mp_nexthop_global_in
,
9071 vty_out(vty
, "%-16pI4",
9072 &attr
->mp_nexthop_global_in
);
9075 json_object_string_add(
9076 json_out
, "nexthop",
9077 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9080 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9082 } else if (((p
->family
== AF_INET6
)
9083 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9084 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9085 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9088 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9090 json_object_string_add(
9091 json_out
, "mpNexthopGlobalIn",
9093 &attr
->mp_nexthop_global
,
9094 buf_a
, sizeof(buf_a
)));
9098 &attr
->mp_nexthop_global
,
9099 buf_a
, sizeof(buf_a
)));
9100 } else if (attr
->mp_nexthop_len
9101 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9102 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9103 &attr
->mp_nexthop_global
,
9104 &attr
->mp_nexthop_local
);
9106 json_object_string_add(json_out
,
9107 "mpNexthopGlobalLocal",
9110 vty_out(vty
, "%s", buf_a
);
9114 label
= decode_label(&path
->extra
->label
[0]);
9116 if (bgp_is_valid_label(&label
)) {
9118 json_object_int_add(json_out
, "notag", label
);
9119 json_object_array_add(json
, json_out
);
9121 vty_out(vty
, "notag/%d", label
);
9127 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9128 struct bgp_path_info
*path
, int display
,
9129 json_object
*json_paths
)
9132 char buf
[BUFSIZ
] = {0};
9133 json_object
*json_path
= NULL
;
9134 json_object
*json_nexthop
= NULL
;
9135 json_object
*json_overlay
= NULL
;
9141 json_path
= json_object_new_object();
9142 json_overlay
= json_object_new_object();
9143 json_nexthop
= json_object_new_object();
9146 /* short status lead text */
9147 route_vty_short_status_out(vty
, path
, json_path
);
9149 /* print prefix and mask */
9151 route_vty_out_route(p
, vty
, json_path
, false);
9153 vty_out(vty
, "%*s", 17, " ");
9155 /* Print attribute */
9158 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9162 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9164 vty_out(vty
, "%-16s", buf
);
9166 json_object_string_add(json_nexthop
, "ip", buf
);
9168 json_object_string_add(json_nexthop
, "afi", "ipv4");
9170 json_object_object_add(json_path
, "nexthop",
9175 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9176 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9178 vty_out(vty
, "%s(%s)", buf
, buf1
);
9180 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9182 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9185 json_object_string_add(json_nexthop
, "afi", "ipv6");
9187 json_object_object_add(json_path
, "nexthop",
9195 json_object_string_add(json_nexthop
, "Error",
9196 "Unsupported address-family");
9200 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9202 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9203 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9204 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9205 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9208 vty_out(vty
, "/%s", buf
);
9210 json_object_string_add(json_overlay
, "gw", buf
);
9212 if (attr
->ecommunity
) {
9214 struct ecommunity_val
*routermac
= ecommunity_lookup(
9215 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9216 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9219 mac
= ecom_mac2str((char *)routermac
->val
);
9222 vty_out(vty
, "/%s", mac
);
9224 json_object_string_add(json_overlay
, "rmac",
9227 XFREE(MTYPE_TMP
, mac
);
9234 json_object_object_add(json_path
, "overlay", json_overlay
);
9236 json_object_array_add(json_paths
, json_path
);
9240 /* dampening route */
9241 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9242 struct bgp_path_info
*path
, int display
,
9243 afi_t afi
, safi_t safi
, bool use_json
,
9248 char timebuf
[BGP_UPTIME_LEN
];
9250 /* short status lead text */
9251 route_vty_short_status_out(vty
, path
, json
);
9253 /* print prefix and mask */
9256 route_vty_out_route(p
, vty
, NULL
, false);
9258 vty_out(vty
, "%*s", 17, " ");
9261 len
= vty_out(vty
, "%s", path
->peer
->host
);
9265 vty_out(vty
, "\n%*s", 34, " ");
9268 json_object_int_add(json
, "peerHost", len
);
9270 vty_out(vty
, "%*s", len
, " ");
9274 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9275 safi
, use_json
, json
);
9278 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9279 BGP_UPTIME_LEN
, afi
, safi
,
9282 /* Print attribute */
9288 json_object_string_add(json
, "asPath",
9291 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9296 json_object_string_add(json
, "origin",
9297 bgp_origin_str
[attr
->origin
]);
9299 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9306 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9307 struct bgp_path_info
*path
, int display
,
9308 afi_t afi
, safi_t safi
, bool use_json
,
9312 struct bgp_damp_info
*bdi
;
9313 char timebuf
[BGP_UPTIME_LEN
];
9319 bdi
= path
->extra
->damp_info
;
9321 /* short status lead text */
9322 route_vty_short_status_out(vty
, path
, json
);
9324 /* print prefix and mask */
9327 route_vty_out_route(p
, vty
, NULL
, false);
9329 vty_out(vty
, "%*s", 17, " ");
9332 len
= vty_out(vty
, "%s", path
->peer
->host
);
9336 vty_out(vty
, "\n%*s", 33, " ");
9339 json_object_int_add(json
, "peerHost", len
);
9341 vty_out(vty
, "%*s", len
, " ");
9344 len
= vty_out(vty
, "%d", bdi
->flap
);
9351 json_object_int_add(json
, "bdiFlap", len
);
9353 vty_out(vty
, "%*s", len
, " ");
9357 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9360 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9361 BGP_UPTIME_LEN
, 0, NULL
));
9363 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9364 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9366 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9367 BGP_UPTIME_LEN
, afi
, safi
,
9371 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9372 BGP_UPTIME_LEN
, afi
,
9373 safi
, use_json
, json
));
9376 vty_out(vty
, "%*s ", 8, " ");
9379 /* Print attribute */
9385 json_object_string_add(json
, "asPath",
9388 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9393 json_object_string_add(json
, "origin",
9394 bgp_origin_str
[attr
->origin
]);
9396 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9402 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9403 int *first
, const char *header
,
9404 json_object
*json_adv_to
)
9406 char buf1
[INET6_ADDRSTRLEN
];
9407 json_object
*json_peer
= NULL
;
9410 /* 'advertised-to' is a dictionary of peers we have advertised
9412 * prefix too. The key is the peer's IP or swpX, the value is
9414 * hostname if we know it and "" if not.
9416 json_peer
= json_object_new_object();
9419 json_object_string_add(json_peer
, "hostname",
9423 json_object_object_add(json_adv_to
, peer
->conf_if
,
9426 json_object_object_add(
9428 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9432 vty_out(vty
, "%s", header
);
9437 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9439 vty_out(vty
, " %s(%s)", peer
->hostname
,
9442 vty_out(vty
, " %s(%s)", peer
->hostname
,
9443 sockunion2str(&peer
->su
, buf1
,
9447 vty_out(vty
, " %s", peer
->conf_if
);
9450 sockunion2str(&peer
->su
, buf1
,
9456 static void route_vty_out_tx_ids(struct vty
*vty
,
9457 struct bgp_addpath_info_data
*d
)
9461 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9462 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9463 d
->addpath_tx_id
[i
],
9464 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9468 static void route_vty_out_detail_es_info(struct vty
*vty
,
9469 struct bgp_path_info
*pi
,
9471 json_object
*json_path
)
9473 char esi_buf
[ESI_STR_LEN
];
9474 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9475 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9476 ATTR_ES_PEER_ROUTER
);
9477 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9478 ATTR_ES_PEER_ACTIVE
);
9479 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9480 ATTR_ES_PEER_PROXY
);
9481 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9483 json_object
*json_es_info
= NULL
;
9485 json_object_string_add(
9488 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9489 json_es_info
= json_object_new_object();
9491 json_object_boolean_true_add(
9492 json_es_info
, "localEs");
9494 json_object_boolean_true_add(
9495 json_es_info
, "peerActive");
9497 json_object_boolean_true_add(
9498 json_es_info
, "peerProxy");
9500 json_object_boolean_true_add(
9501 json_es_info
, "peerRouter");
9502 if (attr
->mm_sync_seqnum
)
9503 json_object_int_add(
9504 json_es_info
, "peerSeq",
9505 attr
->mm_sync_seqnum
);
9506 json_object_object_add(
9507 json_path
, "es_info",
9511 if (bgp_evpn_attr_is_sync(attr
))
9513 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9515 es_local
? "local-es":"",
9516 peer_proxy
? "proxy " : "",
9517 peer_active
? "active ":"",
9518 peer_router
? "router ":"",
9519 attr
->mm_sync_seqnum
);
9521 vty_out(vty
, " ESI %s %s\n",
9523 es_local
? "local-es":"");
9527 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
9528 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
9529 afi_t afi
, safi_t safi
, json_object
*json_paths
)
9531 char buf
[INET6_ADDRSTRLEN
];
9533 struct attr
*attr
= path
->attr
;
9534 int sockunion_vty_out(struct vty
*, union sockunion
*);
9536 json_object
*json_bestpath
= NULL
;
9537 json_object
*json_cluster_list
= NULL
;
9538 json_object
*json_cluster_list_list
= NULL
;
9539 json_object
*json_ext_community
= NULL
;
9540 json_object
*json_last_update
= NULL
;
9541 json_object
*json_pmsi
= NULL
;
9542 json_object
*json_nexthop_global
= NULL
;
9543 json_object
*json_nexthop_ll
= NULL
;
9544 json_object
*json_nexthops
= NULL
;
9545 json_object
*json_path
= NULL
;
9546 json_object
*json_peer
= NULL
;
9547 json_object
*json_string
= NULL
;
9548 json_object
*json_adv_to
= NULL
;
9550 struct listnode
*node
, *nnode
;
9552 int addpath_capable
;
9554 unsigned int first_as
;
9556 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9558 char *nexthop_hostname
=
9559 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9562 json_path
= json_object_new_object();
9563 json_peer
= json_object_new_object();
9564 json_nexthop_global
= json_object_new_object();
9571 if (path
->extra
&& path
->extra
->num_labels
) {
9572 bgp_evpn_label2str(path
->extra
->label
,
9573 path
->extra
->num_labels
, tag_buf
,
9576 if (safi
== SAFI_EVPN
) {
9578 vty_out(vty
, " Route %pFX",
9579 (struct prefix_evpn
*)
9580 bgp_dest_get_prefix(bn
));
9581 if (tag_buf
[0] != '\0')
9582 vty_out(vty
, " VNI %s", tag_buf
);
9586 json_object_string_add(json_path
, "VNI",
9591 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9592 struct bgp_path_info
*parent_ri
;
9593 struct bgp_dest
*dest
, *pdest
;
9595 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9596 dest
= parent_ri
->net
;
9597 if (dest
&& dest
->pdest
) {
9598 pdest
= dest
->pdest
;
9600 (struct prefix_rd
*)bgp_dest_get_prefix(
9602 buf1
, sizeof(buf1
));
9603 if (is_pi_family_evpn(parent_ri
)) {
9605 " Imported from %s:%pFX, VNI %s\n",
9607 (struct prefix_evpn
*)
9608 bgp_dest_get_prefix(
9613 " Imported from %s:%pFX\n",
9615 (struct prefix_evpn
*)
9616 bgp_dest_get_prefix(
9622 /* Line1 display AS-path, Aggregator */
9625 if (!attr
->aspath
->json
)
9626 aspath_str_update(attr
->aspath
, true);
9627 json_object_lock(attr
->aspath
->json
);
9628 json_object_object_add(json_path
, "aspath",
9629 attr
->aspath
->json
);
9631 if (attr
->aspath
->segments
)
9632 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9634 vty_out(vty
, " Local");
9638 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9640 json_object_boolean_true_add(json_path
, "removed");
9642 vty_out(vty
, ", (removed)");
9645 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9647 json_object_boolean_true_add(json_path
, "stale");
9649 vty_out(vty
, ", (stale)");
9652 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9654 char buf
[BUFSIZ
] = {0};
9656 json_object_int_add(json_path
, "aggregatorAs",
9657 attr
->aggregator_as
);
9658 json_object_string_add(json_path
, "aggregatorId",
9660 &attr
->aggregator_addr
,
9662 if (attr
->aggregator_as
== BGP_AS_ZERO
)
9663 json_object_boolean_true_add(
9664 json_path
, "aggregatorAsMalformed");
9666 json_object_boolean_false_add(
9667 json_path
, "aggregatorAsMalformed");
9669 if (attr
->aggregator_as
== BGP_AS_ZERO
)
9671 ", (aggregated by %u(malformed) %pI4)",
9672 attr
->aggregator_as
,
9673 &attr
->aggregator_addr
);
9675 vty_out(vty
, ", (aggregated by %u %pI4)",
9676 attr
->aggregator_as
,
9677 &attr
->aggregator_addr
);
9681 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9682 PEER_FLAG_REFLECTOR_CLIENT
)) {
9684 json_object_boolean_true_add(json_path
,
9685 "rxedFromRrClient");
9687 vty_out(vty
, ", (Received from a RR-client)");
9690 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9691 PEER_FLAG_RSERVER_CLIENT
)) {
9693 json_object_boolean_true_add(json_path
,
9694 "rxedFromRsClient");
9696 vty_out(vty
, ", (Received from a RS-client)");
9699 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9701 json_object_boolean_true_add(json_path
,
9702 "dampeningHistoryEntry");
9704 vty_out(vty
, ", (history entry)");
9705 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9707 json_object_boolean_true_add(json_path
,
9708 "dampeningSuppressed");
9710 vty_out(vty
, ", (suppressed due to dampening)");
9716 /* Line2 display Next-hop, Neighbor, Router-id */
9717 /* Display the nexthop */
9718 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9720 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9721 || bn_p
->family
== AF_EVPN
)
9722 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9723 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9724 char buf
[BUFSIZ
] = {0};
9726 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9727 || safi
== SAFI_EVPN
) {
9729 json_object_string_add(
9730 json_nexthop_global
, "ip",
9732 &attr
->mp_nexthop_global_in
,
9735 if (path
->peer
->hostname
)
9736 json_object_string_add(
9737 json_nexthop_global
, "hostname",
9738 path
->peer
->hostname
);
9740 if (nexthop_hostname
)
9741 vty_out(vty
, " %pI4(%s)",
9742 &attr
->mp_nexthop_global_in
,
9745 vty_out(vty
, " %pI4",
9746 &attr
->mp_nexthop_global_in
);
9750 json_object_string_add(
9751 json_nexthop_global
, "ip",
9752 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9755 if (path
->peer
->hostname
)
9756 json_object_string_add(
9757 json_nexthop_global
, "hostname",
9758 path
->peer
->hostname
);
9760 if (nexthop_hostname
)
9761 vty_out(vty
, " %pI4(%s)",
9765 vty_out(vty
, " %pI4",
9771 json_object_string_add(json_nexthop_global
, "afi",
9775 json_object_string_add(
9776 json_nexthop_global
, "ip",
9777 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9778 buf
, INET6_ADDRSTRLEN
));
9780 if (path
->peer
->hostname
)
9781 json_object_string_add(json_nexthop_global
,
9783 path
->peer
->hostname
);
9785 json_object_string_add(json_nexthop_global
, "afi",
9787 json_object_string_add(json_nexthop_global
, "scope",
9790 if (nexthop_hostname
)
9791 vty_out(vty
, " %pI6(%s)",
9792 &attr
->mp_nexthop_global
,
9795 vty_out(vty
, " %pI6",
9796 &attr
->mp_nexthop_global
);
9800 /* Display the IGP cost or 'inaccessible' */
9801 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9803 json_object_boolean_false_add(json_nexthop_global
,
9806 vty_out(vty
, " (inaccessible)");
9808 if (path
->extra
&& path
->extra
->igpmetric
) {
9810 json_object_int_add(json_nexthop_global
,
9812 path
->extra
->igpmetric
);
9814 vty_out(vty
, " (metric %u)",
9815 path
->extra
->igpmetric
);
9818 /* IGP cost is 0, display this only for json */
9821 json_object_int_add(json_nexthop_global
,
9826 json_object_boolean_true_add(json_nexthop_global
,
9830 /* Display peer "from" output */
9831 /* This path was originated locally */
9832 if (path
->peer
== bgp
->peer_self
) {
9834 if (safi
== SAFI_EVPN
9835 || (bn_p
->family
== AF_INET
9836 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9838 json_object_string_add(json_peer
, "peerId",
9841 vty_out(vty
, " from 0.0.0.0 ");
9844 json_object_string_add(json_peer
, "peerId",
9847 vty_out(vty
, " from :: ");
9851 char buf
[BUFSIZ
] = {0};
9853 json_object_string_add(json_peer
, "routerId",
9855 &bgp
->router_id
, buf
,
9858 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
9862 /* We RXed this path from one of our peers */
9866 json_object_string_add(json_peer
, "peerId",
9867 sockunion2str(&path
->peer
->su
,
9870 json_object_string_add(json_peer
, "routerId",
9872 &path
->peer
->remote_id
,
9873 buf1
, sizeof(buf1
)));
9875 if (path
->peer
->hostname
)
9876 json_object_string_add(json_peer
, "hostname",
9877 path
->peer
->hostname
);
9879 if (path
->peer
->domainname
)
9880 json_object_string_add(json_peer
, "domainname",
9881 path
->peer
->domainname
);
9883 if (path
->peer
->conf_if
)
9884 json_object_string_add(json_peer
, "interface",
9885 path
->peer
->conf_if
);
9887 if (path
->peer
->conf_if
) {
9888 if (path
->peer
->hostname
9889 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9890 BGP_FLAG_SHOW_HOSTNAME
))
9891 vty_out(vty
, " from %s(%s)",
9892 path
->peer
->hostname
,
9893 path
->peer
->conf_if
);
9895 vty_out(vty
, " from %s",
9896 path
->peer
->conf_if
);
9898 if (path
->peer
->hostname
9899 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9900 BGP_FLAG_SHOW_HOSTNAME
))
9901 vty_out(vty
, " from %s(%s)",
9902 path
->peer
->hostname
,
9905 vty_out(vty
, " from %s",
9906 sockunion2str(&path
->peer
->su
,
9911 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9912 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
9914 vty_out(vty
, " (%s)",
9916 &path
->peer
->remote_id
, buf1
,
9922 * Note when vrfid of nexthop is different from that of prefix
9924 if (path
->extra
&& path
->extra
->bgp_orig
) {
9925 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9930 if (path
->extra
->bgp_orig
->inst_type
9931 == BGP_INSTANCE_TYPE_DEFAULT
)
9932 vn
= VRF_DEFAULT_NAME
;
9934 vn
= path
->extra
->bgp_orig
->name
;
9936 json_object_string_add(json_path
, "nhVrfName", vn
);
9938 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9939 json_object_int_add(json_path
, "nhVrfId", -1);
9941 json_object_int_add(json_path
, "nhVrfId",
9942 (int)nexthop_vrfid
);
9945 if (nexthop_vrfid
== VRF_UNKNOWN
)
9946 vty_out(vty
, " vrf ?");
9950 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9951 vty_out(vty
, " vrf %s(%u)",
9952 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9959 json_object_boolean_true_add(json_path
,
9960 "announceNexthopSelf");
9962 vty_out(vty
, " announce-nh-self");
9969 /* display the link-local nexthop */
9970 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9972 json_nexthop_ll
= json_object_new_object();
9973 json_object_string_add(
9974 json_nexthop_ll
, "ip",
9975 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9976 buf
, INET6_ADDRSTRLEN
));
9978 if (path
->peer
->hostname
)
9979 json_object_string_add(json_nexthop_ll
,
9981 path
->peer
->hostname
);
9983 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9984 json_object_string_add(json_nexthop_ll
, "scope",
9987 json_object_boolean_true_add(json_nexthop_ll
,
9990 if (!attr
->mp_nexthop_prefer_global
)
9991 json_object_boolean_true_add(json_nexthop_ll
,
9994 json_object_boolean_true_add(
9995 json_nexthop_global
, "used");
9997 vty_out(vty
, " (%s) %s\n",
9998 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9999 buf
, INET6_ADDRSTRLEN
),
10000 attr
->mp_nexthop_prefer_global
10001 ? "(prefer-global)"
10005 /* If we do not have a link-local nexthop then we must flag the
10006 global as "used" */
10009 json_object_boolean_true_add(json_nexthop_global
,
10013 if (safi
== SAFI_EVPN
&&
10014 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10015 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10018 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10019 * Int/Ext/Local, Atomic, best */
10021 json_object_string_add(json_path
, "origin",
10022 bgp_origin_long_str
[attr
->origin
]);
10024 vty_out(vty
, " Origin %s",
10025 bgp_origin_long_str
[attr
->origin
]);
10027 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10029 json_object_int_add(json_path
, "metric", attr
->med
);
10031 vty_out(vty
, ", metric %u", attr
->med
);
10034 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10036 json_object_int_add(json_path
, "locPrf",
10039 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10042 if (attr
->weight
!= 0) {
10044 json_object_int_add(json_path
, "weight", attr
->weight
);
10046 vty_out(vty
, ", weight %u", attr
->weight
);
10049 if (attr
->tag
!= 0) {
10051 json_object_int_add(json_path
, "tag", attr
->tag
);
10053 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10056 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10058 json_object_boolean_false_add(json_path
, "valid");
10060 vty_out(vty
, ", invalid");
10061 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10063 json_object_boolean_true_add(json_path
, "valid");
10065 vty_out(vty
, ", valid");
10068 if (path
->peer
!= bgp
->peer_self
) {
10069 if (path
->peer
->as
== path
->peer
->local_as
) {
10070 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10072 json_object_string_add(
10074 "confed-internal");
10076 vty_out(vty
, ", confed-internal");
10079 json_object_string_add(
10080 json_peer
, "type", "internal");
10082 vty_out(vty
, ", internal");
10085 if (bgp_confederation_peers_check(bgp
,
10088 json_object_string_add(
10090 "confed-external");
10092 vty_out(vty
, ", confed-external");
10095 json_object_string_add(
10096 json_peer
, "type", "external");
10098 vty_out(vty
, ", external");
10101 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10103 json_object_boolean_true_add(json_path
, "aggregated");
10104 json_object_boolean_true_add(json_path
, "local");
10106 vty_out(vty
, ", aggregated, local");
10108 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10110 json_object_boolean_true_add(json_path
, "sourced");
10112 vty_out(vty
, ", sourced");
10115 json_object_boolean_true_add(json_path
, "sourced");
10116 json_object_boolean_true_add(json_path
, "local");
10118 vty_out(vty
, ", sourced, local");
10122 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10124 json_object_boolean_true_add(json_path
,
10125 "atomicAggregate");
10127 vty_out(vty
, ", atomic-aggregate");
10130 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10131 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10132 && bgp_path_info_mpath_count(path
))) {
10134 json_object_boolean_true_add(json_path
, "multipath");
10136 vty_out(vty
, ", multipath");
10139 // Mark the bestpath(s)
10140 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10141 first_as
= aspath_get_first_as(attr
->aspath
);
10144 if (!json_bestpath
)
10145 json_bestpath
= json_object_new_object();
10146 json_object_int_add(json_bestpath
, "bestpathFromAs",
10150 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10152 vty_out(vty
, ", bestpath-from-AS Local");
10156 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10158 if (!json_bestpath
)
10159 json_bestpath
= json_object_new_object();
10160 json_object_boolean_true_add(json_bestpath
, "overall");
10161 json_object_string_add(
10162 json_bestpath
, "selectionReason",
10163 bgp_path_selection_reason2str(bn
->reason
));
10165 vty_out(vty
, ", best");
10166 vty_out(vty
, " (%s)",
10167 bgp_path_selection_reason2str(bn
->reason
));
10172 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10175 vty_out(vty
, "\n");
10177 /* Line 4 display Community */
10178 if (attr
->community
) {
10180 if (!attr
->community
->json
)
10181 community_str(attr
->community
, true);
10182 json_object_lock(attr
->community
->json
);
10183 json_object_object_add(json_path
, "community",
10184 attr
->community
->json
);
10186 vty_out(vty
, " Community: %s\n",
10187 attr
->community
->str
);
10191 /* Line 5 display Extended-community */
10192 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10194 json_ext_community
= json_object_new_object();
10195 json_object_string_add(json_ext_community
, "string",
10196 attr
->ecommunity
->str
);
10197 json_object_object_add(json_path
, "extendedCommunity",
10198 json_ext_community
);
10200 vty_out(vty
, " Extended Community: %s\n",
10201 attr
->ecommunity
->str
);
10205 /* Line 6 display Large community */
10206 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10208 if (!attr
->lcommunity
->json
)
10209 lcommunity_str(attr
->lcommunity
, true);
10210 json_object_lock(attr
->lcommunity
->json
);
10211 json_object_object_add(json_path
, "largeCommunity",
10212 attr
->lcommunity
->json
);
10214 vty_out(vty
, " Large Community: %s\n",
10215 attr
->lcommunity
->str
);
10219 /* Line 7 display Originator, Cluster-id */
10220 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10221 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10222 char buf
[BUFSIZ
] = {0};
10224 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10226 json_object_string_add(
10227 json_path
, "originatorId",
10228 inet_ntop(AF_INET
, &attr
->originator_id
,
10229 buf
, sizeof(buf
)));
10231 vty_out(vty
, " Originator: %pI4",
10232 &attr
->originator_id
);
10235 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10236 struct cluster_list
*cluster
=
10237 bgp_attr_get_cluster(attr
);
10241 json_cluster_list
= json_object_new_object();
10242 json_cluster_list_list
=
10243 json_object_new_array();
10245 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10246 json_string
= json_object_new_string(
10249 buf
, sizeof(buf
)));
10250 json_object_array_add(
10251 json_cluster_list_list
,
10256 * struct cluster_list does not have
10257 * "str" variable like aspath and community
10258 * do. Add this someday if someone asks
10260 * json_object_string_add(json_cluster_list,
10261 * "string", cluster->str);
10263 json_object_object_add(json_cluster_list
,
10265 json_cluster_list_list
);
10266 json_object_object_add(json_path
, "clusterList",
10267 json_cluster_list
);
10269 vty_out(vty
, ", Cluster list: ");
10271 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10272 vty_out(vty
, "%pI4 ",
10273 &cluster
->list
[i
]);
10279 vty_out(vty
, "\n");
10282 if (path
->extra
&& path
->extra
->damp_info
)
10283 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10286 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10287 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10288 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10291 json_object_int_add(json_path
, "remoteLabel", label
);
10293 vty_out(vty
, " Remote label: %d\n", label
);
10297 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10298 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10300 json_object_string_add(json_path
, "remoteSid", buf
);
10302 vty_out(vty
, " Remote SID: %s\n", buf
);
10306 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10308 json_object_int_add(json_path
, "labelIndex",
10309 attr
->label_index
);
10311 vty_out(vty
, " Label Index: %d\n",
10312 attr
->label_index
);
10315 /* Line 8 display Addpath IDs */
10316 if (path
->addpath_rx_id
10317 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10319 json_object_int_add(json_path
, "addpathRxId",
10320 path
->addpath_rx_id
);
10322 /* Keep backwards compatibility with the old API
10323 * by putting TX All's ID in the old field
10325 json_object_int_add(
10326 json_path
, "addpathTxId",
10328 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10330 /* ... but create a specific field for each
10333 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10334 json_object_int_add(
10336 bgp_addpath_names(i
)->id_json_name
,
10337 path
->tx_addpath
.addpath_tx_id
[i
]);
10340 vty_out(vty
, " AddPath ID: RX %u, ",
10341 path
->addpath_rx_id
);
10343 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10347 /* If we used addpath to TX a non-bestpath we need to display
10348 * "Advertised to" on a path-by-path basis
10350 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10353 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10355 bgp_addpath_encode_tx(peer
, afi
, safi
);
10356 has_adj
= bgp_adj_out_lookup(
10358 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10359 &path
->tx_addpath
));
10361 if ((addpath_capable
&& has_adj
)
10362 || (!addpath_capable
&& has_adj
10363 && CHECK_FLAG(path
->flags
,
10364 BGP_PATH_SELECTED
))) {
10365 if (json_path
&& !json_adv_to
)
10366 json_adv_to
= json_object_new_object();
10368 route_vty_out_advertised_to(
10370 " Advertised to:", json_adv_to
);
10376 json_object_object_add(
10377 json_path
, "advertisedTo", json_adv_to
);
10381 vty_out(vty
, "\n");
10386 /* Line 9 display Uptime */
10387 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10389 json_last_update
= json_object_new_object();
10390 json_object_int_add(json_last_update
, "epoch", tbuf
);
10391 json_object_string_add(json_last_update
, "string",
10393 json_object_object_add(json_path
, "lastUpdate",
10396 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10398 /* Line 10 display PMSI tunnel attribute, if present */
10399 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10400 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10401 bgp_attr_get_pmsi_tnl_type(attr
),
10402 PMSI_TNLTYPE_STR_DEFAULT
);
10405 json_pmsi
= json_object_new_object();
10406 json_object_string_add(json_pmsi
, "tunnelType", str
);
10407 json_object_int_add(json_pmsi
, "label",
10408 label2vni(&attr
->label
));
10409 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10411 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10412 str
, label2vni(&attr
->label
));
10415 /* Output some debug about internal state of the dest flags */
10417 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10418 json_object_boolean_true_add(json_path
, "processScheduled");
10419 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10420 json_object_boolean_true_add(json_path
, "userCleared");
10421 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10422 json_object_boolean_true_add(json_path
, "labelChanged");
10423 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10424 json_object_boolean_true_add(json_path
, "registeredForLabel");
10425 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10426 json_object_boolean_true_add(json_path
, "selectDefered");
10427 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10428 json_object_boolean_true_add(json_path
, "fibInstalled");
10429 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10430 json_object_boolean_true_add(json_path
, "fibPending");
10433 /* We've constructed the json object for this path, add it to the json
10437 if (json_nexthop_global
|| json_nexthop_ll
) {
10438 json_nexthops
= json_object_new_array();
10440 if (json_nexthop_global
)
10441 json_object_array_add(json_nexthops
,
10442 json_nexthop_global
);
10444 if (json_nexthop_ll
)
10445 json_object_array_add(json_nexthops
,
10448 json_object_object_add(json_path
, "nexthops",
10452 json_object_object_add(json_path
, "peer", json_peer
);
10453 json_object_array_add(json_paths
, json_path
);
10457 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10458 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10459 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10461 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10462 const char *prefix_list_str
, afi_t afi
,
10463 safi_t safi
, enum bgp_show_type type
);
10464 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10465 const char *filter
, afi_t afi
, safi_t safi
,
10466 enum bgp_show_type type
);
10467 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10468 const char *rmap_str
, afi_t afi
, safi_t safi
,
10469 enum bgp_show_type type
);
10470 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10471 const char *com
, int exact
, afi_t afi
,
10473 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10474 const char *prefix
, afi_t afi
, safi_t safi
,
10475 enum bgp_show_type type
);
10476 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10477 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10479 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10480 const char *comstr
, int exact
, afi_t afi
,
10481 safi_t safi
, uint8_t show_flags
);
10484 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10485 struct bgp_table
*table
, enum bgp_show_type type
,
10486 void *output_arg
, char *rd
, int is_last
,
10487 unsigned long *output_cum
, unsigned long *total_cum
,
10488 unsigned long *json_header_depth
, uint8_t show_flags
)
10490 struct bgp_path_info
*pi
;
10491 struct bgp_dest
*dest
;
10494 unsigned long output_count
= 0;
10495 unsigned long total_count
= 0;
10497 json_object
*json_paths
= NULL
;
10499 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10500 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10501 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10503 if (output_cum
&& *output_cum
!= 0)
10506 if (use_json
&& !*json_header_depth
) {
10508 *json_header_depth
= 1;
10510 vty_out(vty
, "{\n");
10511 *json_header_depth
= 2;
10515 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10516 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10517 " \"localAS\": %u,\n \"routes\": { ",
10518 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10519 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10522 table
->version
, &bgp
->router_id
,
10523 bgp
->default_local_pref
, bgp
->as
);
10525 vty_out(vty
, " \"routeDistinguishers\" : {");
10526 ++*json_header_depth
;
10530 if (use_json
&& rd
) {
10531 vty_out(vty
, " \"%s\" : { ", rd
);
10534 /* Start processing of routes. */
10535 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10536 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10538 pi
= bgp_dest_get_bgp_path_info(dest
);
10544 json_paths
= json_object_new_array();
10548 for (; pi
; pi
= pi
->next
) {
10550 if (type
== bgp_show_type_flap_statistics
10551 || type
== bgp_show_type_flap_neighbor
10552 || type
== bgp_show_type_dampend_paths
10553 || type
== bgp_show_type_damp_neighbor
) {
10554 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10557 if (type
== bgp_show_type_regexp
) {
10558 regex_t
*regex
= output_arg
;
10560 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10564 if (type
== bgp_show_type_prefix_list
) {
10565 struct prefix_list
*plist
= output_arg
;
10567 if (prefix_list_apply(plist
, dest_p
)
10571 if (type
== bgp_show_type_filter_list
) {
10572 struct as_list
*as_list
= output_arg
;
10574 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10575 != AS_FILTER_PERMIT
)
10578 if (type
== bgp_show_type_route_map
) {
10579 struct route_map
*rmap
= output_arg
;
10580 struct bgp_path_info path
;
10581 struct attr dummy_attr
;
10582 route_map_result_t ret
;
10584 dummy_attr
= *pi
->attr
;
10586 path
.peer
= pi
->peer
;
10587 path
.attr
= &dummy_attr
;
10589 ret
= route_map_apply(rmap
, dest_p
, &path
);
10590 if (ret
== RMAP_DENYMATCH
)
10593 if (type
== bgp_show_type_neighbor
10594 || type
== bgp_show_type_flap_neighbor
10595 || type
== bgp_show_type_damp_neighbor
) {
10596 union sockunion
*su
= output_arg
;
10598 if (pi
->peer
== NULL
10599 || pi
->peer
->su_remote
== NULL
10600 || !sockunion_same(pi
->peer
->su_remote
, su
))
10603 if (type
== bgp_show_type_cidr_only
) {
10604 uint32_t destination
;
10606 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10607 if (IN_CLASSC(destination
)
10608 && dest_p
->prefixlen
== 24)
10610 if (IN_CLASSB(destination
)
10611 && dest_p
->prefixlen
== 16)
10613 if (IN_CLASSA(destination
)
10614 && dest_p
->prefixlen
== 8)
10617 if (type
== bgp_show_type_prefix_longer
) {
10619 if (!prefix_match(p
, dest_p
))
10622 if (type
== bgp_show_type_community_all
) {
10623 if (!pi
->attr
->community
)
10626 if (type
== bgp_show_type_community
) {
10627 struct community
*com
= output_arg
;
10629 if (!pi
->attr
->community
10630 || !community_match(pi
->attr
->community
,
10634 if (type
== bgp_show_type_community_exact
) {
10635 struct community
*com
= output_arg
;
10637 if (!pi
->attr
->community
10638 || !community_cmp(pi
->attr
->community
, com
))
10641 if (type
== bgp_show_type_community_list
) {
10642 struct community_list
*list
= output_arg
;
10644 if (!community_list_match(pi
->attr
->community
,
10648 if (type
== bgp_show_type_community_list_exact
) {
10649 struct community_list
*list
= output_arg
;
10651 if (!community_list_exact_match(
10652 pi
->attr
->community
, list
))
10655 if (type
== bgp_show_type_lcommunity
) {
10656 struct lcommunity
*lcom
= output_arg
;
10658 if (!pi
->attr
->lcommunity
10659 || !lcommunity_match(pi
->attr
->lcommunity
,
10664 if (type
== bgp_show_type_lcommunity_exact
) {
10665 struct lcommunity
*lcom
= output_arg
;
10667 if (!pi
->attr
->lcommunity
10668 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10672 if (type
== bgp_show_type_lcommunity_list
) {
10673 struct community_list
*list
= output_arg
;
10675 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10680 == bgp_show_type_lcommunity_list_exact
) {
10681 struct community_list
*list
= output_arg
;
10683 if (!lcommunity_list_exact_match(
10684 pi
->attr
->lcommunity
, list
))
10687 if (type
== bgp_show_type_lcommunity_all
) {
10688 if (!pi
->attr
->lcommunity
)
10691 if (type
== bgp_show_type_dampend_paths
10692 || type
== bgp_show_type_damp_neighbor
) {
10693 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10694 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10698 if (!use_json
&& header
) {
10700 "BGP table version is %" PRIu64
10701 ", local router ID is %pI4, vrf id ",
10702 table
->version
, &bgp
->router_id
);
10703 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10704 vty_out(vty
, "%s", VRFID_NONE_STR
);
10706 vty_out(vty
, "%u", bgp
->vrf_id
);
10707 vty_out(vty
, "\n");
10708 vty_out(vty
, "Default local pref %u, ",
10709 bgp
->default_local_pref
);
10710 vty_out(vty
, "local AS %u\n", bgp
->as
);
10711 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10712 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10713 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10714 if (type
== bgp_show_type_dampend_paths
10715 || type
== bgp_show_type_damp_neighbor
)
10716 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10717 else if (type
== bgp_show_type_flap_statistics
10718 || type
== bgp_show_type_flap_neighbor
)
10719 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10721 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10722 : BGP_SHOW_HEADER
));
10725 if (rd
!= NULL
&& !display
&& !output_count
) {
10728 "Route Distinguisher: %s\n",
10731 if (type
== bgp_show_type_dampend_paths
10732 || type
== bgp_show_type_damp_neighbor
)
10733 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10734 AFI_IP
, safi
, use_json
,
10736 else if (type
== bgp_show_type_flap_statistics
10737 || type
== bgp_show_type_flap_neighbor
)
10738 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10739 AFI_IP
, safi
, use_json
,
10742 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10752 /* encode prefix */
10753 if (dest_p
->family
== AF_FLOWSPEC
) {
10754 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10757 bgp_fs_nlri_get_string(
10759 dest_p
->u
.prefix_flowspec
.ptr
,
10760 dest_p
->u
.prefix_flowspec
.prefixlen
,
10761 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10762 family2afi(dest_p
->u
10763 .prefix_flowspec
.family
));
10765 vty_out(vty
, "\"%s/%d\": ", retstr
,
10766 dest_p
->u
.prefix_flowspec
10769 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10770 dest_p
->u
.prefix_flowspec
10774 vty_out(vty
, "\"%pFX\": ", dest_p
);
10776 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10779 json_object_to_json_string_ext(
10780 json_paths
, JSON_C_TO_STRING_PRETTY
));
10781 json_object_free(json_paths
);
10785 json_object_free(json_paths
);
10789 output_count
+= *output_cum
;
10790 *output_cum
= output_count
;
10793 total_count
+= *total_cum
;
10794 *total_cum
= total_count
;
10798 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10802 for (i
= 0; i
< *json_header_depth
; ++i
)
10803 vty_out(vty
, " } ");
10805 vty_out(vty
, "\n");
10809 /* No route is displayed */
10810 if (output_count
== 0) {
10811 if (type
== bgp_show_type_normal
)
10813 "No BGP prefixes displayed, %ld exist\n",
10817 "\nDisplayed %ld routes and %ld total paths\n",
10818 output_count
, total_count
);
10822 return CMD_SUCCESS
;
10825 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10826 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10827 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10829 struct bgp_dest
*dest
, *next
;
10830 unsigned long output_cum
= 0;
10831 unsigned long total_cum
= 0;
10832 unsigned long json_header_depth
= 0;
10833 struct bgp_table
*itable
;
10835 uint8_t show_flags
= 0;
10837 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10840 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10842 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10843 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10845 next
= bgp_route_next(dest
);
10846 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10849 itable
= bgp_dest_get_bgp_table_info(dest
);
10850 if (itable
!= NULL
) {
10851 struct prefix_rd prd
;
10852 char rd
[RD_ADDRSTRLEN
];
10854 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10855 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10856 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10857 rd
, next
== NULL
, &output_cum
,
10858 &total_cum
, &json_header_depth
,
10865 if (output_cum
== 0)
10866 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10870 "\nDisplayed %ld routes and %ld total paths\n",
10871 output_cum
, total_cum
);
10873 return CMD_SUCCESS
;
10875 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10876 enum bgp_show_type type
, void *output_arg
,
10877 uint8_t show_flags
)
10879 struct bgp_table
*table
;
10880 unsigned long json_header_depth
= 0;
10881 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10884 bgp
= bgp_get_default();
10889 vty_out(vty
, "No BGP process is configured\n");
10891 vty_out(vty
, "{}\n");
10892 return CMD_WARNING
;
10895 table
= bgp
->rib
[afi
][safi
];
10896 /* use MPLS and ENCAP specific shows until they are merged */
10897 if (safi
== SAFI_MPLS_VPN
) {
10898 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10899 output_arg
, use_json
);
10902 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10903 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10904 output_arg
, use_json
,
10907 /* labeled-unicast routes live in the unicast table */
10908 else if (safi
== SAFI_LABELED_UNICAST
)
10909 safi
= SAFI_UNICAST
;
10911 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10912 NULL
, NULL
, &json_header_depth
, show_flags
);
10915 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10916 safi_t safi
, uint8_t show_flags
)
10918 struct listnode
*node
, *nnode
;
10921 bool route_output
= false;
10922 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10925 vty_out(vty
, "{\n");
10927 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10928 route_output
= true;
10931 vty_out(vty
, ",\n");
10935 vty_out(vty
, "\"%s\":",
10936 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10940 vty_out(vty
, "\nInstance %s:\n",
10941 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10945 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10950 vty_out(vty
, "}\n");
10951 else if (!route_output
)
10952 vty_out(vty
, "%% BGP instance not found\n");
10955 /* Header of detailed BGP route information */
10956 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10957 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10958 afi_t afi
, safi_t safi
, json_object
*json
)
10960 struct bgp_path_info
*pi
;
10961 const struct prefix
*p
;
10963 struct listnode
*node
, *nnode
;
10964 char buf1
[RD_ADDRSTRLEN
];
10965 char prefix_str
[BUFSIZ
];
10969 int accept_own
= 0;
10970 int route_filter_translated_v4
= 0;
10971 int route_filter_v4
= 0;
10972 int route_filter_translated_v6
= 0;
10973 int route_filter_v6
= 0;
10974 int llgr_stale
= 0;
10976 int accept_own_nexthop
= 0;
10979 int no_advertise
= 0;
10983 int has_valid_label
= 0;
10984 mpls_label_t label
= 0;
10985 json_object
*json_adv_to
= NULL
;
10987 p
= bgp_dest_get_prefix(dest
);
10988 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10990 if (has_valid_label
)
10991 label
= label_pton(&dest
->local_label
);
10993 if (safi
== SAFI_EVPN
) {
10996 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
10997 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10999 prd
? ":" : "", (struct prefix_evpn
*)p
);
11001 json_object_string_add(json
, "rd",
11002 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11004 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11008 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11009 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11010 ? prefix_rd2str(prd
, buf1
,
11013 safi
== SAFI_MPLS_VPN
? ":" : "", p
);
11016 json_object_string_add(json
, "prefix",
11017 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11020 if (has_valid_label
) {
11022 json_object_int_add(json
, "localLabel", label
);
11024 vty_out(vty
, "Local label: %d\n", label
);
11028 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11029 vty_out(vty
, "not allocated\n");
11031 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11033 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11035 if (bgp_path_suppressed(pi
))
11038 if (pi
->attr
->community
== NULL
)
11041 no_advertise
+= community_include(
11042 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11043 no_export
+= community_include(pi
->attr
->community
,
11044 COMMUNITY_NO_EXPORT
);
11045 local_as
+= community_include(pi
->attr
->community
,
11046 COMMUNITY_LOCAL_AS
);
11047 accept_own
+= community_include(pi
->attr
->community
,
11048 COMMUNITY_ACCEPT_OWN
);
11049 route_filter_translated_v4
+= community_include(
11050 pi
->attr
->community
,
11051 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11052 route_filter_translated_v6
+= community_include(
11053 pi
->attr
->community
,
11054 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11055 route_filter_v4
+= community_include(
11056 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11057 route_filter_v6
+= community_include(
11058 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11059 llgr_stale
+= community_include(pi
->attr
->community
,
11060 COMMUNITY_LLGR_STALE
);
11061 no_llgr
+= community_include(pi
->attr
->community
,
11062 COMMUNITY_NO_LLGR
);
11063 accept_own_nexthop
+=
11064 community_include(pi
->attr
->community
,
11065 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11066 blackhole
+= community_include(pi
->attr
->community
,
11067 COMMUNITY_BLACKHOLE
);
11068 no_peer
+= community_include(pi
->attr
->community
,
11069 COMMUNITY_NO_PEER
);
11074 vty_out(vty
, "Paths: (%d available", count
);
11076 vty_out(vty
, ", best #%d", best
);
11077 if (safi
== SAFI_UNICAST
) {
11078 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11079 vty_out(vty
, ", table %s",
11082 vty_out(vty
, ", vrf %s",
11086 vty_out(vty
, ", no best path");
11090 ", accept own local route exported and imported in different VRF");
11091 else if (route_filter_translated_v4
)
11093 ", mark translated RTs for VPNv4 route filtering");
11094 else if (route_filter_v4
)
11096 ", attach RT as-is for VPNv4 route filtering");
11097 else if (route_filter_translated_v6
)
11099 ", mark translated RTs for VPNv6 route filtering");
11100 else if (route_filter_v6
)
11102 ", attach RT as-is for VPNv6 route filtering");
11103 else if (llgr_stale
)
11105 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11108 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11109 else if (accept_own_nexthop
)
11111 ", accept local nexthop");
11112 else if (blackhole
)
11113 vty_out(vty
, ", inform peer to blackhole prefix");
11114 else if (no_export
)
11115 vty_out(vty
, ", not advertised to EBGP peer");
11116 else if (no_advertise
)
11117 vty_out(vty
, ", not advertised to any peer");
11119 vty_out(vty
, ", not advertised outside local AS");
11122 ", inform EBGP peer not to advertise to their EBGP peers");
11126 ", Advertisements suppressed by an aggregate.");
11127 vty_out(vty
, ")\n");
11130 /* If we are not using addpath then we can display Advertised to and
11132 * show what peers we advertised the bestpath to. If we are using
11134 * though then we must display Advertised to on a path-by-path basis. */
11135 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11136 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11137 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11138 if (json
&& !json_adv_to
)
11139 json_adv_to
= json_object_new_object();
11141 route_vty_out_advertised_to(
11143 " Advertised to non peer-group peers:\n ",
11150 json_object_object_add(json
, "advertisedTo",
11155 vty_out(vty
, " Not advertised to any peer");
11156 vty_out(vty
, "\n");
11161 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11162 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11163 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11164 json_object
*json
, enum bgp_path_type pathtype
,
11167 struct bgp_path_info
*pi
;
11169 char rdbuf
[RD_ADDRSTRLEN
];
11170 json_object
*json_header
= NULL
;
11171 json_object
*json_paths
= NULL
;
11173 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11175 if (json
&& !json_paths
) {
11176 /* Instantiate json_paths only if path is valid */
11177 json_paths
= json_object_new_array();
11179 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11180 json_header
= json_object_new_object();
11182 json_header
= json
;
11186 route_vty_out_detail_header(
11187 vty
, bgp
, bgp_node
, pfx_rd
,
11188 AFI_IP
, safi
, json_header
);
11193 if (pathtype
== BGP_PATH_SHOW_ALL
11194 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11195 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11196 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11197 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11198 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11199 route_vty_out_detail(vty
, bgp
, bgp_node
,
11204 if (json
&& json_paths
) {
11205 json_object_object_add(json_header
, "paths", json_paths
);
11208 json_object_object_add(json
, rdbuf
, json_header
);
11212 /* Display specified route of BGP table. */
11213 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11214 struct bgp_table
*rib
, const char *ip_str
,
11215 afi_t afi
, safi_t safi
,
11216 struct prefix_rd
*prd
, int prefix_check
,
11217 enum bgp_path_type pathtype
, bool use_json
)
11221 struct prefix match
;
11222 struct bgp_dest
*dest
;
11223 struct bgp_dest
*rm
;
11224 struct bgp_table
*table
;
11225 json_object
*json
= NULL
;
11226 json_object
*json_paths
= NULL
;
11228 /* Check IP address argument. */
11229 ret
= str2prefix(ip_str
, &match
);
11231 vty_out(vty
, "address is malformed\n");
11232 return CMD_WARNING
;
11235 match
.family
= afi2family(afi
);
11238 json
= json_object_new_object();
11240 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11241 for (dest
= bgp_table_top(rib
); dest
;
11242 dest
= bgp_route_next(dest
)) {
11243 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11245 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11247 table
= bgp_dest_get_bgp_table_info(dest
);
11251 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11254 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11256 && rm_p
->prefixlen
!= match
.prefixlen
) {
11257 bgp_dest_unlock_node(rm
);
11261 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11262 bgp
, afi
, safi
, json
, pathtype
,
11265 bgp_dest_unlock_node(rm
);
11267 } else if (safi
== SAFI_EVPN
) {
11268 struct bgp_dest
*longest_pfx
;
11269 bool is_exact_pfxlen_match
= false;
11271 for (dest
= bgp_table_top(rib
); dest
;
11272 dest
= bgp_route_next(dest
)) {
11273 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11275 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11277 table
= bgp_dest_get_bgp_table_info(dest
);
11281 longest_pfx
= NULL
;
11282 is_exact_pfxlen_match
= false;
11284 * Search through all the prefixes for a match. The
11285 * pfx's are enumerated in ascending order of pfxlens.
11286 * So, the last pfx match is the longest match. Set
11287 * is_exact_pfxlen_match when we get exact pfxlen match
11289 for (rm
= bgp_table_top(table
); rm
;
11290 rm
= bgp_route_next(rm
)) {
11291 const struct prefix
*rm_p
=
11292 bgp_dest_get_prefix(rm
);
11294 * Get prefixlen of the ip-prefix within type5
11297 if (evpn_type5_prefix_match(rm_p
, &match
)
11301 bgp_evpn_get_type5_prefixlen(
11303 if (type5_pfxlen
== match
.prefixlen
) {
11304 is_exact_pfxlen_match
= true;
11305 bgp_dest_unlock_node(rm
);
11314 if (prefix_check
&& !is_exact_pfxlen_match
)
11318 bgp_dest_lock_node(rm
);
11320 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11321 bgp
, afi
, safi
, json
, pathtype
,
11324 bgp_dest_unlock_node(rm
);
11326 } else if (safi
== SAFI_FLOWSPEC
) {
11328 json_paths
= json_object_new_array();
11330 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11331 &match
, prefix_check
,
11337 json_object_object_add(json
, "paths",
11340 json_object_free(json_paths
);
11343 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
11344 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11346 || dest_p
->prefixlen
== match
.prefixlen
) {
11347 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11348 safi
, json
, pathtype
,
11352 bgp_dest_unlock_node(dest
);
11357 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11358 json
, JSON_C_TO_STRING_PRETTY
|
11359 JSON_C_TO_STRING_NOSLASHESCAPE
));
11360 json_object_free(json
);
11363 vty_out(vty
, "%% Network not in table\n");
11364 return CMD_WARNING
;
11368 return CMD_SUCCESS
;
11371 /* Display specified route of Main RIB */
11372 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11373 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11374 int prefix_check
, enum bgp_path_type pathtype
,
11378 bgp
= bgp_get_default();
11381 vty_out(vty
, "No BGP process is configured\n");
11383 vty_out(vty
, "{}\n");
11384 return CMD_WARNING
;
11388 /* labeled-unicast routes live in the unicast table */
11389 if (safi
== SAFI_LABELED_UNICAST
)
11390 safi
= SAFI_UNICAST
;
11392 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11393 afi
, safi
, prd
, prefix_check
, pathtype
,
11397 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11398 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11399 safi_t safi
, bool uj
)
11401 struct lcommunity
*lcom
;
11406 uint8_t show_flags
= 0;
11410 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11412 b
= buffer_new(1024);
11413 for (i
= 0; i
< argc
; i
++) {
11415 buffer_putc(b
, ' ');
11417 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11419 buffer_putstr(b
, argv
[i
]->arg
);
11423 buffer_putc(b
, '\0');
11425 str
= buffer_getstr(b
);
11428 lcom
= lcommunity_str2com(str
);
11429 XFREE(MTYPE_TMP
, str
);
11431 vty_out(vty
, "%% Large-community malformed\n");
11432 return CMD_WARNING
;
11435 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11436 (exact
? bgp_show_type_lcommunity_exact
11437 : bgp_show_type_lcommunity
),
11440 lcommunity_free(&lcom
);
11444 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11445 const char *lcom
, bool exact
, afi_t afi
,
11446 safi_t safi
, bool uj
)
11448 struct community_list
*list
;
11449 uint8_t show_flags
= 0;
11452 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11455 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11456 LARGE_COMMUNITY_LIST_MASTER
);
11457 if (list
== NULL
) {
11458 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11460 return CMD_WARNING
;
11463 return bgp_show(vty
, bgp
, afi
, safi
,
11464 (exact
? bgp_show_type_lcommunity_list_exact
11465 : bgp_show_type_lcommunity_list
),
11469 DEFUN (show_ip_bgp_large_community_list
,
11470 show_ip_bgp_large_community_list_cmd
,
11471 "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]",
11475 BGP_INSTANCE_HELP_STR
11477 BGP_SAFI_WITH_LABEL_HELP_STR
11478 "Display routes matching the large-community-list\n"
11479 "large-community-list number\n"
11480 "large-community-list name\n"
11481 "Exact match of the large-communities\n"
11484 afi_t afi
= AFI_IP6
;
11485 safi_t safi
= SAFI_UNICAST
;
11487 bool exact_match
= 0;
11488 struct bgp
*bgp
= NULL
;
11489 bool uj
= use_json(argc
, argv
);
11494 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11497 return CMD_WARNING
;
11499 argv_find(argv
, argc
, "large-community-list", &idx
);
11501 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11503 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11506 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11507 exact_match
, afi
, safi
, uj
);
11509 DEFUN (show_ip_bgp_large_community
,
11510 show_ip_bgp_large_community_cmd
,
11511 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11515 BGP_INSTANCE_HELP_STR
11517 BGP_SAFI_WITH_LABEL_HELP_STR
11518 "Display routes matching the large-communities\n"
11519 "List of large-community numbers\n"
11520 "Exact match of the large-communities\n"
11523 afi_t afi
= AFI_IP6
;
11524 safi_t safi
= SAFI_UNICAST
;
11526 bool exact_match
= 0;
11527 struct bgp
*bgp
= NULL
;
11528 bool uj
= use_json(argc
, argv
);
11529 uint8_t show_flags
= 0;
11533 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11536 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11539 return CMD_WARNING
;
11541 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11542 if (argv_find(argv
, argc
, "exact-match", &idx
))
11544 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11545 exact_match
, afi
, safi
, uj
);
11547 return bgp_show(vty
, bgp
, afi
, safi
,
11548 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
11551 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11552 safi_t safi
, struct json_object
*json_array
);
11553 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11554 safi_t safi
, struct json_object
*json
);
11557 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11558 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11559 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11560 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11562 bool uj
= use_json(argc
, argv
);
11563 struct bgp
*bgp
= NULL
;
11564 safi_t safi
= SAFI_UNICAST
;
11565 afi_t afi
= AFI_IP6
;
11567 struct json_object
*json_all
= NULL
;
11568 struct json_object
*json_afi_safi
= NULL
;
11570 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11573 return CMD_WARNING
;
11576 json_all
= json_object_new_object();
11578 FOREACH_AFI_SAFI (afi
, safi
) {
11580 * So limit output to those afi/safi pairs that
11581 * actually have something interesting in them
11583 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11588 json_afi_safi
= json_object_new_array();
11589 json_object_object_add(
11591 get_afi_safi_str(afi
, safi
, true),
11594 json_afi_safi
= NULL
;
11597 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11602 json_object_to_json_string_ext(
11603 json_all
, JSON_C_TO_STRING_PRETTY
));
11604 json_object_free(json_all
);
11607 return CMD_SUCCESS
;
11610 /* BGP route print out function without JSON */
11611 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11612 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11613 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11617 BGP_INSTANCE_HELP_STR
11620 "BGP RIB advertisement statistics\n"
11623 afi_t afi
= AFI_IP6
;
11624 safi_t safi
= SAFI_UNICAST
;
11625 struct bgp
*bgp
= NULL
;
11627 bool uj
= use_json(argc
, argv
);
11628 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11630 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11633 return CMD_WARNING
;
11636 json_afi_safi
= json_object_new_array();
11638 json_afi_safi
= NULL
;
11640 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11643 json
= json_object_new_object();
11644 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11646 vty_out(vty
, "%s", json_object_to_json_string_ext(
11647 json
, JSON_C_TO_STRING_PRETTY
));
11648 json_object_free(json
);
11653 /* BGP route print out function without JSON */
11654 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11655 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11656 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11658 statistics [json]",
11659 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11660 BGP_SAFI_WITH_LABEL_HELP_STR
11661 "BGP RIB advertisement statistics\n" JSON_STR
)
11663 afi_t afi
= AFI_IP6
;
11664 safi_t safi
= SAFI_UNICAST
;
11665 struct bgp
*bgp
= NULL
;
11667 bool uj
= use_json(argc
, argv
);
11668 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11670 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11673 return CMD_WARNING
;
11676 json_afi_safi
= json_object_new_array();
11678 json_afi_safi
= NULL
;
11680 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11683 json
= json_object_new_object();
11684 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11687 json_object_to_json_string_ext(
11688 json
, JSON_C_TO_STRING_PRETTY
));
11689 json_object_free(json
);
11694 /* BGP route print out function without JSON */
11695 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11696 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11697 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11699 <[all$all] dampening <parameters>\
11703 |community-list <(1-500)|WORD> [exact-match]\
11704 |A.B.C.D/M longer-prefixes\
11705 |X:X::X:X/M longer-prefixes\
11707 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11708 BGP_SAFI_WITH_LABEL_HELP_STR
11709 "Display the entries for all address families\n"
11710 "Display detailed information about dampening\n"
11711 "Display detail of configured dampening parameters\n"
11712 "Display routes matching the route-map\n"
11713 "A route-map to match on\n"
11714 "Display routes conforming to the prefix-list\n"
11715 "Prefix-list name\n"
11716 "Display routes conforming to the filter-list\n"
11717 "Regular expression access list name\n"
11718 "Display routes matching the community-list\n"
11719 "community-list number\n"
11720 "community-list name\n"
11721 "Exact match of the communities\n"
11723 "Display route and more specific routes\n"
11725 "Display route and more specific routes\n")
11727 afi_t afi
= AFI_IP6
;
11728 safi_t safi
= SAFI_UNICAST
;
11729 int exact_match
= 0;
11730 struct bgp
*bgp
= NULL
;
11732 uint8_t show_flags
= 0;
11734 /* [<ipv4|ipv6> [all]] */
11736 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11737 if (argv_find(argv
, argc
, "ipv4", &idx
))
11738 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11740 if (argv_find(argv
, argc
, "ipv6", &idx
))
11741 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11744 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11747 return CMD_WARNING
;
11749 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11750 if (argv_find(argv
, argc
, "parameters", &idx
))
11751 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11755 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11756 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11757 safi
, bgp_show_type_prefix_list
);
11759 if (argv_find(argv
, argc
, "filter-list", &idx
))
11760 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11761 safi
, bgp_show_type_filter_list
);
11763 if (argv_find(argv
, argc
, "route-map", &idx
))
11764 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11765 safi
, bgp_show_type_route_map
);
11767 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11768 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11769 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11771 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11772 exact_match
, afi
, safi
);
11774 /* prefix-longer */
11775 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11776 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11777 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11779 bgp_show_type_prefix_longer
);
11781 return CMD_WARNING
;
11784 /* BGP route print out function with JSON */
11785 DEFPY (show_ip_bgp_json
,
11786 show_ip_bgp_json_cmd
,
11787 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11790 |dampening <flap-statistics|dampened-paths>\
11791 |community [AA:NN|local-AS|no-advertise|no-export\
11792 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11793 |accept-own|accept-own-nexthop|route-filter-v6\
11794 |route-filter-v4|route-filter-translated-v6\
11795 |route-filter-translated-v4] [exact-match]\
11796 ] [json$uj | wide$wide]",
11800 BGP_INSTANCE_HELP_STR
11802 BGP_SAFI_WITH_LABEL_HELP_STR
11803 "Display the entries for all address families\n"
11804 "Display only routes with non-natural netmasks\n"
11805 "Display detailed information about dampening\n"
11806 "Display flap statistics of routes\n"
11807 "Display paths suppressed due to dampening\n"
11808 "Display routes matching the communities\n"
11810 "Do not send outside local AS (well-known community)\n"
11811 "Do not advertise to any peer (well-known community)\n"
11812 "Do not export to next AS (well-known community)\n"
11813 "Graceful shutdown (well-known community)\n"
11814 "Do not export to any peer (well-known community)\n"
11815 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11816 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11817 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11818 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11819 "Should accept VPN route with local nexthop (well-known community)\n"
11820 "RT VPNv6 route filtering (well-known community)\n"
11821 "RT VPNv4 route filtering (well-known community)\n"
11822 "RT translated VPNv6 route filtering (well-known community)\n"
11823 "RT translated VPNv4 route filtering (well-known community)\n"
11824 "Exact match of the communities\n"
11826 "Increase table width for longer prefixes\n")
11828 afi_t afi
= AFI_IP6
;
11829 safi_t safi
= SAFI_UNICAST
;
11830 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11831 struct bgp
*bgp
= NULL
;
11833 int exact_match
= 0;
11834 char *community
= NULL
;
11836 uint8_t show_flags
= 0;
11841 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11844 /* [<ipv4|ipv6> [all]] */
11846 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11848 if (argv_find(argv
, argc
, "ipv4", &idx
))
11849 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11851 if (argv_find(argv
, argc
, "ipv6", &idx
))
11852 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11856 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11858 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11861 return CMD_WARNING
;
11863 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11864 sh_type
= bgp_show_type_cidr_only
;
11866 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11867 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11868 sh_type
= bgp_show_type_dampend_paths
;
11869 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11870 sh_type
= bgp_show_type_flap_statistics
;
11873 if (argv_find(argv
, argc
, "community", &idx
)) {
11874 char *maybecomm
= NULL
;
11876 if (idx
+ 1 < argc
) {
11877 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11878 maybecomm
= argv
[idx
+ 1]->arg
;
11880 maybecomm
= argv
[idx
+ 1]->text
;
11883 if (maybecomm
&& !strmatch(maybecomm
, "json")
11884 && !strmatch(maybecomm
, "exact-match"))
11885 community
= maybecomm
;
11887 if (argv_find(argv
, argc
, "exact-match", &idx
))
11891 sh_type
= bgp_show_type_community_all
;
11895 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11897 return bgp_show_community(vty
, bgp
, community
,
11898 exact_match
, afi
, safi
,
11901 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11904 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11908 vty_out(vty
, "{\n");
11910 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11911 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11912 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11915 FOREACH_SAFI (safi
) {
11916 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11923 vty_out(vty
, ",\n");
11924 vty_out(vty
, "\"%s\":{\n",
11925 get_afi_safi_str(afi
, safi
,
11929 "\nFor address family: %s\n",
11930 get_afi_safi_str(afi
, safi
,
11934 bgp_show_community(vty
, bgp
, community
,
11938 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11941 vty_out(vty
, "}\n");
11944 /* show <ip> bgp all: for each AFI and SAFI*/
11945 FOREACH_AFI_SAFI (afi
, safi
) {
11946 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11953 vty_out(vty
, ",\n");
11955 vty_out(vty
, "\"%s\":{\n",
11956 get_afi_safi_str(afi
, safi
,
11960 "\nFor address family: %s\n",
11961 get_afi_safi_str(afi
, safi
,
11965 bgp_show_community(vty
, bgp
, community
,
11969 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11972 vty_out(vty
, "}\n");
11976 vty_out(vty
, "}\n");
11978 return CMD_SUCCESS
;
11981 DEFUN (show_ip_bgp_route
,
11982 show_ip_bgp_route_cmd
,
11983 "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]",
11987 BGP_INSTANCE_HELP_STR
11989 BGP_SAFI_WITH_LABEL_HELP_STR
11990 "Network in the BGP routing table to display\n"
11992 "Network in the BGP routing table to display\n"
11994 "Display only the bestpath\n"
11995 "Display only multipaths\n"
11998 int prefix_check
= 0;
12000 afi_t afi
= AFI_IP6
;
12001 safi_t safi
= SAFI_UNICAST
;
12002 char *prefix
= NULL
;
12003 struct bgp
*bgp
= NULL
;
12004 enum bgp_path_type path_type
;
12005 bool uj
= use_json(argc
, argv
);
12009 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12012 return CMD_WARNING
;
12016 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12017 return CMD_WARNING
;
12020 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12021 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12022 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12024 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12025 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12028 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12029 && afi
!= AFI_IP6
) {
12031 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12032 return CMD_WARNING
;
12034 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12035 && afi
!= AFI_IP
) {
12037 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12038 return CMD_WARNING
;
12041 prefix
= argv
[idx
]->arg
;
12043 /* [<bestpath|multipath>] */
12044 if (argv_find(argv
, argc
, "bestpath", &idx
))
12045 path_type
= BGP_PATH_SHOW_BESTPATH
;
12046 else if (argv_find(argv
, argc
, "multipath", &idx
))
12047 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12049 path_type
= BGP_PATH_SHOW_ALL
;
12051 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12055 DEFUN (show_ip_bgp_regexp
,
12056 show_ip_bgp_regexp_cmd
,
12057 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12061 BGP_INSTANCE_HELP_STR
12063 BGP_SAFI_WITH_LABEL_HELP_STR
12064 "Display routes matching the AS path regular expression\n"
12065 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12068 afi_t afi
= AFI_IP6
;
12069 safi_t safi
= SAFI_UNICAST
;
12070 struct bgp
*bgp
= NULL
;
12071 bool uj
= use_json(argc
, argv
);
12072 char *regstr
= NULL
;
12075 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12078 return CMD_WARNING
;
12080 // get index of regex
12081 if (argv_find(argv
, argc
, "REGEX", &idx
))
12082 regstr
= argv
[idx
]->arg
;
12085 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12086 bgp_show_type_regexp
, uj
);
12089 DEFPY (show_ip_bgp_instance_all
,
12090 show_ip_bgp_instance_all_cmd
,
12091 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12095 BGP_INSTANCE_ALL_HELP_STR
12097 BGP_SAFI_WITH_LABEL_HELP_STR
12099 "Increase table width for longer prefixes\n")
12101 afi_t afi
= AFI_IP
;
12102 safi_t safi
= SAFI_UNICAST
;
12103 struct bgp
*bgp
= NULL
;
12105 uint8_t show_flags
= 0;
12109 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12113 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12115 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12118 return CMD_WARNING
;
12120 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12121 return CMD_SUCCESS
;
12124 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12125 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12130 uint8_t show_flags
= 0;
12133 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12135 if (!config_bgp_aspath_validate(regstr
)) {
12136 vty_out(vty
, "Invalid character in REGEX %s\n",
12138 return CMD_WARNING_CONFIG_FAILED
;
12141 regex
= bgp_regcomp(regstr
);
12143 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12144 return CMD_WARNING
;
12147 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
12148 bgp_regex_free(regex
);
12152 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12153 const char *prefix_list_str
, afi_t afi
,
12154 safi_t safi
, enum bgp_show_type type
)
12156 struct prefix_list
*plist
;
12157 uint8_t show_flags
= 0;
12159 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12160 if (plist
== NULL
) {
12161 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12163 return CMD_WARNING
;
12166 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
12169 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12170 const char *filter
, afi_t afi
, safi_t safi
,
12171 enum bgp_show_type type
)
12173 struct as_list
*as_list
;
12174 uint8_t show_flags
= 0;
12176 as_list
= as_list_lookup(filter
);
12177 if (as_list
== NULL
) {
12178 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12180 return CMD_WARNING
;
12183 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
12186 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12187 const char *rmap_str
, afi_t afi
, safi_t safi
,
12188 enum bgp_show_type type
)
12190 struct route_map
*rmap
;
12191 uint8_t show_flags
= 0;
12193 rmap
= route_map_lookup_by_name(rmap_str
);
12195 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12196 return CMD_WARNING
;
12199 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
12202 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12203 const char *comstr
, int exact
, afi_t afi
,
12204 safi_t safi
, uint8_t show_flags
)
12206 struct community
*com
;
12209 com
= community_str2com(comstr
);
12211 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12212 return CMD_WARNING
;
12215 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12216 (exact
? bgp_show_type_community_exact
12217 : bgp_show_type_community
),
12219 community_free(&com
);
12224 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12225 const char *com
, int exact
, afi_t afi
,
12228 struct community_list
*list
;
12229 uint8_t show_flags
= 0;
12231 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12232 if (list
== NULL
) {
12233 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12234 return CMD_WARNING
;
12237 return bgp_show(vty
, bgp
, afi
, safi
,
12238 (exact
? bgp_show_type_community_list_exact
12239 : bgp_show_type_community_list
),
12243 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12244 const char *prefix
, afi_t afi
, safi_t safi
,
12245 enum bgp_show_type type
)
12249 uint8_t show_flags
= 0;
12253 ret
= str2prefix(prefix
, p
);
12255 vty_out(vty
, "%% Malformed Prefix\n");
12256 return CMD_WARNING
;
12259 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
12265 BGP_STATS_MAXBITLEN
= 0,
12267 BGP_STATS_PREFIXES
,
12269 BGP_STATS_UNAGGREGATEABLE
,
12270 BGP_STATS_MAX_AGGREGATEABLE
,
12271 BGP_STATS_AGGREGATES
,
12273 BGP_STATS_ASPATH_COUNT
,
12274 BGP_STATS_ASPATH_MAXHOPS
,
12275 BGP_STATS_ASPATH_TOTHOPS
,
12276 BGP_STATS_ASPATH_MAXSIZE
,
12277 BGP_STATS_ASPATH_TOTSIZE
,
12278 BGP_STATS_ASN_HIGHEST
,
12282 #define TABLE_STATS_IDX_VTY 0
12283 #define TABLE_STATS_IDX_JSON 1
12285 static const char *table_stats_strs
[][2] = {
12286 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12287 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12288 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12289 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12290 "unaggregateablePrefixes"},
12291 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12292 "maximumAggregateablePrefixes"},
12293 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12294 "bgpAggregateAdvertisements"},
12295 [BGP_STATS_SPACE
] = {"Address space advertised",
12296 "addressSpaceAdvertised"},
12297 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12298 "advertisementsWithPaths"},
12299 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12301 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12303 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12304 "averageAsPathLengthHops"},
12305 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12306 "averageAsPathSizeBytes"},
12307 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12308 [BGP_STATS_MAX
] = {NULL
, NULL
}
12311 struct bgp_table_stats
{
12312 struct bgp_table
*table
;
12313 unsigned long long counts
[BGP_STATS_MAX
];
12314 double total_space
;
12317 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12318 struct bgp_table_stats
*ts
, unsigned int space
)
12320 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12321 struct bgp_path_info
*pi
;
12322 const struct prefix
*rn_p
;
12324 if (!bgp_dest_has_bgp_path_info_data(dest
))
12327 rn_p
= bgp_dest_get_prefix(dest
);
12328 ts
->counts
[BGP_STATS_PREFIXES
]++;
12329 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12331 /* check if the prefix is included by any other announcements */
12332 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12333 pdest
= bgp_dest_parent_nolock(pdest
);
12335 if (pdest
== NULL
|| pdest
== top
) {
12336 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12337 /* announced address space */
12339 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12340 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12341 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12344 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12345 ts
->counts
[BGP_STATS_RIB
]++;
12347 if (CHECK_FLAG(pi
->attr
->flag
,
12348 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12349 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12351 /* as-path stats */
12352 if (pi
->attr
->aspath
) {
12353 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12354 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12355 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12357 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12359 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12360 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12362 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12363 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12365 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12366 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12367 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12368 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12373 static int bgp_table_stats_walker(struct thread
*t
)
12375 struct bgp_dest
*dest
, *ndest
;
12376 struct bgp_dest
*top
;
12377 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12378 unsigned int space
= 0;
12380 if (!(top
= bgp_table_top(ts
->table
)))
12383 switch (ts
->table
->afi
) {
12385 space
= IPV4_MAX_BITLEN
;
12388 space
= IPV6_MAX_BITLEN
;
12394 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12396 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12397 if (ts
->table
->safi
== SAFI_MPLS_VPN
12398 || ts
->table
->safi
== SAFI_ENCAP
12399 || ts
->table
->safi
== SAFI_EVPN
) {
12400 struct bgp_table
*table
;
12402 table
= bgp_dest_get_bgp_table_info(dest
);
12406 top
= bgp_table_top(table
);
12407 for (ndest
= bgp_table_top(table
); ndest
;
12408 ndest
= bgp_route_next(ndest
))
12409 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12411 bgp_table_stats_rn(dest
, top
, ts
, space
);
12418 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12419 struct json_object
*json_array
)
12421 struct listnode
*node
, *nnode
;
12424 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12425 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12428 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12429 safi_t safi
, struct json_object
*json_array
)
12431 struct bgp_table_stats ts
;
12433 int ret
= CMD_SUCCESS
;
12435 struct json_object
*json
= NULL
;
12438 json
= json_object_new_object();
12440 if (!bgp
->rib
[afi
][safi
]) {
12441 char warning_msg
[50];
12443 snprintf(warning_msg
, sizeof(warning_msg
),
12444 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12448 vty_out(vty
, "%s\n", warning_msg
);
12450 json_object_string_add(json
, "warning", warning_msg
);
12453 goto end_table_stats
;
12457 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12458 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12460 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12462 /* labeled-unicast routes live in the unicast table */
12463 if (safi
== SAFI_LABELED_UNICAST
)
12464 safi
= SAFI_UNICAST
;
12466 memset(&ts
, 0, sizeof(ts
));
12467 ts
.table
= bgp
->rib
[afi
][safi
];
12468 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12470 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12471 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12472 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12476 case BGP_STATS_ASPATH_TOTHOPS
:
12477 case BGP_STATS_ASPATH_TOTSIZE
:
12480 temp_buf
, sizeof(temp_buf
), "%12.2f",
12482 ? (float)ts
.counts
[i
]
12484 [BGP_STATS_ASPATH_COUNT
]
12486 vty_out(vty
, "%-30s: %s",
12487 table_stats_strs
[i
]
12488 [TABLE_STATS_IDX_VTY
],
12491 json_object_double_add(
12493 table_stats_strs
[i
]
12494 [TABLE_STATS_IDX_JSON
],
12496 ? (double)ts
.counts
[i
]
12497 / (double)ts
.counts
12498 [BGP_STATS_ASPATH_COUNT
]
12502 case BGP_STATS_TOTPLEN
:
12505 temp_buf
, sizeof(temp_buf
), "%12.2f",
12507 ? (float)ts
.counts
[i
]
12509 [BGP_STATS_PREFIXES
]
12511 vty_out(vty
, "%-30s: %s",
12512 table_stats_strs
[i
]
12513 [TABLE_STATS_IDX_VTY
],
12516 json_object_double_add(
12518 table_stats_strs
[i
]
12519 [TABLE_STATS_IDX_JSON
],
12521 ? (double)ts
.counts
[i
]
12522 / (double)ts
.counts
12523 [BGP_STATS_PREFIXES
]
12527 case BGP_STATS_SPACE
:
12529 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12531 vty_out(vty
, "%-30s: %s\n",
12532 table_stats_strs
[i
]
12533 [TABLE_STATS_IDX_VTY
],
12536 json_object_double_add(
12538 table_stats_strs
[i
]
12539 [TABLE_STATS_IDX_JSON
],
12540 (double)ts
.total_space
);
12542 if (afi
== AFI_IP6
) {
12544 snprintf(temp_buf
, sizeof(temp_buf
),
12547 * pow(2.0, -128 + 32));
12548 vty_out(vty
, "%30s: %s\n",
12549 "/32 equivalent %s\n",
12552 json_object_double_add(
12553 json
, "/32equivalent",
12554 (double)(ts
.total_space
12559 snprintf(temp_buf
, sizeof(temp_buf
),
12562 * pow(2.0, -128 + 48));
12563 vty_out(vty
, "%30s: %s\n",
12564 "/48 equivalent %s\n",
12567 json_object_double_add(
12568 json
, "/48equivalent",
12569 (double)(ts
.total_space
12575 snprintf(temp_buf
, sizeof(temp_buf
),
12577 ts
.total_space
* 100.
12579 vty_out(vty
, "%30s: %s\n",
12580 "% announced ", temp_buf
);
12582 json_object_double_add(
12583 json
, "%announced",
12584 (double)(ts
.total_space
* 100.
12588 snprintf(temp_buf
, sizeof(temp_buf
),
12591 * pow(2.0, -32 + 8));
12592 vty_out(vty
, "%30s: %s\n",
12593 "/8 equivalent ", temp_buf
);
12595 json_object_double_add(
12596 json
, "/8equivalent",
12597 (double)(ts
.total_space
12598 * pow(2.0, -32 + 8)));
12601 snprintf(temp_buf
, sizeof(temp_buf
),
12604 * pow(2.0, -32 + 24));
12605 vty_out(vty
, "%30s: %s\n",
12606 "/24 equivalent ", temp_buf
);
12608 json_object_double_add(
12609 json
, "/24equivalent",
12610 (double)(ts
.total_space
12611 * pow(2.0, -32 + 24)));
12617 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12619 vty_out(vty
, "%-30s: %s",
12620 table_stats_strs
[i
]
12621 [TABLE_STATS_IDX_VTY
],
12624 json_object_int_add(
12626 table_stats_strs
[i
]
12627 [TABLE_STATS_IDX_JSON
],
12632 vty_out(vty
, "\n");
12636 json_object_array_add(json_array
, json
);
12640 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12641 safi_t safi
, struct json_object
*json_array
)
12644 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12645 return CMD_SUCCESS
;
12648 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12660 PCOUNT_BPATH_SELECTED
,
12661 PCOUNT_PFCNT
, /* the figure we display to users */
12665 static const char *const pcount_strs
[] = {
12666 [PCOUNT_ADJ_IN
] = "Adj-in",
12667 [PCOUNT_DAMPED
] = "Damped",
12668 [PCOUNT_REMOVED
] = "Removed",
12669 [PCOUNT_HISTORY
] = "History",
12670 [PCOUNT_STALE
] = "Stale",
12671 [PCOUNT_VALID
] = "Valid",
12672 [PCOUNT_ALL
] = "All RIB",
12673 [PCOUNT_COUNTED
] = "PfxCt counted",
12674 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12675 [PCOUNT_PFCNT
] = "Useable",
12676 [PCOUNT_MAX
] = NULL
,
12679 struct peer_pcounts
{
12680 unsigned int count
[PCOUNT_MAX
];
12681 const struct peer
*peer
;
12682 const struct bgp_table
*table
;
12686 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12688 const struct bgp_adj_in
*ain
;
12689 const struct bgp_path_info
*pi
;
12690 const struct peer
*peer
= pc
->peer
;
12692 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12693 if (ain
->peer
== peer
)
12694 pc
->count
[PCOUNT_ADJ_IN
]++;
12696 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12698 if (pi
->peer
!= peer
)
12701 pc
->count
[PCOUNT_ALL
]++;
12703 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12704 pc
->count
[PCOUNT_DAMPED
]++;
12705 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12706 pc
->count
[PCOUNT_HISTORY
]++;
12707 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12708 pc
->count
[PCOUNT_REMOVED
]++;
12709 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12710 pc
->count
[PCOUNT_STALE
]++;
12711 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12712 pc
->count
[PCOUNT_VALID
]++;
12713 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12714 pc
->count
[PCOUNT_PFCNT
]++;
12715 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12716 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12718 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12719 pc
->count
[PCOUNT_COUNTED
]++;
12720 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12722 EC_LIB_DEVELOPMENT
,
12723 "Attempting to count but flags say it is unusable");
12725 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12727 EC_LIB_DEVELOPMENT
,
12728 "Not counted but flags say we should");
12733 static int bgp_peer_count_walker(struct thread
*t
)
12735 struct bgp_dest
*rn
, *rm
;
12736 const struct bgp_table
*table
;
12737 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12739 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12740 || pc
->safi
== SAFI_EVPN
) {
12741 /* Special handling for 2-level routing tables. */
12742 for (rn
= bgp_table_top(pc
->table
); rn
;
12743 rn
= bgp_route_next(rn
)) {
12744 table
= bgp_dest_get_bgp_table_info(rn
);
12746 for (rm
= bgp_table_top(table
); rm
;
12747 rm
= bgp_route_next(rm
))
12748 bgp_peer_count_proc(rm
, pc
);
12751 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
12752 bgp_peer_count_proc(rn
, pc
);
12757 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12758 safi_t safi
, bool use_json
)
12760 struct peer_pcounts pcounts
= {.peer
= peer
};
12762 json_object
*json
= NULL
;
12763 json_object
*json_loop
= NULL
;
12766 json
= json_object_new_object();
12767 json_loop
= json_object_new_object();
12770 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
12771 || !peer
->bgp
->rib
[afi
][safi
]) {
12773 json_object_string_add(
12775 "No such neighbor or address family");
12776 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12777 json_object_free(json
);
12778 json_object_free(json_loop
);
12780 vty_out(vty
, "%% No such neighbor or address family\n");
12782 return CMD_WARNING
;
12785 memset(&pcounts
, 0, sizeof(pcounts
));
12786 pcounts
.peer
= peer
;
12787 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
12788 pcounts
.safi
= safi
;
12790 /* in-place call via thread subsystem so as to record execution time
12791 * stats for the thread-walk (i.e. ensure this can't be blamed on
12792 * on just vty_read()).
12794 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
12797 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
12798 json_object_string_add(json
, "multiProtocol",
12799 get_afi_safi_str(afi
, safi
, true));
12800 json_object_int_add(json
, "pfxCounter",
12801 peer
->pcount
[afi
][safi
]);
12803 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12804 json_object_int_add(json_loop
, pcount_strs
[i
],
12807 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12809 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12810 json_object_string_add(json
, "pfxctDriftFor",
12812 json_object_string_add(
12813 json
, "recommended",
12814 "Please report this bug, with the above command output");
12816 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12817 json
, JSON_C_TO_STRING_PRETTY
));
12818 json_object_free(json
);
12822 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12823 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12824 peer
->hostname
, peer
->host
,
12825 get_afi_safi_str(afi
, safi
, false));
12827 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12828 get_afi_safi_str(afi
, safi
, false));
12831 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12832 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12834 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12835 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12838 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12839 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12841 "Please report this bug, with the above command output\n");
12845 return CMD_SUCCESS
;
12848 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12849 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12850 "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]",
12854 BGP_INSTANCE_HELP_STR
12857 "Detailed information on TCP and BGP neighbor connections\n"
12858 "Neighbor to display information about\n"
12859 "Neighbor to display information about\n"
12860 "Neighbor on BGP configured interface\n"
12861 "Display detailed prefix count information\n"
12864 afi_t afi
= AFI_IP6
;
12865 safi_t safi
= SAFI_UNICAST
;
12868 struct bgp
*bgp
= NULL
;
12869 bool uj
= use_json(argc
, argv
);
12874 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12877 return CMD_WARNING
;
12879 argv_find(argv
, argc
, "neighbors", &idx
);
12880 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12882 return CMD_WARNING
;
12884 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12887 #ifdef KEEP_OLD_VPN_COMMANDS
12888 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12889 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12890 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12895 "Display information about all VPNv4 NLRIs\n"
12896 "Detailed information on TCP and BGP neighbor connections\n"
12897 "Neighbor to display information about\n"
12898 "Neighbor to display information about\n"
12899 "Neighbor on BGP configured interface\n"
12900 "Display detailed prefix count information\n"
12905 bool uj
= use_json(argc
, argv
);
12907 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12909 return CMD_WARNING
;
12911 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12914 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12915 show_ip_bgp_vpn_all_route_prefix_cmd
,
12916 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12921 "Display information about all VPNv4 NLRIs\n"
12922 "Network in the BGP routing table to display\n"
12923 "Network in the BGP routing table to display\n"
12927 char *network
= NULL
;
12928 struct bgp
*bgp
= bgp_get_default();
12930 vty_out(vty
, "Can't find default instance\n");
12931 return CMD_WARNING
;
12934 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12935 network
= argv
[idx
]->arg
;
12936 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12937 network
= argv
[idx
]->arg
;
12939 vty_out(vty
, "Unable to figure out Network\n");
12940 return CMD_WARNING
;
12943 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12944 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12946 #endif /* KEEP_OLD_VPN_COMMANDS */
12948 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12949 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12950 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12955 "Network in the BGP routing table to display\n"
12956 "Network in the BGP routing table to display\n"
12957 "Network in the BGP routing table to display\n"
12958 "Network in the BGP routing table to display\n"
12962 char *network
= NULL
;
12963 int prefix_check
= 0;
12965 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12966 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12967 network
= argv
[idx
]->arg
;
12968 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12969 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12970 network
= argv
[idx
]->arg
;
12973 vty_out(vty
, "Unable to figure out Network\n");
12974 return CMD_WARNING
;
12976 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12977 prefix_check
, BGP_PATH_SHOW_ALL
,
12978 use_json(argc
, argv
));
12981 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12982 struct bgp_table
*table
, int *header1
,
12983 int *header2
, json_object
*json
,
12984 json_object
*json_scode
,
12985 json_object
*json_ocode
, bool wide
)
12987 uint64_t version
= table
? table
->version
: 0;
12988 char buf
[BUFSIZ
] = {0};
12992 json_object_int_add(json
, "bgpTableVersion", version
);
12993 json_object_string_add(json
, "bgpLocalRouterId",
12995 &bgp
->router_id
, buf
,
12997 json_object_int_add(json
, "defaultLocPrf",
12998 bgp
->default_local_pref
);
12999 json_object_int_add(json
, "localAS", bgp
->as
);
13000 json_object_object_add(json
, "bgpStatusCodes",
13002 json_object_object_add(json
, "bgpOriginCodes",
13006 "BGP table version is %" PRIu64
13007 ", local router ID is %pI4, vrf id ",
13008 version
, &bgp
->router_id
);
13009 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13010 vty_out(vty
, "%s", VRFID_NONE_STR
);
13012 vty_out(vty
, "%u", bgp
->vrf_id
);
13013 vty_out(vty
, "\n");
13014 vty_out(vty
, "Default local pref %u, ",
13015 bgp
->default_local_pref
);
13016 vty_out(vty
, "local AS %u\n", bgp
->as
);
13017 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13018 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13019 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13025 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13026 : BGP_SHOW_HEADER
));
13031 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13032 safi_t safi
, enum bgp_show_adj_route_type type
,
13033 const char *rmap_name
, json_object
*json
,
13034 uint8_t show_flags
)
13036 struct bgp_table
*table
;
13037 struct bgp_adj_in
*ain
;
13038 struct bgp_adj_out
*adj
;
13039 unsigned long output_count
= 0;
13040 unsigned long filtered_count
= 0;
13041 struct bgp_dest
*dest
;
13047 struct update_subgroup
*subgrp
;
13048 json_object
*json_scode
= NULL
;
13049 json_object
*json_ocode
= NULL
;
13050 json_object
*json_ar
= NULL
;
13051 struct peer_af
*paf
;
13052 bool route_filtered
;
13053 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13054 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13057 json_scode
= json_object_new_object();
13058 json_ocode
= json_object_new_object();
13059 json_ar
= json_object_new_object();
13061 json_object_string_add(json_scode
, "suppressed", "s");
13062 json_object_string_add(json_scode
, "damped", "d");
13063 json_object_string_add(json_scode
, "history", "h");
13064 json_object_string_add(json_scode
, "valid", "*");
13065 json_object_string_add(json_scode
, "best", ">");
13066 json_object_string_add(json_scode
, "multipath", "=");
13067 json_object_string_add(json_scode
, "internal", "i");
13068 json_object_string_add(json_scode
, "ribFailure", "r");
13069 json_object_string_add(json_scode
, "stale", "S");
13070 json_object_string_add(json_scode
, "removed", "R");
13072 json_object_string_add(json_ocode
, "igp", "i");
13073 json_object_string_add(json_ocode
, "egp", "e");
13074 json_object_string_add(json_ocode
, "incomplete", "?");
13081 json_object_string_add(json
, "alert", "no BGP");
13082 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13083 json_object_free(json
);
13085 vty_out(vty
, "%% No bgp\n");
13089 /* labeled-unicast routes live in the unicast table */
13090 if (safi
== SAFI_LABELED_UNICAST
)
13091 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13093 table
= bgp
->rib
[afi
][safi
];
13095 output_count
= filtered_count
= 0;
13096 subgrp
= peer_subgroup(peer
, afi
, safi
);
13098 if (type
== bgp_show_adj_route_advertised
&& subgrp
13099 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13100 char buf
[BUFSIZ
] = {0};
13103 json_object_int_add(json
, "bgpTableVersion",
13105 json_object_string_add(json
, "bgpLocalRouterId",
13107 &bgp
->router_id
, buf
,
13109 json_object_int_add(json
, "defaultLocPrf",
13110 bgp
->default_local_pref
);
13111 json_object_int_add(json
, "localAS", bgp
->as
);
13112 json_object_object_add(json
, "bgpStatusCodes",
13114 json_object_object_add(json
, "bgpOriginCodes",
13116 json_object_string_add(
13117 json
, "bgpOriginatingDefaultNetwork",
13118 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13121 "BGP table version is %" PRIu64
13122 ", local router ID is %pI4, vrf id ",
13123 table
->version
, &bgp
->router_id
);
13124 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13125 vty_out(vty
, "%s", VRFID_NONE_STR
);
13127 vty_out(vty
, "%u", bgp
->vrf_id
);
13128 vty_out(vty
, "\n");
13129 vty_out(vty
, "Default local pref %u, ",
13130 bgp
->default_local_pref
);
13131 vty_out(vty
, "local AS %u\n", bgp
->as
);
13132 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13133 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13134 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13136 vty_out(vty
, "Originating default network %s\n\n",
13137 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13142 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13143 if (type
== bgp_show_adj_route_received
13144 || type
== bgp_show_adj_route_filtered
) {
13145 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13146 if (ain
->peer
!= peer
)
13149 show_adj_route_header(
13150 vty
, bgp
, table
, &header1
, &header2
,
13151 json
, json_scode
, json_ocode
, wide
);
13154 route_filtered
= false;
13156 /* Filter prefix using distribute list,
13157 * filter list or prefix list
13159 const struct prefix
*rn_p
=
13160 bgp_dest_get_prefix(dest
);
13161 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13164 route_filtered
= true;
13166 /* Filter prefix using route-map */
13167 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13168 safi
, rmap_name
, NULL
,
13171 if (type
== bgp_show_adj_route_filtered
&&
13172 !route_filtered
&& ret
!= RMAP_DENY
) {
13173 bgp_attr_undup(&attr
, ain
->attr
);
13177 if (type
== bgp_show_adj_route_received
&&
13178 (route_filtered
|| ret
== RMAP_DENY
))
13181 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
13182 use_json
, json_ar
, wide
);
13183 bgp_attr_undup(&attr
, ain
->attr
);
13186 } else if (type
== bgp_show_adj_route_advertised
) {
13187 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13188 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13189 if (paf
->peer
!= peer
|| !adj
->attr
)
13192 show_adj_route_header(
13193 vty
, bgp
, table
, &header1
,
13194 &header2
, json
, json_scode
,
13197 const struct prefix
*rn_p
=
13198 bgp_dest_get_prefix(dest
);
13201 ret
= bgp_output_modifier(
13202 peer
, rn_p
, &attr
, afi
, safi
,
13205 if (ret
!= RMAP_DENY
) {
13207 vty
, rn_p
, &attr
, safi
,
13215 bgp_attr_undup(&attr
, adj
->attr
);
13217 } else if (type
== bgp_show_adj_route_bestpath
) {
13218 struct bgp_path_info
*pi
;
13220 show_adj_route_header(vty
, bgp
, table
, &header1
,
13221 &header2
, json
, json_scode
,
13224 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13226 if (pi
->peer
!= peer
)
13229 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13232 route_vty_out_tmp(vty
,
13233 bgp_dest_get_prefix(dest
),
13234 pi
->attr
, safi
, use_json
,
13242 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13243 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13244 json_object_int_add(json
, "filteredPrefixCounter",
13247 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
13248 json
, JSON_C_TO_STRING_PRETTY
));
13250 if (!output_count
&& !filtered_count
) {
13251 json_object_free(json_scode
);
13252 json_object_free(json_ocode
);
13255 json_object_free(json
);
13256 } else if (output_count
> 0) {
13257 if (filtered_count
> 0)
13259 "\nTotal number of prefixes %ld (%ld filtered)\n",
13260 output_count
, filtered_count
);
13262 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13267 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13268 safi_t safi
, enum bgp_show_adj_route_type type
,
13269 const char *rmap_name
, uint8_t show_flags
)
13271 json_object
*json
= NULL
;
13272 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13275 json
= json_object_new_object();
13277 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13279 json_object_string_add(
13281 "No such neighbor or address family");
13282 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13283 json_object_free(json
);
13285 vty_out(vty
, "%% No such neighbor or address family\n");
13287 return CMD_WARNING
;
13290 if ((type
== bgp_show_adj_route_received
13291 || type
== bgp_show_adj_route_filtered
)
13292 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13293 PEER_FLAG_SOFT_RECONFIG
)) {
13295 json_object_string_add(
13297 "Inbound soft reconfiguration not enabled");
13298 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13299 json_object_free(json
);
13302 "%% Inbound soft reconfiguration not enabled\n");
13304 return CMD_WARNING
;
13307 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, json
, show_flags
);
13309 return CMD_SUCCESS
;
13312 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13313 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13314 "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]",
13318 BGP_INSTANCE_HELP_STR
13320 BGP_SAFI_WITH_LABEL_HELP_STR
13321 "Detailed information on TCP and BGP neighbor connections\n"
13322 "Neighbor to display information about\n"
13323 "Neighbor to display information about\n"
13324 "Neighbor on BGP configured interface\n"
13325 "Display the routes selected by best path\n"
13327 "Increase table width for longer prefixes\n")
13329 afi_t afi
= AFI_IP6
;
13330 safi_t safi
= SAFI_UNICAST
;
13331 char *rmap_name
= NULL
;
13332 char *peerstr
= NULL
;
13333 struct bgp
*bgp
= NULL
;
13335 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13337 uint8_t show_flags
= 0;
13340 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13343 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13345 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13349 return CMD_WARNING
;
13351 argv_find(argv
, argc
, "neighbors", &idx
);
13352 peerstr
= argv
[++idx
]->arg
;
13354 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13356 return CMD_WARNING
;
13358 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13362 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13363 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13364 "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]",
13368 BGP_INSTANCE_HELP_STR
13370 BGP_SAFI_WITH_LABEL_HELP_STR
13371 "Display the entries for all address families\n"
13372 "Detailed information on TCP and BGP neighbor connections\n"
13373 "Neighbor to display information about\n"
13374 "Neighbor to display information about\n"
13375 "Neighbor on BGP configured interface\n"
13376 "Display the routes advertised to a BGP neighbor\n"
13377 "Display the received routes from neighbor\n"
13378 "Display the filtered routes received from neighbor\n"
13379 "Route-map to modify the attributes\n"
13380 "Name of the route map\n"
13382 "Increase table width for longer prefixes\n")
13384 afi_t afi
= AFI_IP6
;
13385 safi_t safi
= SAFI_UNICAST
;
13386 char *rmap_name
= NULL
;
13387 char *peerstr
= NULL
;
13388 struct bgp
*bgp
= NULL
;
13390 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13393 uint8_t show_flags
= 0;
13397 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13401 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13402 if (argv_find(argv
, argc
, "ipv4", &idx
))
13403 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13405 if (argv_find(argv
, argc
, "ipv6", &idx
))
13406 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13410 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13412 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13415 return CMD_WARNING
;
13417 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13418 argv_find(argv
, argc
, "neighbors", &idx
);
13419 peerstr
= argv
[++idx
]->arg
;
13421 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13423 return CMD_WARNING
;
13425 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13426 type
= bgp_show_adj_route_advertised
;
13427 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13428 type
= bgp_show_adj_route_received
;
13429 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13430 type
= bgp_show_adj_route_filtered
;
13432 if (argv_find(argv
, argc
, "route-map", &idx
))
13433 rmap_name
= argv
[++idx
]->arg
;
13436 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13439 vty_out(vty
, "{\n");
13441 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13442 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13443 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13445 FOREACH_SAFI (safi
) {
13446 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13453 vty_out(vty
, ",\n");
13454 vty_out(vty
, "\"%s\":",
13455 get_afi_safi_str(afi
, safi
, true));
13457 vty_out(vty
, "\nFor address family: %s\n",
13458 get_afi_safi_str(afi
, safi
, false));
13460 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13464 FOREACH_AFI_SAFI (afi
, safi
) {
13465 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13472 vty_out(vty
, ",\n");
13473 vty_out(vty
, "\"%s\":",
13474 get_afi_safi_str(afi
, safi
, true));
13476 vty_out(vty
, "\nFor address family: %s\n",
13477 get_afi_safi_str(afi
, safi
, false));
13479 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13484 vty_out(vty
, "}\n");
13486 return CMD_SUCCESS
;
13489 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13490 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13491 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13497 "Address Family modifier\n"
13498 "Detailed information on TCP and BGP neighbor connections\n"
13499 "Neighbor to display information about\n"
13500 "Neighbor to display information about\n"
13501 "Neighbor on BGP configured interface\n"
13502 "Display information received from a BGP neighbor\n"
13503 "Display the prefixlist filter\n"
13506 afi_t afi
= AFI_IP6
;
13507 safi_t safi
= SAFI_UNICAST
;
13508 char *peerstr
= NULL
;
13511 union sockunion su
;
13517 /* show [ip] bgp */
13518 if (argv_find(argv
, argc
, "ip", &idx
))
13520 /* [<ipv4|ipv6> [unicast]] */
13521 if (argv_find(argv
, argc
, "ipv4", &idx
))
13523 if (argv_find(argv
, argc
, "ipv6", &idx
))
13525 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13526 argv_find(argv
, argc
, "neighbors", &idx
);
13527 peerstr
= argv
[++idx
]->arg
;
13529 bool uj
= use_json(argc
, argv
);
13531 ret
= str2sockunion(peerstr
, &su
);
13533 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13536 vty_out(vty
, "{}\n");
13539 "%% Malformed address or name: %s\n",
13541 return CMD_WARNING
;
13544 peer
= peer_lookup(NULL
, &su
);
13547 vty_out(vty
, "{}\n");
13549 vty_out(vty
, "No peer\n");
13550 return CMD_WARNING
;
13554 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13555 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13558 vty_out(vty
, "Address Family: %s\n",
13559 get_afi_safi_str(afi
, safi
, false));
13560 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13563 vty_out(vty
, "{}\n");
13565 vty_out(vty
, "No functional output\n");
13568 return CMD_SUCCESS
;
13571 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13572 afi_t afi
, safi_t safi
,
13573 enum bgp_show_type type
, bool use_json
)
13575 uint8_t show_flags
= 0;
13578 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13580 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13582 json_object
*json_no
= NULL
;
13583 json_no
= json_object_new_object();
13584 json_object_string_add(
13585 json_no
, "warning",
13586 "No such neighbor or address family");
13587 vty_out(vty
, "%s\n",
13588 json_object_to_json_string(json_no
));
13589 json_object_free(json_no
);
13591 vty_out(vty
, "%% No such neighbor or address family\n");
13592 return CMD_WARNING
;
13595 /* labeled-unicast routes live in the unicast table */
13596 if (safi
== SAFI_LABELED_UNICAST
)
13597 safi
= SAFI_UNICAST
;
13599 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
13602 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13603 show_ip_bgp_flowspec_routes_detailed_cmd
,
13604 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13608 BGP_INSTANCE_HELP_STR
13611 "Detailed information on flowspec entries\n"
13614 afi_t afi
= AFI_IP
;
13615 safi_t safi
= SAFI_UNICAST
;
13616 struct bgp
*bgp
= NULL
;
13618 bool uj
= use_json(argc
, argv
);
13619 uint8_t show_flags
= 0;
13623 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13626 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13629 return CMD_WARNING
;
13631 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13635 DEFUN (show_ip_bgp_neighbor_routes
,
13636 show_ip_bgp_neighbor_routes_cmd
,
13637 "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]",
13641 BGP_INSTANCE_HELP_STR
13643 BGP_SAFI_WITH_LABEL_HELP_STR
13644 "Detailed information on TCP and BGP neighbor connections\n"
13645 "Neighbor to display information about\n"
13646 "Neighbor to display information about\n"
13647 "Neighbor on BGP configured interface\n"
13648 "Display flap statistics of the routes learned from neighbor\n"
13649 "Display the dampened routes received from neighbor\n"
13650 "Display routes learned from neighbor\n"
13653 char *peerstr
= NULL
;
13654 struct bgp
*bgp
= NULL
;
13655 afi_t afi
= AFI_IP6
;
13656 safi_t safi
= SAFI_UNICAST
;
13658 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
13660 bool uj
= use_json(argc
, argv
);
13665 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13668 return CMD_WARNING
;
13670 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13671 argv_find(argv
, argc
, "neighbors", &idx
);
13672 peerstr
= argv
[++idx
]->arg
;
13674 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13676 return CMD_WARNING
;
13678 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
13679 sh_type
= bgp_show_type_flap_neighbor
;
13680 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
13681 sh_type
= bgp_show_type_damp_neighbor
;
13682 else if (argv_find(argv
, argc
, "routes", &idx
))
13683 sh_type
= bgp_show_type_neighbor
;
13685 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
13688 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
13690 struct bgp_distance
{
13691 /* Distance value for the IP source prefix. */
13694 /* Name of the access-list to be matched. */
13698 DEFUN (show_bgp_afi_vpn_rd_route
,
13699 show_bgp_afi_vpn_rd_route_cmd
,
13700 "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]",
13704 "Address Family modifier\n"
13705 "Display information for a route distinguisher\n"
13706 "Route Distinguisher\n"
13707 "Network in the BGP routing table to display\n"
13708 "Network in the BGP routing table to display\n"
13712 struct prefix_rd prd
;
13713 afi_t afi
= AFI_MAX
;
13716 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
13717 vty_out(vty
, "%% Malformed Address Family\n");
13718 return CMD_WARNING
;
13721 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
13723 vty_out(vty
, "%% Malformed Route Distinguisher\n");
13724 return CMD_WARNING
;
13727 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
13728 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
13731 static struct bgp_distance
*bgp_distance_new(void)
13733 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
13736 static void bgp_distance_free(struct bgp_distance
*bdistance
)
13738 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
13741 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
13742 const char *access_list_str
, afi_t afi
, safi_t safi
,
13743 char *errmsg
, size_t errmsg_len
)
13747 struct bgp_dest
*dest
;
13748 struct bgp_distance
*bdistance
;
13750 ret
= str2prefix(ip_str
, &p
);
13752 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13753 return CMD_WARNING_CONFIG_FAILED
;
13756 /* Get BGP distance node. */
13757 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
13758 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13760 bgp_dest_unlock_node(dest
);
13762 bdistance
= bgp_distance_new();
13763 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
13766 /* Set distance value. */
13767 bdistance
->distance
= distance
;
13769 /* Reset access-list configuration. */
13770 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13771 if (access_list_str
)
13772 bdistance
->access_list
=
13773 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
13775 return CMD_SUCCESS
;
13778 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
13779 const char *access_list_str
, afi_t afi
, safi_t safi
,
13780 char *errmsg
, size_t errmsg_len
)
13784 struct bgp_dest
*dest
;
13785 struct bgp_distance
*bdistance
;
13787 ret
= str2prefix(ip_str
, &p
);
13789 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13790 return CMD_WARNING_CONFIG_FAILED
;
13793 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13795 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
13796 return CMD_WARNING_CONFIG_FAILED
;
13799 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13801 if (bdistance
->distance
!= distance
) {
13802 snprintf(errmsg
, errmsg_len
,
13803 "Distance does not match configured\n");
13804 return CMD_WARNING_CONFIG_FAILED
;
13807 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13808 bgp_distance_free(bdistance
);
13810 bgp_dest_set_bgp_path_info(dest
, NULL
);
13811 bgp_dest_unlock_node(dest
);
13812 bgp_dest_unlock_node(dest
);
13814 return CMD_SUCCESS
;
13817 /* Apply BGP information to distance method. */
13818 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13819 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13821 struct bgp_dest
*dest
;
13822 struct prefix q
= {0};
13824 struct bgp_distance
*bdistance
;
13825 struct access_list
*alist
;
13826 struct bgp_static
*bgp_static
;
13831 peer
= pinfo
->peer
;
13833 if (pinfo
->attr
->distance
)
13834 return pinfo
->attr
->distance
;
13836 /* Check source address.
13837 * Note: for aggregate route, peer can have unspec af type.
13839 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
13840 && !sockunion2hostprefix(&peer
->su
, &q
))
13843 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13845 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13846 bgp_dest_unlock_node(dest
);
13848 if (bdistance
->access_list
) {
13849 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13851 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13852 return bdistance
->distance
;
13854 return bdistance
->distance
;
13857 /* Backdoor check. */
13858 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
13860 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13861 bgp_dest_unlock_node(dest
);
13863 if (bgp_static
->backdoor
) {
13864 if (bgp
->distance_local
[afi
][safi
])
13865 return bgp
->distance_local
[afi
][safi
];
13867 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13871 if (peer
->sort
== BGP_PEER_EBGP
) {
13872 if (bgp
->distance_ebgp
[afi
][safi
])
13873 return bgp
->distance_ebgp
[afi
][safi
];
13874 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
13875 } else if (peer
->sort
== BGP_PEER_IBGP
) {
13876 if (bgp
->distance_ibgp
[afi
][safi
])
13877 return bgp
->distance_ibgp
[afi
][safi
];
13878 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13880 if (bgp
->distance_local
[afi
][safi
])
13881 return bgp
->distance_local
[afi
][safi
];
13882 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13886 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13887 * we should tell ZEBRA update the routes for a specific
13888 * AFI/SAFI to reflect changes in RIB.
13890 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
13891 safi_t update_safi
)
13896 FOREACH_AFI_SAFI (afi
, safi
) {
13897 if (!bgp_fibupd_safi(safi
))
13900 if (afi
!= update_afi
&& safi
!= update_safi
)
13903 if (BGP_DEBUG(zebra
, ZEBRA
))
13905 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13906 __func__
, afi
, safi
);
13907 bgp_zebra_announce_table(bgp
, afi
, safi
);
13911 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
13912 "distance bgp (1-255) (1-255) (1-255)",
13913 "Define an administrative distance\n"
13915 "Distance for routes external to the AS\n"
13916 "Distance for routes internal to the AS\n"
13917 "Distance for local routes\n")
13919 int idx_number
= 2;
13920 int idx_number_2
= 3;
13921 int idx_number_3
= 4;
13924 char xpath
[XPATH_MAXLEN
];
13926 afi
= bgp_node_afi(vty
);
13927 safi
= bgp_node_safi(vty
);
13930 xpath
, sizeof(xpath
),
13931 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13932 yang_afi_safi_value2identity(afi
, safi
),
13933 bgp_afi_safi_get_container_str(afi
, safi
));
13934 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
13936 xpath
, sizeof(xpath
),
13937 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13938 yang_afi_safi_value2identity(afi
, safi
),
13939 bgp_afi_safi_get_container_str(afi
, safi
));
13940 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
13941 argv
[idx_number_2
]->arg
);
13943 xpath
, sizeof(xpath
),
13944 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13945 yang_afi_safi_value2identity(afi
, safi
),
13946 bgp_afi_safi_get_container_str(afi
, safi
));
13948 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
13949 argv
[idx_number_3
]->arg
);
13951 return nb_cli_apply_changes(vty
, NULL
);
13954 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
13955 "no distance bgp [(1-255) (1-255) (1-255)]",
13957 "Define an administrative distance\n"
13959 "Distance for routes external to the AS\n"
13960 "Distance for routes internal to the AS\n"
13961 "Distance for local routes\n")
13965 char xpath
[XPATH_MAXLEN
];
13967 afi
= bgp_node_afi(vty
);
13968 safi
= bgp_node_safi(vty
);
13971 xpath
, sizeof(xpath
),
13972 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13973 yang_afi_safi_value2identity(afi
, safi
),
13974 bgp_afi_safi_get_container_str(afi
, safi
));
13975 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
13977 xpath
, sizeof(xpath
),
13978 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13979 yang_afi_safi_value2identity(afi
, safi
),
13980 bgp_afi_safi_get_container_str(afi
, safi
));
13981 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
13983 xpath
, sizeof(xpath
),
13984 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13985 yang_afi_safi_value2identity(afi
, safi
),
13986 bgp_afi_safi_get_container_str(afi
, safi
));
13988 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
13990 return nb_cli_apply_changes(vty
, NULL
);
13993 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
13994 struct lyd_node
*dnode
,
13995 bool show_defaults
)
13997 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
13999 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14000 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14001 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14003 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14007 DEFPY_YANG(bgp_distance_source
,
14008 bgp_distance_source_cmd
,
14009 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14011 "Define an administrative distance\n"
14013 "IPv4 source prefix\n"
14014 "IPv6 source prefix\n"
14015 "Access list name\n")
14019 char xpath
[XPATH_MAXLEN
];
14021 afi
= bgp_node_afi(vty
);
14022 safi
= bgp_node_safi(vty
);
14025 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14026 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14029 nb_cli_enqueue_change(vty
,
14030 "./access-list-policy-export",
14031 NB_OP_CREATE
, acl
);
14033 nb_cli_enqueue_change(vty
,
14034 "./access-list-policy-export",
14035 NB_OP_DESTROY
, NULL
);
14037 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14041 xpath
, sizeof(xpath
),
14042 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14043 yang_afi_safi_value2identity(afi
, safi
),
14044 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14046 return nb_cli_apply_changes(vty
, xpath
);
14049 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14050 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14052 vty_out(vty
, " distance %d %s %s\n",
14053 yang_dnode_get_uint8(dnode
, "./distance"),
14054 yang_dnode_get_string(dnode
, "./prefix"),
14055 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14056 ? yang_dnode_get_string(dnode
,
14057 "./access-list-policy-export")
14062 bgp_dampening
, bgp_dampening_cmd
,
14063 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14065 "BGP Specific commands\n"
14066 "Enable route-flap dampening\n"
14067 "Half-life time for the penalty\n"
14068 "Value to start reusing a route\n"
14069 "Value to start suppressing a route\n"
14070 "Maximum duration to suppress a stable route\n")
14074 char xpath
[XPATH_MAXLEN
];
14076 afi
= bgp_node_afi(vty
);
14077 safi
= bgp_node_safi(vty
);
14080 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14082 nb_cli_enqueue_change(vty
, "./reach-decay",
14083 NB_OP_MODIFY
, halflife_str
);
14084 nb_cli_enqueue_change(vty
, "./reuse-above",
14085 NB_OP_MODIFY
, reuse_str
);
14086 nb_cli_enqueue_change(vty
, "./suppress-above",
14087 NB_OP_MODIFY
, suppress_str
);
14088 nb_cli_enqueue_change(vty
, "./unreach-decay",
14089 NB_OP_MODIFY
, max_suppress_str
);
14091 nb_cli_enqueue_change(vty
, "./reach-decay",
14092 NB_OP_MODIFY
, halflife_str
);
14095 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14099 xpath
, sizeof(xpath
),
14100 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14101 yang_afi_safi_value2identity(afi
, safi
),
14102 bgp_afi_safi_get_container_str(afi
, safi
));
14104 return nb_cli_apply_changes(vty
, xpath
);
14107 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14108 struct lyd_node
*dnode
,
14109 bool show_defaults
)
14111 if (!yang_dnode_get_bool(dnode
, "./enable"))
14114 int half
= DEFAULT_HALF_LIFE
* 60;
14115 int reuse
= DEFAULT_REUSE
;
14116 int suppress
= DEFAULT_SUPPRESS
;
14119 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14120 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14121 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14122 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14124 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14125 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14126 vty_out(vty
, " bgp dampening\n");
14127 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14128 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14129 vty_out(vty
, " bgp dampening %u\n", half
);
14131 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14135 /* Display specified route of BGP table. */
14136 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14137 const char *ip_str
, afi_t afi
, safi_t safi
,
14138 struct prefix_rd
*prd
, int prefix_check
)
14141 struct prefix match
;
14142 struct bgp_dest
*dest
;
14143 struct bgp_dest
*rm
;
14144 struct bgp_path_info
*pi
;
14145 struct bgp_path_info
*pi_temp
;
14147 struct bgp_table
*table
;
14149 /* BGP structure lookup. */
14151 bgp
= bgp_lookup_by_name(view_name
);
14153 vty_out(vty
, "%% Can't find BGP instance %s\n",
14155 return CMD_WARNING
;
14158 bgp
= bgp_get_default();
14160 vty_out(vty
, "%% No BGP process is configured\n");
14161 return CMD_WARNING
;
14165 /* Check IP address argument. */
14166 ret
= str2prefix(ip_str
, &match
);
14168 vty_out(vty
, "%% address is malformed\n");
14169 return CMD_WARNING
;
14172 match
.family
= afi2family(afi
);
14174 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14175 || (safi
== SAFI_EVPN
)) {
14176 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14177 dest
= bgp_route_next(dest
)) {
14178 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14180 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14182 table
= bgp_dest_get_bgp_table_info(dest
);
14185 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
14188 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14191 || rm_p
->prefixlen
== match
.prefixlen
) {
14192 pi
= bgp_dest_get_bgp_path_info(rm
);
14194 if (pi
->extra
&& pi
->extra
->damp_info
) {
14195 pi_temp
= pi
->next
;
14196 bgp_damp_info_free(
14197 &pi
->extra
->damp_info
,
14198 &bgp
->damp
[afi
][safi
],
14206 bgp_dest_unlock_node(rm
);
14209 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
14211 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14214 || dest_p
->prefixlen
== match
.prefixlen
) {
14215 pi
= bgp_dest_get_bgp_path_info(dest
);
14217 if (pi
->extra
&& pi
->extra
->damp_info
) {
14218 pi_temp
= pi
->next
;
14219 bgp_damp_info_free(
14220 &pi
->extra
->damp_info
,
14221 &bgp
->damp
[afi
][safi
],
14229 bgp_dest_unlock_node(dest
);
14233 return CMD_SUCCESS
;
14236 DEFUN (clear_ip_bgp_dampening
,
14237 clear_ip_bgp_dampening_cmd
,
14238 "clear ip bgp dampening",
14242 "Clear route flap dampening information\n")
14244 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14245 bgp_damp_info_clean(&bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14247 return CMD_SUCCESS
;
14250 DEFUN (clear_ip_bgp_dampening_prefix
,
14251 clear_ip_bgp_dampening_prefix_cmd
,
14252 "clear ip bgp dampening A.B.C.D/M",
14256 "Clear route flap dampening information\n"
14259 int idx_ipv4_prefixlen
= 4;
14260 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14261 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14264 DEFUN (clear_ip_bgp_dampening_address
,
14265 clear_ip_bgp_dampening_address_cmd
,
14266 "clear ip bgp dampening A.B.C.D",
14270 "Clear route flap dampening information\n"
14271 "Network to clear damping information\n")
14274 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14275 SAFI_UNICAST
, NULL
, 0);
14278 DEFUN (clear_ip_bgp_dampening_address_mask
,
14279 clear_ip_bgp_dampening_address_mask_cmd
,
14280 "clear ip bgp dampening A.B.C.D A.B.C.D",
14284 "Clear route flap dampening information\n"
14285 "Network to clear damping information\n"
14289 int idx_ipv4_2
= 5;
14291 char prefix_str
[BUFSIZ
];
14293 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14296 vty_out(vty
, "%% Inconsistent address and mask\n");
14297 return CMD_WARNING
;
14300 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14304 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14306 struct vty
*vty
= arg
;
14307 struct peer
*peer
= bucket
->data
;
14308 char buf
[SU_ADDRSTRLEN
];
14310 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14311 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14314 DEFUN (show_bgp_listeners
,
14315 show_bgp_listeners_cmd
,
14316 "show bgp listeners",
14319 "Display Listen Sockets and who created them\n")
14321 bgp_dump_listener_info(vty
);
14323 return CMD_SUCCESS
;
14326 DEFUN (show_bgp_peerhash
,
14327 show_bgp_peerhash_cmd
,
14328 "show bgp peerhash",
14331 "Display information about the BGP peerhash\n")
14333 struct list
*instances
= bm
->bgp
;
14334 struct listnode
*node
;
14337 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14338 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14339 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14343 return CMD_SUCCESS
;
14346 /* also used for encap safi */
14347 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14348 afi_t afi
, safi_t safi
)
14350 struct bgp_dest
*pdest
;
14351 struct bgp_dest
*dest
;
14352 struct bgp_table
*table
;
14353 const struct prefix
*p
;
14354 const struct prefix_rd
*prd
;
14355 struct bgp_static
*bgp_static
;
14356 mpls_label_t label
;
14357 char rdbuf
[RD_ADDRSTRLEN
];
14359 /* Network configuration. */
14360 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14361 pdest
= bgp_route_next(pdest
)) {
14362 table
= bgp_dest_get_bgp_table_info(pdest
);
14366 for (dest
= bgp_table_top(table
); dest
;
14367 dest
= bgp_route_next(dest
)) {
14368 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14369 if (bgp_static
== NULL
)
14372 p
= bgp_dest_get_prefix(dest
);
14373 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14376 /* "network" configuration display. */
14377 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14378 label
= decode_label(&bgp_static
->label
);
14380 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14381 if (safi
== SAFI_MPLS_VPN
)
14382 vty_out(vty
, " label %u", label
);
14384 if (bgp_static
->rmap
.name
)
14385 vty_out(vty
, " route-map %s",
14386 bgp_static
->rmap
.name
);
14388 if (bgp_static
->backdoor
)
14389 vty_out(vty
, " backdoor");
14391 vty_out(vty
, "\n");
14396 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14397 afi_t afi
, safi_t safi
)
14399 struct bgp_dest
*pdest
;
14400 struct bgp_dest
*dest
;
14401 struct bgp_table
*table
;
14402 const struct prefix
*p
;
14403 const struct prefix_rd
*prd
;
14404 struct bgp_static
*bgp_static
;
14405 char buf
[PREFIX_STRLEN
* 2];
14406 char buf2
[SU_ADDRSTRLEN
];
14407 char rdbuf
[RD_ADDRSTRLEN
];
14408 char esi_buf
[ESI_BYTES
];
14410 /* Network configuration. */
14411 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14412 pdest
= bgp_route_next(pdest
)) {
14413 table
= bgp_dest_get_bgp_table_info(pdest
);
14417 for (dest
= bgp_table_top(table
); dest
;
14418 dest
= bgp_route_next(dest
)) {
14419 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14420 if (bgp_static
== NULL
)
14423 char *macrouter
= NULL
;
14425 if (bgp_static
->router_mac
)
14426 macrouter
= prefix_mac2str(
14427 bgp_static
->router_mac
, NULL
, 0);
14428 if (bgp_static
->eth_s_id
)
14429 esi_to_str(bgp_static
->eth_s_id
,
14430 esi_buf
, sizeof(esi_buf
));
14431 p
= bgp_dest_get_prefix(dest
);
14432 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14434 /* "network" configuration display. */
14435 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14436 if (p
->u
.prefix_evpn
.route_type
== 5) {
14437 char local_buf
[PREFIX_STRLEN
];
14438 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14439 struct prefix_evpn
*)p
)
14443 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14444 local_buf
, PREFIX_STRLEN
);
14445 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14446 p
->u
.prefix_evpn
.prefix_addr
14447 .ip_prefix_length
);
14449 prefix2str(p
, buf
, sizeof(buf
));
14452 if (bgp_static
->gatewayIp
.family
== AF_INET
14453 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14454 inet_ntop(bgp_static
->gatewayIp
.family
,
14455 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14458 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14460 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14461 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14464 XFREE(MTYPE_TMP
, macrouter
);
14469 /* Configuration of static route announcement and aggregate
14471 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14474 struct bgp_dest
*dest
;
14475 const struct prefix
*p
;
14476 struct bgp_static
*bgp_static
;
14477 struct bgp_aggregate
*bgp_aggregate
;
14479 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14480 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14484 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14485 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14489 /* Network configuration. */
14490 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14491 dest
= bgp_route_next(dest
)) {
14492 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14493 if (bgp_static
== NULL
)
14496 p
= bgp_dest_get_prefix(dest
);
14498 vty_out(vty
, " network %pFX", p
);
14500 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14501 vty_out(vty
, " label-index %u",
14502 bgp_static
->label_index
);
14504 if (bgp_static
->rmap
.name
)
14505 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14507 if (bgp_static
->backdoor
)
14508 vty_out(vty
, " backdoor");
14510 vty_out(vty
, "\n");
14513 /* Aggregate-address configuration. */
14514 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14515 dest
= bgp_route_next(dest
)) {
14516 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14517 if (bgp_aggregate
== NULL
)
14520 p
= bgp_dest_get_prefix(dest
);
14522 vty_out(vty
, " aggregate-address %pFX", p
);
14524 if (bgp_aggregate
->as_set
)
14525 vty_out(vty
, " as-set");
14527 if (bgp_aggregate
->summary_only
)
14528 vty_out(vty
, " summary-only");
14530 if (bgp_aggregate
->rmap
.name
)
14531 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14533 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14534 vty_out(vty
, " origin %s",
14535 bgp_origin2str(bgp_aggregate
->origin
));
14537 if (bgp_aggregate
->match_med
)
14538 vty_out(vty
, " matching-MED-only");
14540 if (bgp_aggregate
->suppress_map_name
)
14541 vty_out(vty
, " suppress-map %s",
14542 bgp_aggregate
->suppress_map_name
);
14544 vty_out(vty
, "\n");
14548 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14551 struct bgp_dest
*dest
;
14552 struct bgp_distance
*bdistance
;
14554 /* Distance configuration. */
14555 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
14556 && bgp
->distance_local
[afi
][safi
]
14557 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
14558 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
14559 || bgp
->distance_local
[afi
][safi
]
14560 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
14561 vty_out(vty
, " distance bgp %d %d %d\n",
14562 bgp
->distance_ebgp
[afi
][safi
],
14563 bgp
->distance_ibgp
[afi
][safi
],
14564 bgp
->distance_local
[afi
][safi
]);
14567 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14568 dest
= bgp_route_next(dest
)) {
14569 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14570 if (bdistance
!= NULL
)
14571 vty_out(vty
, " distance %d %pBD %s\n",
14572 bdistance
->distance
, dest
,
14573 bdistance
->access_list
? bdistance
->access_list
14578 /* Allocate routing table structure and install commands. */
14579 void bgp_route_init(void)
14584 /* Init BGP distance table. */
14585 FOREACH_AFI_SAFI (afi
, safi
)
14586 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14588 /* IPv4 BGP commands. */
14589 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14590 install_element(BGP_NODE
, &bgp_network_cmd
);
14591 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14593 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14595 /* IPv4 unicast configuration. */
14596 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14597 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14598 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14600 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14602 /* IPv4 multicast configuration. */
14603 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14604 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14605 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14606 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14608 /* IPv4 labeled-unicast configuration. */
14609 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14610 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14612 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14613 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14614 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14615 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14616 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14617 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14618 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14619 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14621 install_element(VIEW_NODE
,
14622 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14623 install_element(VIEW_NODE
,
14624 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
14625 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
14626 install_element(VIEW_NODE
,
14627 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
14628 #ifdef KEEP_OLD_VPN_COMMANDS
14629 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
14630 #endif /* KEEP_OLD_VPN_COMMANDS */
14631 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
14632 install_element(VIEW_NODE
,
14633 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
14635 /* BGP dampening clear commands */
14636 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
14637 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
14639 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
14640 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
14643 install_element(ENABLE_NODE
,
14644 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
14645 #ifdef KEEP_OLD_VPN_COMMANDS
14646 install_element(ENABLE_NODE
,
14647 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
14648 #endif /* KEEP_OLD_VPN_COMMANDS */
14650 /* New config IPv6 BGP commands. */
14651 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
14652 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
14653 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
14655 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
14657 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
14659 /* IPv6 labeled unicast address family. */
14660 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
14661 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
14663 install_element(BGP_NODE
, &bgp_distance_cmd
);
14664 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
14665 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
14666 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
14667 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
14668 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
14669 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
14670 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
14671 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
14672 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
14673 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
14674 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
14675 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
14676 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
14677 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
14679 /* BGP dampening */
14680 install_element(BGP_NODE
, &bgp_dampening_cmd
);
14681 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
14682 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
14683 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
14684 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
14685 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
14686 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
14688 /* Large Communities */
14689 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
14690 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
14692 /* show bgp ipv4 flowspec detailed */
14693 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
14695 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
14696 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
14699 void bgp_route_finish(void)
14704 FOREACH_AFI_SAFI (afi
, safi
) {
14705 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
14706 bgp_distance_table
[afi
][safi
] = NULL
;