1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "sockunion.h"
38 #include "workqueue.h"
43 #include "lib_errors.h"
45 #include "bgpd/bgpd.h"
46 #include "bgpd/bgp_table.h"
47 #include "bgpd/bgp_route.h"
48 #include "bgpd/bgp_attr.h"
49 #include "bgpd/bgp_debug.h"
50 #include "bgpd/bgp_errors.h"
51 #include "bgpd/bgp_aspath.h"
52 #include "bgpd/bgp_regex.h"
53 #include "bgpd/bgp_community.h"
54 #include "bgpd/bgp_ecommunity.h"
55 #include "bgpd/bgp_lcommunity.h"
56 #include "bgpd/bgp_clist.h"
57 #include "bgpd/bgp_packet.h"
58 #include "bgpd/bgp_filter.h"
59 #include "bgpd/bgp_fsm.h"
60 #include "bgpd/bgp_mplsvpn.h"
61 #include "bgpd/bgp_nexthop.h"
62 #include "bgpd/bgp_damp.h"
63 #include "bgpd/bgp_advertise.h"
64 #include "bgpd/bgp_zebra.h"
65 #include "bgpd/bgp_vty.h"
66 #include "bgpd/bgp_mpath.h"
67 #include "bgpd/bgp_nht.h"
68 #include "bgpd/bgp_updgrp.h"
69 #include "bgpd/bgp_label.h"
70 #include "bgpd/bgp_addpath.h"
71 #include "bgpd/bgp_mac.h"
72 #include "bgpd/bgp_network.h"
73 #include "bgpd/bgp_trace.h"
76 #include "bgpd/rfapi/rfapi_backend.h"
77 #include "bgpd/rfapi/vnc_import_bgp.h"
78 #include "bgpd/rfapi/vnc_export_bgp.h"
80 #include "bgpd/bgp_encap_types.h"
81 #include "bgpd/bgp_encap_tlv.h"
82 #include "bgpd/bgp_evpn.h"
83 #include "bgpd/bgp_evpn_mh.h"
84 #include "bgpd/bgp_evpn_vty.h"
85 #include "bgpd/bgp_flowspec.h"
86 #include "bgpd/bgp_flowspec_util.h"
87 #include "bgpd/bgp_pbr.h"
88 #include "northbound.h"
89 #include "northbound_cli.h"
90 #include "bgpd/bgp_nb.h"
92 #ifndef VTYSH_EXTRACT_PL
93 #include "bgpd/bgp_route_clippy.c"
96 DEFINE_HOOK(bgp_snmp_update_stats
,
97 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
100 /* Extern from bgp_dump.c */
101 extern const char *bgp_origin_str
[];
102 extern const char *bgp_origin_long_str
[];
105 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
106 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
107 static const struct message bgp_pmsi_tnltype_str
[] = {
108 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
109 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
110 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
111 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
112 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
113 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
114 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
115 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
119 #define VRFID_NONE_STR "-"
121 DEFINE_HOOK(bgp_process
,
122 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
123 struct peer
*peer
, bool withdraw
),
124 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
126 /** Test if path is suppressed. */
127 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
129 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
132 return listcount(pi
->extra
->aggr_suppressors
) > 0;
135 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
136 safi_t safi
, const struct prefix
*p
,
137 struct prefix_rd
*prd
)
139 struct bgp_dest
*dest
;
140 struct bgp_dest
*pdest
= NULL
;
144 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
145 || (safi
== SAFI_EVPN
)) {
146 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
148 if (!bgp_dest_has_bgp_path_info_data(pdest
))
149 bgp_dest_set_bgp_table_info(
150 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
152 bgp_dest_unlock_node(pdest
);
153 table
= bgp_dest_get_bgp_table_info(pdest
);
156 dest
= bgp_node_get(table
, p
);
158 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
159 || (safi
== SAFI_EVPN
))
165 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
166 safi_t safi
, const struct prefix
*p
,
167 struct prefix_rd
*prd
)
169 struct bgp_dest
*dest
;
170 struct bgp_dest
*pdest
= NULL
;
175 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
176 || (safi
== SAFI_EVPN
)) {
177 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
181 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
182 bgp_dest_unlock_node(pdest
);
186 table
= bgp_dest_get_bgp_table_info(pdest
);
189 dest
= bgp_node_lookup(table
, p
);
194 /* Allocate bgp_path_info_extra */
195 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
197 struct bgp_path_info_extra
*new;
198 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
199 sizeof(struct bgp_path_info_extra
));
200 new->label
[0] = MPLS_INVALID_LABEL
;
202 new->bgp_fs_pbr
= NULL
;
203 new->bgp_fs_iprule
= NULL
;
207 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
209 struct bgp_path_info_extra
*e
;
211 if (!extra
|| !*extra
)
218 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
221 /* FIXME: since multiple e may have the same e->parent
222 * and e->parent->net is holding a refcount for each
223 * of them, we need to do some fudging here.
225 * WARNING: if bpi->net->lock drops to 0, bpi may be
226 * freed as well (because bpi->net was holding the
227 * last reference to bpi) => write after free!
231 bpi
= bgp_path_info_lock(bpi
);
232 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
233 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
236 bgp_path_info_unlock(bpi
);
238 bgp_path_info_unlock(e
->parent
);
243 bgp_unlock(e
->bgp_orig
);
245 if (e
->aggr_suppressors
)
246 list_delete(&e
->aggr_suppressors
);
249 bgp_evpn_path_es_info_free(e
->es_info
);
251 if ((*extra
)->bgp_fs_iprule
)
252 list_delete(&((*extra
)->bgp_fs_iprule
));
253 if ((*extra
)->bgp_fs_pbr
)
254 list_delete(&((*extra
)->bgp_fs_pbr
));
255 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
258 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
259 * allocated if required.
261 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
264 pi
->extra
= bgp_path_info_extra_new();
268 /* Free bgp route information. */
269 static void bgp_path_info_free(struct bgp_path_info
*path
)
271 bgp_attr_unintern(&path
->attr
);
273 bgp_unlink_nexthop(path
);
274 bgp_path_info_extra_free(&path
->extra
);
275 bgp_path_info_mpath_free(&path
->mpath
);
277 bgp_addpath_free_info_data(&path
->tx_addpath
,
278 &path
->net
->tx_addpath
);
280 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
282 XFREE(MTYPE_BGP_ROUTE
, path
);
285 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
291 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
293 assert(path
&& path
->lock
> 0);
296 if (path
->lock
== 0) {
298 zlog_debug ("%s: unlocked and freeing", __func__
);
299 zlog_backtrace (LOG_DEBUG
);
301 bgp_path_info_free(path
);
308 zlog_debug ("%s: unlocked to 1", __func__
);
309 zlog_backtrace (LOG_DEBUG
);
316 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
317 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
320 struct bgp_path_info
*old_pi
, *nextpi
;
321 bool set_flag
= false;
322 struct bgp
*bgp
= NULL
;
323 struct bgp_table
*table
= NULL
;
327 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
328 * then the route selection is deferred
330 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
333 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
334 if (BGP_DEBUG(update
, UPDATE_OUT
))
336 "Route %pBD is in workqueue and being processed, not deferred.",
342 table
= bgp_dest_table(dest
);
349 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
350 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
351 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
354 /* Route selection is deferred if there is a stale path which
355 * which indicates peer is in restart mode
357 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
358 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
361 /* If the peer is graceful restart capable and peer is
362 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
365 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
366 && BGP_PEER_RESTARTING_MODE(peer
)
368 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
376 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
379 if (set_flag
&& table
) {
380 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
381 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
382 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
383 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
384 if (BGP_DEBUG(update
, UPDATE_OUT
))
385 zlog_debug("DEFER route %pBD, dest %p", dest
,
393 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
395 struct bgp_path_info
*top
;
397 top
= bgp_dest_get_bgp_path_info(dest
);
403 bgp_dest_set_bgp_path_info(dest
, pi
);
405 bgp_path_info_lock(pi
);
406 bgp_dest_lock_node(dest
);
407 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
408 bgp_dest_set_defer_flag(dest
, false);
409 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
412 /* Do the actual removal of info from RIB, for use by bgp_process
413 completion callback *only* */
414 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
417 pi
->next
->prev
= pi
->prev
;
419 pi
->prev
->next
= pi
->next
;
421 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
423 bgp_path_info_mpath_dequeue(pi
);
424 bgp_path_info_unlock(pi
);
425 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
426 bgp_dest_unlock_node(dest
);
429 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
431 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
432 /* set of previous already took care of pcount */
433 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
436 /* undo the effects of a previous call to bgp_path_info_delete; typically
437 called when a route is deleted and then quickly re-added before the
438 deletion has been processed */
439 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
441 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
442 /* unset of previous already took care of pcount */
443 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
446 /* Adjust pcount as required */
447 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
449 struct bgp_table
*table
;
451 assert(dest
&& bgp_dest_table(dest
));
452 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
454 table
= bgp_dest_table(dest
);
456 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
459 if (!BGP_PATH_COUNTABLE(pi
)
460 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
462 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
464 /* slight hack, but more robust against errors. */
465 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
466 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
468 flog_err(EC_LIB_DEVELOPMENT
,
469 "Asked to decrement 0 prefix count for peer");
470 } else if (BGP_PATH_COUNTABLE(pi
)
471 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
472 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
473 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
477 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
478 struct bgp_path_info
*pi2
)
480 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
483 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
484 * This is here primarily to keep prefix-count in check.
486 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
489 SET_FLAG(pi
->flags
, flag
);
491 /* early bath if we know it's not a flag that changes countability state
493 if (!CHECK_FLAG(flag
,
494 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
497 bgp_pcount_adjust(dest
, pi
);
500 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
503 UNSET_FLAG(pi
->flags
, flag
);
505 /* early bath if we know it's not a flag that changes countability state
507 if (!CHECK_FLAG(flag
,
508 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
511 bgp_pcount_adjust(dest
, pi
);
514 /* Get MED value. If MED value is missing and "bgp bestpath
515 missing-as-worst" is specified, treat it as the worst value. */
516 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
518 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
521 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
528 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
531 if (pi
->addpath_rx_id
)
532 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
533 pi
->peer
->host
, pi
->addpath_rx_id
);
535 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
538 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
540 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
541 struct bgp_path_info
*exist
, int *paths_eq
,
542 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
543 char *pfx_buf
, afi_t afi
, safi_t safi
,
544 enum bgp_path_selection_reason
*reason
)
546 struct attr
*newattr
, *existattr
;
547 bgp_peer_sort_t new_sort
;
548 bgp_peer_sort_t exist_sort
;
554 uint32_t exist_weight
;
555 uint32_t newm
, existm
;
556 struct in_addr new_id
;
557 struct in_addr exist_id
;
560 int internal_as_route
;
563 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
564 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
566 uint32_t exist_mm_seq
;
573 bool new_origin
, exist_origin
;
579 *reason
= bgp_path_selection_none
;
581 zlog_debug("%s: new is NULL", pfx_buf
);
586 bgp_path_info_path_with_addpath_rx_str(new, new_buf
,
590 *reason
= bgp_path_selection_first
;
592 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
598 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
,
600 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
601 pfx_buf
, new_buf
, new->flags
, exist_buf
,
606 existattr
= exist
->attr
;
608 /* For EVPN routes, we cannot just go by local vs remote, we have to
609 * look at the MAC mobility sequence number, if present.
611 if (safi
== SAFI_EVPN
) {
612 /* This is an error condition described in RFC 7432 Section
614 * states that in this scenario "the PE MUST alert the operator"
616 * does not state what other action to take. In order to provide
618 * consistency in this scenario we are going to prefer the path
622 if (newattr
->sticky
!= existattr
->sticky
) {
625 bgp_dest_get_prefix(new->net
), pfx_buf
,
626 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
627 bgp_path_info_path_with_addpath_rx_str(
628 new, new_buf
, sizeof(new_buf
));
629 bgp_path_info_path_with_addpath_rx_str(
630 exist
, exist_buf
, sizeof(exist_buf
));
633 if (newattr
->sticky
&& !existattr
->sticky
) {
634 *reason
= bgp_path_selection_evpn_sticky_mac
;
637 "%s: %s wins over %s due to sticky MAC flag",
638 pfx_buf
, new_buf
, exist_buf
);
642 if (!newattr
->sticky
&& existattr
->sticky
) {
643 *reason
= bgp_path_selection_evpn_sticky_mac
;
646 "%s: %s loses to %s due to sticky MAC flag",
647 pfx_buf
, new_buf
, exist_buf
);
652 new_esi
= bgp_evpn_attr_get_esi(newattr
);
653 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
654 if (bgp_evpn_is_esi_valid(new_esi
) &&
655 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
661 /* If both paths have the same non-zero ES and
662 * one path is local it wins.
663 * PS: Note the local path wins even if the remote
664 * has the higher MM seq. The local path's
665 * MM seq will be fixed up to match the highest
666 * rem seq, subsequently.
669 char esi_buf
[ESI_STR_LEN
];
671 if (bgp_evpn_is_path_local(bgp
, new)) {
672 *reason
= bgp_path_selection_evpn_local_path
;
675 "%s: %s wins over %s as ES %s is same and local",
676 pfx_buf
, new_buf
, exist_buf
,
677 esi_to_str(new_esi
, esi_buf
,
681 if (bgp_evpn_is_path_local(bgp
, exist
)) {
682 *reason
= bgp_path_selection_evpn_local_path
;
685 "%s: %s loses to %s as ES %s is same and local",
686 pfx_buf
, new_buf
, exist_buf
,
687 esi_to_str(new_esi
, esi_buf
,
693 new_mm_seq
= mac_mobility_seqnum(newattr
);
694 exist_mm_seq
= mac_mobility_seqnum(existattr
);
696 if (new_mm_seq
> exist_mm_seq
) {
697 *reason
= bgp_path_selection_evpn_seq
;
700 "%s: %s wins over %s due to MM seq %u > %u",
701 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
706 if (new_mm_seq
< exist_mm_seq
) {
707 *reason
= bgp_path_selection_evpn_seq
;
710 "%s: %s loses to %s due to MM seq %u < %u",
711 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
716 /* if the sequence numbers and ESI are the same and one path
717 * is non-proxy it wins (over proxy)
719 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
720 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
721 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
722 old_proxy
!= new_proxy
) {
724 *reason
= bgp_path_selection_evpn_non_proxy
;
727 "%s: %s wins over %s, same seq/es and non-proxy",
728 pfx_buf
, new_buf
, exist_buf
);
732 *reason
= bgp_path_selection_evpn_non_proxy
;
735 "%s: %s loses to %s, same seq/es and non-proxy",
736 pfx_buf
, new_buf
, exist_buf
);
741 * if sequence numbers are the same path with the lowest IP
744 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
746 *reason
= bgp_path_selection_evpn_lower_ip
;
749 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
750 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
751 &new->attr
->nexthop
);
755 *reason
= bgp_path_selection_evpn_lower_ip
;
758 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
759 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
760 &new->attr
->nexthop
);
765 /* 1. Weight check. */
766 new_weight
= newattr
->weight
;
767 exist_weight
= existattr
->weight
;
769 if (new_weight
> exist_weight
) {
770 *reason
= bgp_path_selection_weight
;
772 zlog_debug("%s: %s wins over %s due to weight %d > %d",
773 pfx_buf
, new_buf
, exist_buf
, new_weight
,
778 if (new_weight
< exist_weight
) {
779 *reason
= bgp_path_selection_weight
;
781 zlog_debug("%s: %s loses to %s due to weight %d < %d",
782 pfx_buf
, new_buf
, exist_buf
, new_weight
,
787 /* 2. Local preference check. */
788 new_pref
= exist_pref
= bgp
->default_local_pref
;
790 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
791 new_pref
= newattr
->local_pref
;
792 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
793 exist_pref
= existattr
->local_pref
;
795 if (new_pref
> exist_pref
) {
796 *reason
= bgp_path_selection_local_pref
;
799 "%s: %s wins over %s due to localpref %d > %d",
800 pfx_buf
, new_buf
, exist_buf
, new_pref
,
805 if (new_pref
< exist_pref
) {
806 *reason
= bgp_path_selection_local_pref
;
809 "%s: %s loses to %s due to localpref %d < %d",
810 pfx_buf
, new_buf
, exist_buf
, new_pref
,
815 /* 3. Local route check. We prefer:
817 * - BGP_ROUTE_AGGREGATE
818 * - BGP_ROUTE_REDISTRIBUTE
820 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
821 new->sub_type
== BGP_ROUTE_IMPORTED
);
822 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
823 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
825 if (new_origin
&& !exist_origin
) {
826 *reason
= bgp_path_selection_local_route
;
829 "%s: %s wins over %s due to preferred BGP_ROUTE type",
830 pfx_buf
, new_buf
, exist_buf
);
834 if (!new_origin
&& exist_origin
) {
835 *reason
= bgp_path_selection_local_route
;
838 "%s: %s loses to %s due to preferred BGP_ROUTE type",
839 pfx_buf
, new_buf
, exist_buf
);
843 /* 4. AS path length check. */
844 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
845 int exist_hops
= aspath_count_hops(existattr
->aspath
);
846 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
848 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
851 aspath_hops
= aspath_count_hops(newattr
->aspath
);
852 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
854 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
855 *reason
= bgp_path_selection_confed_as_path
;
858 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
859 pfx_buf
, new_buf
, exist_buf
,
861 (exist_hops
+ exist_confeds
));
865 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
866 *reason
= bgp_path_selection_confed_as_path
;
869 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
870 pfx_buf
, new_buf
, exist_buf
,
872 (exist_hops
+ exist_confeds
));
876 int newhops
= aspath_count_hops(newattr
->aspath
);
878 if (newhops
< exist_hops
) {
879 *reason
= bgp_path_selection_as_path
;
882 "%s: %s wins over %s due to aspath hopcount %d < %d",
883 pfx_buf
, new_buf
, exist_buf
,
884 newhops
, exist_hops
);
888 if (newhops
> exist_hops
) {
889 *reason
= bgp_path_selection_as_path
;
892 "%s: %s loses to %s due to aspath hopcount %d > %d",
893 pfx_buf
, new_buf
, exist_buf
,
894 newhops
, exist_hops
);
900 /* 5. Origin check. */
901 if (newattr
->origin
< existattr
->origin
) {
902 *reason
= bgp_path_selection_origin
;
904 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
905 pfx_buf
, new_buf
, exist_buf
,
906 bgp_origin_long_str
[newattr
->origin
],
907 bgp_origin_long_str
[existattr
->origin
]);
911 if (newattr
->origin
> existattr
->origin
) {
912 *reason
= bgp_path_selection_origin
;
914 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
915 pfx_buf
, new_buf
, exist_buf
,
916 bgp_origin_long_str
[newattr
->origin
],
917 bgp_origin_long_str
[existattr
->origin
]);
922 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
923 && aspath_count_hops(existattr
->aspath
) == 0);
924 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
925 && aspath_count_confeds(existattr
->aspath
) > 0
926 && aspath_count_hops(newattr
->aspath
) == 0
927 && aspath_count_hops(existattr
->aspath
) == 0);
929 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
930 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
931 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
932 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
933 || internal_as_route
) {
934 new_med
= bgp_med_value(new->attr
, bgp
);
935 exist_med
= bgp_med_value(exist
->attr
, bgp
);
937 if (new_med
< exist_med
) {
938 *reason
= bgp_path_selection_med
;
941 "%s: %s wins over %s due to MED %d < %d",
942 pfx_buf
, new_buf
, exist_buf
, new_med
,
947 if (new_med
> exist_med
) {
948 *reason
= bgp_path_selection_med
;
951 "%s: %s loses to %s due to MED %d > %d",
952 pfx_buf
, new_buf
, exist_buf
, new_med
,
958 /* 7. Peer type check. */
959 new_sort
= new->peer
->sort
;
960 exist_sort
= exist
->peer
->sort
;
962 if (new_sort
== BGP_PEER_EBGP
963 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
964 *reason
= bgp_path_selection_peer
;
967 "%s: %s wins over %s due to eBGP peer > iBGP peer",
968 pfx_buf
, new_buf
, exist_buf
);
972 if (exist_sort
== BGP_PEER_EBGP
973 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
974 *reason
= bgp_path_selection_peer
;
977 "%s: %s loses to %s due to iBGP peer < eBGP peer",
978 pfx_buf
, new_buf
, exist_buf
);
982 /* 8. IGP metric check. */
986 newm
= new->extra
->igpmetric
;
988 existm
= exist
->extra
->igpmetric
;
993 "%s: %s wins over %s due to IGP metric %d < %d",
994 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1001 "%s: %s loses to %s due to IGP metric %d > %d",
1002 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1006 /* 9. Same IGP metric. Compare the cluster list length as
1007 representative of IGP hops metric. Rewrite the metric value
1008 pair (newm, existm) with the cluster list length. Prefer the
1009 path with smaller cluster list length. */
1010 if (newm
== existm
) {
1011 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1012 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1013 && (mpath_cfg
== NULL
1015 mpath_cfg
->ibgp_flags
,
1016 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1017 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1018 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1020 if (newm
< existm
) {
1023 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1024 pfx_buf
, new_buf
, exist_buf
,
1029 if (newm
> existm
) {
1032 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1033 pfx_buf
, new_buf
, exist_buf
,
1040 /* 10. confed-external vs. confed-internal */
1041 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1042 if (new_sort
== BGP_PEER_CONFED
1043 && exist_sort
== BGP_PEER_IBGP
) {
1044 *reason
= bgp_path_selection_confed
;
1047 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1048 pfx_buf
, new_buf
, exist_buf
);
1052 if (exist_sort
== BGP_PEER_CONFED
1053 && new_sort
== BGP_PEER_IBGP
) {
1054 *reason
= bgp_path_selection_confed
;
1057 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1058 pfx_buf
, new_buf
, exist_buf
);
1063 /* 11. Maximum path check. */
1064 if (newm
== existm
) {
1065 /* If one path has a label but the other does not, do not treat
1066 * them as equals for multipath
1068 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1070 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1073 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1074 pfx_buf
, new_buf
, exist_buf
);
1075 } else if (CHECK_FLAG(bgp
->flags
,
1076 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1079 * For the two paths, all comparison steps till IGP
1081 * have succeeded - including AS_PATH hop count. Since
1083 * bestpath as-path multipath-relax' knob is on, we
1085 * an exact match of AS_PATH. Thus, mark the paths are
1087 * That will trigger both these paths to get into the
1095 "%s: %s and %s are equal via multipath-relax",
1096 pfx_buf
, new_buf
, exist_buf
);
1097 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1098 if (aspath_cmp(new->attr
->aspath
,
1099 exist
->attr
->aspath
)) {
1104 "%s: %s and %s are equal via matching aspaths",
1105 pfx_buf
, new_buf
, exist_buf
);
1107 } else if (new->peer
->as
== exist
->peer
->as
) {
1112 "%s: %s and %s are equal via same remote-as",
1113 pfx_buf
, new_buf
, exist_buf
);
1117 * TODO: If unequal cost ibgp multipath is enabled we can
1118 * mark the paths as equal here instead of returning
1123 "%s: %s wins over %s after IGP metric comparison",
1124 pfx_buf
, new_buf
, exist_buf
);
1127 "%s: %s loses to %s after IGP metric comparison",
1128 pfx_buf
, new_buf
, exist_buf
);
1130 *reason
= bgp_path_selection_igp_metric
;
1134 /* 12. If both paths are external, prefer the path that was received
1135 first (the oldest one). This step minimizes route-flap, since a
1136 newer path won't displace an older one, even if it was the
1137 preferred route based on the additional decision criteria below. */
1138 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1139 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1140 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1141 *reason
= bgp_path_selection_older
;
1144 "%s: %s wins over %s due to oldest external",
1145 pfx_buf
, new_buf
, exist_buf
);
1149 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1150 *reason
= bgp_path_selection_older
;
1153 "%s: %s loses to %s due to oldest external",
1154 pfx_buf
, new_buf
, exist_buf
);
1159 /* 13. Router-ID comparision. */
1160 /* If one of the paths is "stale", the corresponding peer router-id will
1161 * be 0 and would always win over the other path. If originator id is
1162 * used for the comparision, it will decide which path is better.
1164 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1165 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1167 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1168 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1169 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1171 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1173 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1174 *reason
= bgp_path_selection_router_id
;
1177 "%s: %s wins over %s due to Router-ID comparison",
1178 pfx_buf
, new_buf
, exist_buf
);
1182 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1183 *reason
= bgp_path_selection_router_id
;
1186 "%s: %s loses to %s due to Router-ID comparison",
1187 pfx_buf
, new_buf
, exist_buf
);
1191 /* 14. Cluster length comparision. */
1192 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1193 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1195 if (new_cluster
< exist_cluster
) {
1196 *reason
= bgp_path_selection_cluster_length
;
1199 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1200 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1205 if (new_cluster
> exist_cluster
) {
1206 *reason
= bgp_path_selection_cluster_length
;
1209 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1210 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1215 /* 15. Neighbor address comparision. */
1216 /* Do this only if neither path is "stale" as stale paths do not have
1217 * valid peer information (as the connection may or may not be up).
1219 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1220 *reason
= bgp_path_selection_stale
;
1223 "%s: %s wins over %s due to latter path being STALE",
1224 pfx_buf
, new_buf
, exist_buf
);
1228 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1229 *reason
= bgp_path_selection_stale
;
1232 "%s: %s loses to %s due to former path being STALE",
1233 pfx_buf
, new_buf
, exist_buf
);
1237 /* locally configured routes to advertise do not have su_remote */
1238 if (new->peer
->su_remote
== NULL
) {
1239 *reason
= bgp_path_selection_local_configured
;
1242 if (exist
->peer
->su_remote
== NULL
) {
1243 *reason
= bgp_path_selection_local_configured
;
1247 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1250 *reason
= bgp_path_selection_neighbor_ip
;
1253 "%s: %s loses to %s due to Neighor IP comparison",
1254 pfx_buf
, new_buf
, exist_buf
);
1259 *reason
= bgp_path_selection_neighbor_ip
;
1262 "%s: %s wins over %s due to Neighor IP comparison",
1263 pfx_buf
, new_buf
, exist_buf
);
1267 *reason
= bgp_path_selection_default
;
1269 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1270 pfx_buf
, new_buf
, exist_buf
);
1276 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1277 struct bgp_path_info
*exist
, int *paths_eq
)
1279 enum bgp_path_selection_reason reason
;
1280 char pfx_buf
[PREFIX2STR_BUFFER
];
1282 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1283 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1286 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1287 * is preferred, or 0 if they are the same (usually will only occur if
1288 * multipath is enabled
1289 * This version is compatible with */
1290 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1291 struct bgp_path_info
*exist
, char *pfx_buf
,
1292 afi_t afi
, safi_t safi
,
1293 enum bgp_path_selection_reason
*reason
)
1297 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1311 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1312 const struct prefix
*p
,
1313 struct attr
*attr
, afi_t afi
,
1316 struct bgp_filter
*filter
;
1317 enum filter_type ret
= FILTER_PERMIT
;
1319 filter
= &peer
->filter
[afi
][safi
];
1321 #define FILTER_EXIST_WARN(F, f, filter) \
1322 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1323 zlog_debug("%s: Could not find configured input %s-list %s!", \
1324 peer->host, #f, F##_IN_NAME(filter));
1326 if (DISTRIBUTE_IN_NAME(filter
)) {
1327 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1329 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1336 if (PREFIX_LIST_IN_NAME(filter
)) {
1337 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1339 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1346 if (FILTER_LIST_IN_NAME(filter
)) {
1347 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1349 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1350 == AS_FILTER_DENY
) {
1357 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1358 char pfxprint
[PREFIX2STR_BUFFER
];
1360 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1361 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1362 ret
== FILTER_PERMIT
? "permit" : "deny");
1366 #undef FILTER_EXIST_WARN
1369 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1370 const struct prefix
*p
,
1371 struct attr
*attr
, afi_t afi
,
1374 struct bgp_filter
*filter
;
1375 enum filter_type ret
= FILTER_PERMIT
;
1377 filter
= &peer
->filter
[afi
][safi
];
1379 #define FILTER_EXIST_WARN(F, f, filter) \
1380 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1381 zlog_debug("%s: Could not find configured output %s-list %s!", \
1382 peer->host, #f, F##_OUT_NAME(filter));
1384 if (DISTRIBUTE_OUT_NAME(filter
)) {
1385 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1387 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1394 if (PREFIX_LIST_OUT_NAME(filter
)) {
1395 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1397 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1404 if (FILTER_LIST_OUT_NAME(filter
)) {
1405 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1407 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1408 == AS_FILTER_DENY
) {
1414 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1415 char pfxprint
[PREFIX2STR_BUFFER
];
1417 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1418 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1419 ret
== FILTER_PERMIT
? "permit" : "deny");
1424 #undef FILTER_EXIST_WARN
1427 /* If community attribute includes no_export then return 1. */
1428 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1430 if (attr
->community
) {
1431 /* NO_ADVERTISE check. */
1432 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1435 /* NO_EXPORT check. */
1436 if (peer
->sort
== BGP_PEER_EBGP
1437 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1440 /* NO_EXPORT_SUBCONFED check. */
1441 if (peer
->sort
== BGP_PEER_EBGP
1442 || peer
->sort
== BGP_PEER_CONFED
)
1443 if (community_include(attr
->community
,
1444 COMMUNITY_NO_EXPORT_SUBCONFED
))
1450 /* Route reflection loop check. */
1451 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1453 struct in_addr cluster_id
;
1454 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1457 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1458 cluster_id
= peer
->bgp
->cluster_id
;
1460 cluster_id
= peer
->bgp
->router_id
;
1462 if (cluster_loop_check(cluster
, cluster_id
))
1468 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1469 struct attr
*attr
, afi_t afi
, safi_t safi
,
1470 const char *rmap_name
, mpls_label_t
*label
,
1471 uint32_t num_labels
, struct bgp_dest
*dest
)
1473 struct bgp_filter
*filter
;
1474 struct bgp_path_info rmap_path
= { 0 };
1475 struct bgp_path_info_extra extra
= { 0 };
1476 route_map_result_t ret
;
1477 struct route_map
*rmap
= NULL
;
1479 filter
= &peer
->filter
[afi
][safi
];
1481 /* Apply default weight value. */
1482 if (peer
->weight
[afi
][safi
])
1483 attr
->weight
= peer
->weight
[afi
][safi
];
1486 rmap
= route_map_lookup_by_name(rmap_name
);
1491 if (ROUTE_MAP_IN_NAME(filter
)) {
1492 rmap
= ROUTE_MAP_IN(filter
);
1499 /* Route map apply. */
1501 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1502 /* Duplicate current value to new strucutre for modification. */
1503 rmap_path
.peer
= peer
;
1504 rmap_path
.attr
= attr
;
1505 rmap_path
.extra
= &extra
;
1506 rmap_path
.net
= dest
;
1508 extra
.num_labels
= num_labels
;
1509 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1510 memcpy(extra
.label
, label
,
1511 num_labels
* sizeof(mpls_label_t
));
1513 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1515 /* Apply BGP route map to the attribute. */
1516 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1518 peer
->rmap_type
= 0;
1520 if (ret
== RMAP_DENYMATCH
)
1526 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1527 struct attr
*attr
, afi_t afi
, safi_t safi
,
1528 const char *rmap_name
)
1530 struct bgp_path_info rmap_path
;
1531 route_map_result_t ret
;
1532 struct route_map
*rmap
= NULL
;
1536 * So if we get to this point and have no rmap_name
1537 * we want to just show the output as it currently
1543 /* Apply default weight value. */
1544 if (peer
->weight
[afi
][safi
])
1545 attr
->weight
= peer
->weight
[afi
][safi
];
1547 rmap
= route_map_lookup_by_name(rmap_name
);
1550 * If we have a route map name and we do not find
1551 * the routemap that means we have an implicit
1557 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1558 /* Route map apply. */
1559 /* Duplicate current value to new strucutre for modification. */
1560 rmap_path
.peer
= peer
;
1561 rmap_path
.attr
= attr
;
1563 rmap_type
= peer
->rmap_type
;
1564 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1566 /* Apply BGP route map to the attribute. */
1567 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1569 peer
->rmap_type
= rmap_type
;
1571 if (ret
== RMAP_DENYMATCH
)
1573 * caller has multiple error paths with bgp_attr_flush()
1580 /* If this is an EBGP peer with remove-private-AS */
1581 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1582 struct peer
*peer
, struct attr
*attr
)
1584 if (peer
->sort
== BGP_PEER_EBGP
1585 && (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_REPLACE
)
1589 || peer_af_flag_check(peer
, afi
, safi
,
1590 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1591 || peer_af_flag_check(peer
, afi
, safi
,
1592 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1593 // Take action on the entire aspath
1594 if (peer_af_flag_check(peer
, afi
, safi
,
1595 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1596 || peer_af_flag_check(peer
, afi
, safi
,
1597 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1598 if (peer_af_flag_check(
1600 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1601 attr
->aspath
= aspath_replace_private_asns(
1602 attr
->aspath
, bgp
->as
, peer
->as
);
1604 // The entire aspath consists of private ASNs so create
1606 else if (aspath_private_as_check(attr
->aspath
))
1607 attr
->aspath
= aspath_empty_get();
1609 // There are some public and some private ASNs, remove
1612 attr
->aspath
= aspath_remove_private_asns(
1613 attr
->aspath
, peer
->as
);
1616 // 'all' was not specified so the entire aspath must be private
1618 // for us to do anything
1619 else if (aspath_private_as_check(attr
->aspath
)) {
1620 if (peer_af_flag_check(
1622 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1623 attr
->aspath
= aspath_replace_private_asns(
1624 attr
->aspath
, bgp
->as
, peer
->as
);
1626 attr
->aspath
= aspath_empty_get();
1631 /* If this is an EBGP peer with as-override */
1632 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1633 struct peer
*peer
, struct attr
*attr
)
1635 if (peer
->sort
== BGP_PEER_EBGP
1636 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1637 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1638 attr
->aspath
= aspath_replace_specific_asn(
1639 attr
->aspath
, peer
->as
, bgp
->as
);
1643 void bgp_attr_add_gshut_community(struct attr
*attr
)
1645 struct community
*old
;
1646 struct community
*new;
1647 struct community
*merge
;
1648 struct community
*gshut
;
1650 old
= attr
->community
;
1651 gshut
= community_str2com("graceful-shutdown");
1656 merge
= community_merge(community_dup(old
), gshut
);
1658 if (old
->refcnt
== 0)
1659 community_free(&old
);
1661 new = community_uniq_sort(merge
);
1662 community_free(&merge
);
1664 new = community_dup(gshut
);
1667 community_free(&gshut
);
1668 attr
->community
= new;
1669 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1671 /* When we add the graceful-shutdown community we must also
1672 * lower the local-preference */
1673 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1674 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1678 /* Notify BGP Conditional advertisement scanner process. */
1679 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1681 struct peer
*temp_peer
;
1682 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1683 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1684 afi_t afi
= SUBGRP_AFI(subgrp
);
1685 safi_t safi
= SUBGRP_SAFI(subgrp
);
1686 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1687 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1689 if (!ADVERTISE_MAP_NAME(filter
))
1692 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1693 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1696 if (peer
!= temp_peer
)
1699 temp_peer
->advmap_table_change
= true;
1705 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1707 if (family
== AF_INET
) {
1708 attr
->nexthop
.s_addr
= INADDR_ANY
;
1709 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1711 if (family
== AF_INET6
)
1712 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1713 if (family
== AF_EVPN
)
1714 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1717 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1718 struct update_subgroup
*subgrp
,
1719 const struct prefix
*p
, struct attr
*attr
,
1720 bool skip_rmap_check
)
1722 struct bgp_filter
*filter
;
1725 struct peer
*onlypeer
;
1727 struct attr
*piattr
;
1728 route_map_result_t ret
;
1733 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1734 bool nh_reset
= false;
1737 if (DISABLE_BGP_ANNOUNCE
)
1740 afi
= SUBGRP_AFI(subgrp
);
1741 safi
= SUBGRP_SAFI(subgrp
);
1742 peer
= SUBGRP_PEER(subgrp
);
1744 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1745 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1748 filter
= &peer
->filter
[afi
][safi
];
1749 bgp
= SUBGRP_INST(subgrp
);
1750 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1753 #ifdef ENABLE_BGP_VNC
1754 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1755 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1756 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1759 * direct and direct_ext type routes originate internally even
1760 * though they can have peer pointers that reference other
1763 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1769 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1770 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1771 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1772 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1774 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1779 /* With addpath we may be asked to TX all kinds of paths so make sure
1781 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1782 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1783 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1787 /* If this is not the bestpath then check to see if there is an enabled
1789 * feature that requires us to advertise it */
1790 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1791 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1796 /* Aggregate-address suppress check. */
1797 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1801 * If we are doing VRF 2 VRF leaking via the import
1802 * statement, we want to prevent the route going
1803 * off box as that the RT and RD created are localy
1804 * significant and globaly useless.
1806 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1807 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1810 /* If it's labeled safi, make sure the route has a valid label. */
1811 if (safi
== SAFI_LABELED_UNICAST
) {
1812 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1813 if (!bgp_is_valid_label(&label
)) {
1814 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1815 zlog_debug("u%" PRIu64
":s%" PRIu64
1816 " %pFX is filtered - no label (%p)",
1817 subgrp
->update_group
->id
, subgrp
->id
,
1823 /* Do not send back route to sender. */
1824 if (onlypeer
&& from
== onlypeer
) {
1828 /* Do not send the default route in the BGP table if the neighbor is
1829 * configured for default-originate */
1830 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1831 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1832 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1834 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1838 /* Transparency check. */
1839 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1840 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1845 /* If community is not disabled check the no-export and local. */
1846 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1847 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1848 zlog_debug("%s: community filter check fail for %pFX",
1853 /* If the attribute has originator-id and it is same as remote
1855 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1856 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1857 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1859 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1864 /* ORF prefix-list filter check */
1865 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1866 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1867 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1868 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1869 if (peer
->orf_plist
[afi
][safi
]) {
1870 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1872 if (bgp_debug_update(NULL
, p
,
1873 subgrp
->update_group
, 0))
1875 "%s [Update:SEND] %pFX is filtered via ORF",
1881 /* Output filter check. */
1882 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1883 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1884 zlog_debug("%s [Update:SEND] %pFX is filtered",
1889 /* AS path loop check. */
1890 if (onlypeer
&& onlypeer
->as_path_loop_detection
1891 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1892 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1894 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1895 onlypeer
->host
, onlypeer
->as
);
1899 /* If we're a CONFED we need to loop check the CONFED ID too */
1900 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1901 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1902 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1904 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1905 peer
->host
, bgp
->confed_id
);
1910 /* Route-Reflect check. */
1911 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1916 /* IBGP reflection check. */
1917 if (reflect
&& !samepeer_safe
) {
1918 /* A route from a Client peer. */
1919 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1920 PEER_FLAG_REFLECTOR_CLIENT
)) {
1921 /* Reflect to all the Non-Client peers and also to the
1922 Client peers other than the originator. Originator
1924 is already done. So there is noting to do. */
1925 /* no bgp client-to-client reflection check. */
1926 if (CHECK_FLAG(bgp
->flags
,
1927 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1928 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1929 PEER_FLAG_REFLECTOR_CLIENT
))
1932 /* A route from a Non-client peer. Reflect to all other
1934 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1935 PEER_FLAG_REFLECTOR_CLIENT
))
1940 /* For modify attribute, copy it to temporary structure. */
1943 /* If local-preference is not set. */
1944 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1945 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1946 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1947 attr
->local_pref
= bgp
->default_local_pref
;
1950 /* If originator-id is not set and the route is to be reflected,
1951 set the originator id */
1953 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1954 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1955 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1958 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1960 if (peer
->sort
== BGP_PEER_EBGP
1961 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1962 if (from
!= bgp
->peer_self
&& !transparent
1963 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1964 PEER_FLAG_MED_UNCHANGED
))
1966 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1969 /* Since the nexthop attribute can vary per peer, it is not explicitly
1971 * in announce check, only certain flags and length (or number of
1973 * -- for IPv6/MP_REACH) are set here in order to guide the update
1975 * code in setting the nexthop(s) on a per peer basis in
1977 * Typically, the source nexthop in the attribute is preserved but in
1979 * scenarios where we know it will always be overwritten, we reset the
1980 * nexthop to "0" in an attempt to achieve better Update packing. An
1981 * example of this is when a prefix from each of 2 IBGP peers needs to
1983 * announced to an EBGP peer (and they have the same attributes barring
1987 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1989 #define NEXTHOP_IS_V6 \
1990 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1991 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1992 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1993 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1995 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1997 * the peer (group) is configured to receive link-local nexthop
1999 * and it is available in the prefix OR we're not reflecting the route,
2000 * link-local nexthop address is valid and
2001 * the peer (group) to whom we're going to announce is on a shared
2003 * and this is either a self-originated route or the peer is EBGP.
2004 * By checking if nexthop LL address is valid we are sure that
2005 * we do not announce LL address as `::`.
2007 if (NEXTHOP_IS_V6
) {
2008 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2009 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2010 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2011 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2013 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2014 && peer
->shared_network
2015 && (from
== bgp
->peer_self
2016 || peer
->sort
== BGP_PEER_EBGP
))) {
2017 attr
->mp_nexthop_len
=
2018 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2021 /* Clear off link-local nexthop in source, whenever it is not
2023 * ensure more prefixes share the same attribute for
2026 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2027 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2028 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2031 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2032 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2034 /* Route map & unsuppress-map apply. */
2035 if (!skip_rmap_check
2036 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2037 struct bgp_path_info rmap_path
= {0};
2038 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2039 struct attr dummy_attr
= {0};
2041 /* Fill temp path_info */
2042 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2045 /* don't confuse inbound and outbound setting */
2046 RESET_FLAG(attr
->rmap_change_flags
);
2049 * The route reflector is not allowed to modify the attributes
2050 * of the reflected IBGP routes unless explicitly allowed.
2052 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2053 && !CHECK_FLAG(bgp
->flags
,
2054 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2056 rmap_path
.attr
= &dummy_attr
;
2059 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2061 if (bgp_path_suppressed(pi
))
2062 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2065 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2068 peer
->rmap_type
= 0;
2070 if (ret
== RMAP_DENYMATCH
) {
2071 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2073 "%s [Update:SEND] %pFX is filtered by route-map",
2076 bgp_attr_flush(attr
);
2081 /* RFC 8212 to prevent route leaks.
2082 * This specification intends to improve this situation by requiring the
2083 * explicit configuration of both BGP Import and Export Policies for any
2084 * External BGP (EBGP) session such as customers, peers, or
2085 * confederation boundaries for all enabled address families. Through
2086 * codification of the aforementioned requirement, operators will
2087 * benefit from consistent behavior across different BGP
2090 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2091 if (!bgp_outbound_policy_exists(peer
, filter
))
2094 /* draft-ietf-idr-deprecate-as-set-confed-set
2095 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2096 * Eventually, This document (if approved) updates RFC 4271
2097 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2098 * and obsoletes RFC 6472.
2100 if (peer
->bgp
->reject_as_sets
)
2101 if (aspath_check_as_sets(attr
->aspath
))
2104 /* Codification of AS 0 Processing */
2105 if (aspath_check_as_zero(attr
->aspath
))
2108 if (bgp_in_graceful_shutdown(bgp
)) {
2109 if (peer
->sort
== BGP_PEER_IBGP
2110 || peer
->sort
== BGP_PEER_CONFED
) {
2111 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2112 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2114 bgp_attr_add_gshut_community(attr
);
2118 /* After route-map has been applied, we check to see if the nexthop to
2119 * be carried in the attribute (that is used for the announcement) can
2120 * be cleared off or not. We do this in all cases where we would be
2121 * setting the nexthop to "ourselves". For IPv6, we only need to
2123 * the global nexthop here; the link-local nexthop would have been
2125 * already, and if not, it is required by the update formation code.
2126 * Also see earlier comments in this function.
2129 * If route-map has performed some operation on the nexthop or the peer
2130 * configuration says to pass it unchanged, we cannot reset the nexthop
2131 * here, so only attempt to do it if these aren't true. Note that the
2132 * route-map handler itself might have cleared the nexthop, if for
2134 * it is configured as 'peer-address'.
2136 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2137 piattr
->rmap_change_flags
)
2139 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2140 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2141 /* We can reset the nexthop, if setting (or forcing) it to
2143 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2144 PEER_FLAG_NEXTHOP_SELF
)
2145 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2146 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2148 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2149 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2150 subgroup_announce_reset_nhop(
2151 (peer_cap_enhe(peer
, afi
, safi
)
2157 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2158 /* Can also reset the nexthop if announcing to EBGP, but
2160 * no peer in the subgroup is on a shared subnet.
2161 * Note: 3rd party nexthop currently implemented for
2164 if ((p
->family
== AF_INET
) &&
2165 (!bgp_subgrp_multiaccess_check_v4(
2168 subgroup_announce_reset_nhop(
2169 (peer_cap_enhe(peer
, afi
, safi
)
2176 if ((p
->family
== AF_INET6
) &&
2177 (!bgp_subgrp_multiaccess_check_v6(
2178 piattr
->mp_nexthop_global
,
2180 subgroup_announce_reset_nhop(
2181 (peer_cap_enhe(peer
, afi
, safi
)
2190 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2192 * This flag is used for leaked vpn-vrf routes
2194 int family
= p
->family
;
2196 if (peer_cap_enhe(peer
, afi
, safi
))
2199 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2201 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2202 __func__
, family2str(family
));
2203 subgroup_announce_reset_nhop(family
, attr
);
2208 /* If IPv6/MP and nexthop does not have any override and happens
2210 * be a link-local address, reset it so that we don't pass along
2212 * source's link-local IPv6 address to recipients who may not be
2214 * the same interface.
2216 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2217 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2218 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2224 * When the next hop is set to ourselves, if all multipaths have
2225 * link-bandwidth announce the cumulative bandwidth as that makes
2226 * the most sense. However, don't modify if the link-bandwidth has
2227 * been explicitly set by user policy.
2230 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2231 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2232 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2233 attr
->ecommunity
= ecommunity_replace_linkbw(
2234 bgp
->as
, attr
->ecommunity
, cum_bw
);
2239 static int bgp_route_select_timer_expire(struct thread
*thread
)
2241 struct afi_safi_info
*info
;
2246 info
= THREAD_ARG(thread
);
2251 if (BGP_DEBUG(update
, UPDATE_OUT
))
2252 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2255 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2257 XFREE(MTYPE_TMP
, info
);
2259 /* Best path selection */
2260 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2263 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2264 struct bgp_maxpaths_cfg
*mpath_cfg
,
2265 struct bgp_path_info_pair
*result
, afi_t afi
,
2268 struct bgp_path_info
*new_select
;
2269 struct bgp_path_info
*old_select
;
2270 struct bgp_path_info
*pi
;
2271 struct bgp_path_info
*pi1
;
2272 struct bgp_path_info
*pi2
;
2273 struct bgp_path_info
*nextpi
= NULL
;
2274 int paths_eq
, do_mpath
, debug
;
2275 struct list mp_list
;
2276 char pfx_buf
[PREFIX2STR_BUFFER
];
2277 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2279 bgp_mp_list_init(&mp_list
);
2281 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2283 debug
= bgp_debug_bestpath(dest
);
2286 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2288 dest
->reason
= bgp_path_selection_none
;
2289 /* bgp deterministic-med */
2291 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2293 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2294 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2296 bgp_path_info_unset_flag(dest
, pi1
,
2297 BGP_PATH_DMED_SELECTED
);
2299 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2301 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2303 if (BGP_PATH_HOLDDOWN(pi1
))
2305 if (pi1
->peer
!= bgp
->peer_self
)
2306 if (pi1
->peer
->status
!= Established
)
2311 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2312 if (CHECK_FLAG(pi2
->flags
,
2313 BGP_PATH_DMED_CHECK
))
2315 if (BGP_PATH_HOLDDOWN(pi2
))
2317 if (pi2
->peer
!= bgp
->peer_self
2320 PEER_STATUS_NSF_WAIT
))
2321 if (pi2
->peer
->status
2325 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2327 && !aspath_cmp_left_confed(
2332 if (bgp_path_info_cmp(
2333 bgp
, pi2
, new_select
,
2334 &paths_eq
, mpath_cfg
, debug
,
2337 bgp_path_info_unset_flag(
2339 BGP_PATH_DMED_SELECTED
);
2343 bgp_path_info_set_flag(
2344 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2347 bgp_path_info_set_flag(dest
, new_select
,
2348 BGP_PATH_DMED_CHECK
);
2349 bgp_path_info_set_flag(dest
, new_select
,
2350 BGP_PATH_DMED_SELECTED
);
2353 bgp_path_info_path_with_addpath_rx_str(
2354 new_select
, path_buf
, sizeof(path_buf
));
2356 "%pBD: %s is the bestpath from AS %u",
2358 aspath_get_first_as(
2359 new_select
->attr
->aspath
));
2364 /* Check old selected route and new selected route. */
2367 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2368 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2369 enum bgp_path_selection_reason reason
;
2371 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2374 if (BGP_PATH_HOLDDOWN(pi
)) {
2375 /* reap REMOVED routes, if needs be
2376 * selected route must stay for a while longer though
2378 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2379 && (pi
!= old_select
))
2380 bgp_path_info_reap(dest
, pi
);
2383 zlog_debug("%s: pi %p in holddown", __func__
,
2389 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2390 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2391 if (pi
->peer
->status
!= Established
) {
2395 "%s: pi %p non self peer %s not estab state",
2396 __func__
, pi
, pi
->peer
->host
);
2401 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2402 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2403 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2405 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2409 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2411 reason
= dest
->reason
;
2412 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2413 debug
, pfx_buf
, afi
, safi
,
2415 if (new_select
== NULL
&&
2416 reason
!= bgp_path_selection_none
)
2417 dest
->reason
= reason
;
2422 /* Now that we know which path is the bestpath see if any of the other
2424 * qualify as multipaths
2428 bgp_path_info_path_with_addpath_rx_str(
2429 new_select
, path_buf
, sizeof(path_buf
));
2431 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2433 "%pBD: After path selection, newbest is %s oldbest was %s",
2435 old_select
? old_select
->peer
->host
: "NONE");
2438 if (do_mpath
&& new_select
) {
2439 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2440 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2443 bgp_path_info_path_with_addpath_rx_str(
2444 pi
, path_buf
, sizeof(path_buf
));
2446 if (pi
== new_select
) {
2449 "%pBD: %s is the bestpath, add to the multipath list",
2451 bgp_mp_list_add(&mp_list
, pi
);
2455 if (BGP_PATH_HOLDDOWN(pi
))
2458 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2459 && !CHECK_FLAG(pi
->peer
->sflags
,
2460 PEER_STATUS_NSF_WAIT
))
2461 if (pi
->peer
->status
!= Established
)
2464 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2467 "%pBD: %s has the same nexthop as the bestpath, skip it",
2472 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2473 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2479 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2481 bgp_mp_list_add(&mp_list
, pi
);
2486 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2488 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2489 bgp_mp_list_clear(&mp_list
);
2491 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2493 result
->old
= old_select
;
2494 result
->new = new_select
;
2500 * A new route/change in bestpath of an existing route. Evaluate the path
2501 * for advertisement to the subgroup.
2503 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2504 struct bgp_path_info
*selected
,
2505 struct bgp_dest
*dest
,
2506 uint32_t addpath_tx_id
)
2508 const struct prefix
*p
;
2509 struct peer
*onlypeer
;
2516 p
= bgp_dest_get_prefix(dest
);
2517 afi
= SUBGRP_AFI(subgrp
);
2518 safi
= SUBGRP_SAFI(subgrp
);
2519 bgp
= SUBGRP_INST(subgrp
);
2520 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2523 if (BGP_DEBUG(update
, UPDATE_OUT
))
2524 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2526 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2527 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2528 PEER_STATUS_ORF_WAIT_REFRESH
))
2531 memset(&attr
, 0, sizeof(struct attr
));
2532 /* It's initialized in bgp_announce_check() */
2534 /* Announcement to the subgroup. If the route is filtered withdraw it.
2535 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2536 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2539 advertise
= bgp_check_advertise(bgp
, dest
);
2542 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2544 /* Route is selected, if the route is already installed
2545 * in FIB, then it is advertised
2548 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2551 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2555 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2557 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2562 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2563 * This is called at the end of route processing.
2565 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2567 struct bgp_path_info
*pi
;
2569 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2570 if (BGP_PATH_HOLDDOWN(pi
))
2572 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2573 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2578 * Has the route changed from the RIB's perspective? This is invoked only
2579 * if the route selection returns the same best route as earlier - to
2580 * determine if we need to update zebra or not.
2582 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2584 struct bgp_path_info
*mpinfo
;
2586 /* If this is multipath, check all selected paths for any nexthop
2587 * change or attribute change. Some attribute changes (e.g., community)
2588 * aren't of relevance to the RIB, but we'll update zebra to ensure
2589 * we handle the case of BGP nexthop change. This is the behavior
2590 * when the best path has an attribute change anyway.
2592 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2593 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2594 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2598 * If this is multipath, check all selected paths for any nexthop change
2600 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2601 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2602 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2603 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2607 /* Nothing has changed from the RIB's perspective. */
2611 struct bgp_process_queue
{
2613 STAILQ_HEAD(, bgp_dest
) pqueue
;
2614 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2616 unsigned int queued
;
2619 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2620 safi_t safi
, struct bgp_dest
*dest
,
2621 struct bgp_path_info
*new_select
,
2622 struct bgp_path_info
*old_select
)
2624 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2626 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2629 if (advertise_type5_routes(bgp
, afi
) && new_select
2630 && is_route_injectable_into_evpn(new_select
)) {
2632 /* apply the route-map */
2633 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2634 route_map_result_t ret
;
2635 struct bgp_path_info rmap_path
;
2636 struct bgp_path_info_extra rmap_path_extra
;
2637 struct attr dummy_attr
;
2639 dummy_attr
= *new_select
->attr
;
2641 /* Fill temp path_info */
2642 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2643 new_select
, new_select
->peer
,
2646 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2648 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2651 if (ret
== RMAP_DENYMATCH
) {
2652 bgp_attr_flush(&dummy_attr
);
2653 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2656 bgp_evpn_advertise_type5_route(
2657 bgp
, p
, &dummy_attr
, afi
, safi
);
2659 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2662 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2663 && is_route_injectable_into_evpn(old_select
))
2664 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2668 * old_select = The old best path
2669 * new_select = the new best path
2671 * if (!old_select && new_select)
2672 * We are sending new information on.
2674 * if (old_select && new_select) {
2675 * if (new_select != old_select)
2676 * We have a new best path send a change
2678 * We've received a update with new attributes that needs
2682 * if (old_select && !new_select)
2683 * We have no eligible route that we can announce or the rn
2686 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2687 afi_t afi
, safi_t safi
)
2689 struct bgp_path_info
*new_select
;
2690 struct bgp_path_info
*old_select
;
2691 struct bgp_path_info_pair old_and_new
;
2694 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2696 debug
= bgp_debug_bestpath(dest
);
2699 "%s: bgp delete in progress, ignoring event, p=%pBD",
2703 /* Is it end of initial update? (after startup) */
2705 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2706 sizeof(bgp
->update_delay_zebra_resume_time
));
2708 bgp
->main_zebra_update_hold
= 0;
2709 FOREACH_AFI_SAFI (afi
, safi
) {
2710 if (bgp_fibupd_safi(safi
))
2711 bgp_zebra_announce_table(bgp
, afi
, safi
);
2713 bgp
->main_peers_update_hold
= 0;
2715 bgp_start_routeadv(bgp
);
2719 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2721 debug
= bgp_debug_bestpath(dest
);
2723 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2724 afi2str(afi
), safi2str(safi
));
2726 /* The best path calculation for the route is deferred if
2727 * BGP_NODE_SELECT_DEFER is set
2729 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2730 if (BGP_DEBUG(update
, UPDATE_OUT
))
2731 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2735 /* Best path selection. */
2736 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2738 old_select
= old_and_new
.old
;
2739 new_select
= old_and_new
.new;
2741 /* Do we need to allocate or free labels?
2742 * Right now, since we only deal with per-prefix labels, it is not
2743 * necessary to do this upon changes to best path. Exceptions:
2744 * - label index has changed -> recalculate resulting label
2745 * - path_info sub_type changed -> switch to/from implicit-null
2746 * - no valid label (due to removed static label binding) -> get new one
2748 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2751 || bgp_label_index_differs(new_select
, old_select
)
2752 || new_select
->sub_type
!= old_select
->sub_type
2753 || !bgp_is_valid_label(&dest
->local_label
)) {
2754 /* Enforced penultimate hop popping:
2755 * implicit-null for local routes, aggregate
2756 * and redistributed routes
2758 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2759 || new_select
->sub_type
2760 == BGP_ROUTE_AGGREGATE
2761 || new_select
->sub_type
2762 == BGP_ROUTE_REDISTRIBUTE
) {
2765 BGP_NODE_REGISTERED_FOR_LABEL
)
2768 BGP_NODE_LABEL_REQUESTED
))
2769 bgp_unregister_for_label(dest
);
2770 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2771 &dest
->local_label
);
2772 bgp_set_valid_label(&dest
->local_label
);
2774 bgp_register_for_label(dest
,
2777 } else if (CHECK_FLAG(dest
->flags
,
2778 BGP_NODE_REGISTERED_FOR_LABEL
)
2779 || CHECK_FLAG(dest
->flags
,
2780 BGP_NODE_LABEL_REQUESTED
)) {
2781 bgp_unregister_for_label(dest
);
2783 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2784 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2785 bgp_unregister_for_label(dest
);
2790 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2791 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2792 old_select
, new_select
);
2794 /* If best route remains the same and this is not due to user-initiated
2795 * clear, see exactly what needs to be done.
2797 if (old_select
&& old_select
== new_select
2798 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2799 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2800 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2801 if (bgp_zebra_has_route_changed(old_select
)) {
2802 #ifdef ENABLE_BGP_VNC
2803 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2804 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2806 if (bgp_fibupd_safi(safi
)
2807 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2809 if (new_select
->type
== ZEBRA_ROUTE_BGP
2810 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2811 || new_select
->sub_type
2812 == BGP_ROUTE_IMPORTED
))
2814 bgp_zebra_announce(dest
, p
, old_select
,
2819 /* If there is a change of interest to peers, reannounce the
2821 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2822 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2823 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2824 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2826 /* unicast routes must also be annouced to
2827 * labeled-unicast update-groups */
2828 if (safi
== SAFI_UNICAST
)
2829 group_announce_route(bgp
, afi
,
2830 SAFI_LABELED_UNICAST
, dest
,
2833 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2834 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2837 /* advertise/withdraw type-5 routes */
2838 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2839 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2840 bgp_process_evpn_route_injection(
2841 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2843 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2844 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2845 bgp_zebra_clear_route_change_flags(dest
);
2846 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2850 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2852 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2854 /* bestpath has changed; bump version */
2855 if (old_select
|| new_select
) {
2856 bgp_bump_version(dest
);
2858 if (!bgp
->t_rmap_def_originate_eval
) {
2862 update_group_refresh_default_originate_route_map
,
2863 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2864 &bgp
->t_rmap_def_originate_eval
);
2869 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2872 zlog_debug("%s: setting SELECTED flag", __func__
);
2873 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2874 bgp_path_info_unset_flag(dest
, new_select
,
2875 BGP_PATH_ATTR_CHANGED
);
2876 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2877 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2880 #ifdef ENABLE_BGP_VNC
2881 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2882 if (old_select
!= new_select
) {
2884 vnc_import_bgp_exterior_del_route(bgp
, p
,
2886 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2889 vnc_import_bgp_exterior_add_route(bgp
, p
,
2891 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2897 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2899 /* unicast routes must also be annouced to labeled-unicast update-groups
2901 if (safi
== SAFI_UNICAST
)
2902 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2906 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2907 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2908 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2909 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2910 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2911 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2913 /* if this is an evpn imported type-5 prefix,
2914 * we need to withdraw the route first to clear
2915 * the nh neigh and the RMAC entry.
2918 is_route_parent_evpn(old_select
))
2919 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2921 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2923 /* Withdraw the route from the kernel. */
2924 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2925 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2926 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2927 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2929 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2933 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2936 /* Clear any route change flags. */
2937 bgp_zebra_clear_route_change_flags(dest
);
2939 /* Reap old select bgp_path_info, if it has been removed */
2940 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2941 bgp_path_info_reap(dest
, old_select
);
2943 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2947 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2948 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2950 struct bgp_dest
*dest
;
2952 struct afi_safi_info
*thread_info
;
2954 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
2955 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
2957 thread_info
= THREAD_ARG(t
);
2958 XFREE(MTYPE_TMP
, thread_info
);
2959 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2962 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2963 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2964 get_afi_safi_str(afi
, safi
, false),
2965 bgp
->gr_info
[afi
][safi
].gr_deferred
);
2968 /* Process the route list */
2969 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
2970 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
2971 dest
= bgp_route_next(dest
)) {
2972 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
2975 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2976 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
2977 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2979 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
2980 bgp_dest_unlock_node(dest
);
2985 /* Send EOR message when all routes are processed */
2986 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
2987 bgp_send_delayed_eor(bgp
);
2988 /* Send route processing complete message to RIB */
2989 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2990 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2994 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2996 thread_info
->afi
= afi
;
2997 thread_info
->safi
= safi
;
2998 thread_info
->bgp
= bgp
;
3000 /* If there are more routes to be processed, start the
3003 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3004 BGP_ROUTE_SELECT_DELAY
,
3005 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3009 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3011 struct bgp_process_queue
*pqnode
= data
;
3012 struct bgp
*bgp
= pqnode
->bgp
;
3013 struct bgp_table
*table
;
3014 struct bgp_dest
*dest
;
3017 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3018 bgp_process_main_one(bgp
, NULL
, 0, 0);
3019 /* should always have dedicated wq call */
3020 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3024 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3025 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3026 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3027 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3028 table
= bgp_dest_table(dest
);
3029 /* note, new DESTs may be added as part of processing */
3030 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3032 bgp_dest_unlock_node(dest
);
3033 bgp_table_unlock(table
);
3039 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3041 struct bgp_process_queue
*pqnode
= data
;
3043 bgp_unlock(pqnode
->bgp
);
3045 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3048 void bgp_process_queue_init(struct bgp
*bgp
)
3050 if (!bgp
->process_queue
) {
3053 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3054 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3057 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3058 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3059 bgp
->process_queue
->spec
.max_retries
= 0;
3060 bgp
->process_queue
->spec
.hold
= 50;
3061 /* Use a higher yield value of 50ms for main queue processing */
3062 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3065 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3067 struct bgp_process_queue
*pqnode
;
3069 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3070 sizeof(struct bgp_process_queue
));
3072 /* unlocked in bgp_processq_del */
3073 pqnode
->bgp
= bgp_lock(bgp
);
3074 STAILQ_INIT(&pqnode
->pqueue
);
3079 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3081 #define ARBITRARY_PROCESS_QLEN 10000
3082 struct work_queue
*wq
= bgp
->process_queue
;
3083 struct bgp_process_queue
*pqnode
;
3084 int pqnode_reuse
= 0;
3086 /* already scheduled for processing? */
3087 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3090 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3093 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3094 if (BGP_DEBUG(update
, UPDATE_OUT
))
3095 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3103 /* Add route nodes to an existing work queue item until reaching the
3104 limit only if is from the same BGP view and it's not an EOIU marker
3106 if (work_queue_item_count(wq
)) {
3107 struct work_queue_item
*item
= work_queue_last_item(wq
);
3108 pqnode
= item
->data
;
3110 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3111 || pqnode
->bgp
!= bgp
3112 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3113 pqnode
= bgp_processq_alloc(bgp
);
3117 pqnode
= bgp_processq_alloc(bgp
);
3118 /* all unlocked in bgp_process_wq */
3119 bgp_table_lock(bgp_dest_table(dest
));
3121 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3122 bgp_dest_lock_node(dest
);
3124 /* can't be enqueued twice */
3125 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3126 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3130 work_queue_add(wq
, pqnode
);
3135 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3137 struct bgp_process_queue
*pqnode
;
3139 if (bgp
->process_queue
== NULL
)
3142 pqnode
= bgp_processq_alloc(bgp
);
3144 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3145 work_queue_add(bgp
->process_queue
, pqnode
);
3148 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3152 peer
= THREAD_ARG(thread
);
3153 peer
->t_pmax_restart
= NULL
;
3155 if (bgp_debug_neighbor_events(peer
))
3157 "%s Maximum-prefix restart timer expired, restore peering",
3160 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3161 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3166 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3170 bool filtered
= false;
3171 struct bgp_dest
*dest
;
3172 struct bgp_adj_in
*ain
;
3173 struct attr attr
= {};
3174 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3176 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3177 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3178 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3182 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3186 if (bgp_input_modifier(
3187 peer
, rn_p
, &attr
, afi
, safi
,
3188 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3196 bgp_attr_undup(&attr
, ain
->attr
);
3203 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3207 iana_safi_t pkt_safi
;
3208 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3209 PEER_FLAG_MAX_PREFIX_FORCE
))
3210 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3211 + peer
->pcount
[afi
][safi
]
3212 : peer
->pcount
[afi
][safi
];
3214 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3217 if (pcount
> peer
->pmax
[afi
][safi
]) {
3218 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3219 PEER_STATUS_PREFIX_LIMIT
)
3224 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3225 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3226 peer
->pmax
[afi
][safi
]);
3227 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3229 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3230 PEER_FLAG_MAX_PREFIX_WARNING
))
3233 /* Convert AFI, SAFI to values for packet. */
3234 pkt_afi
= afi_int2iana(afi
);
3235 pkt_safi
= safi_int2iana(safi
);
3239 ndata
[0] = (pkt_afi
>> 8);
3241 ndata
[2] = pkt_safi
;
3242 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3243 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3244 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3245 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3247 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3248 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3249 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3253 /* Dynamic peers will just close their connection. */
3254 if (peer_dynamic_neighbor(peer
))
3257 /* restart timer start */
3258 if (peer
->pmax_restart
[afi
][safi
]) {
3259 peer
->v_pmax_restart
=
3260 peer
->pmax_restart
[afi
][safi
] * 60;
3262 if (bgp_debug_neighbor_events(peer
))
3264 "%s Maximum-prefix restart timer started for %d secs",
3265 peer
->host
, peer
->v_pmax_restart
);
3267 BGP_TIMER_ON(peer
->t_pmax_restart
,
3268 bgp_maximum_prefix_restart_timer
,
3269 peer
->v_pmax_restart
);
3274 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3275 PEER_STATUS_PREFIX_LIMIT
);
3278 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3279 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3280 PEER_STATUS_PREFIX_THRESHOLD
)
3285 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3286 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3287 peer
->pmax
[afi
][safi
]);
3288 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3289 PEER_STATUS_PREFIX_THRESHOLD
);
3291 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3292 PEER_STATUS_PREFIX_THRESHOLD
);
3296 /* Unconditionally remove the route from the RIB, without taking
3297 * damping into consideration (eg, because the session went down)
3299 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3300 struct peer
*peer
, afi_t afi
, safi_t safi
)
3303 struct bgp
*bgp
= NULL
;
3304 bool delete_route
= false;
3306 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3309 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3310 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3312 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3315 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3316 delete_route
= true;
3317 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3318 delete_route
= true;
3320 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3321 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3322 bgp
= pi
->peer
->bgp
;
3323 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3328 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3329 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3332 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3333 struct peer
*peer
, afi_t afi
, safi_t safi
,
3334 struct prefix_rd
*prd
)
3336 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3338 /* apply dampening, if result is suppressed, we'll be retaining
3339 * the bgp_path_info in the RIB for historical reference.
3341 if (peer
->sort
== BGP_PEER_EBGP
) {
3342 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3343 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3344 == BGP_DAMP_SUPPRESSED
) {
3345 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3352 #ifdef ENABLE_BGP_VNC
3353 if (safi
== SAFI_MPLS_VPN
) {
3354 struct bgp_dest
*pdest
= NULL
;
3355 struct bgp_table
*table
= NULL
;
3357 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3358 (struct prefix
*)prd
);
3359 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3360 table
= bgp_dest_get_bgp_table_info(pdest
);
3362 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3363 peer
->bgp
, prd
, table
, p
, pi
);
3365 bgp_dest_unlock_node(pdest
);
3367 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3368 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3370 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3371 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3376 /* If this is an EVPN route, process for un-import. */
3377 if (safi
== SAFI_EVPN
)
3378 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3380 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3383 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3384 struct peer
*peer
, struct attr
*attr
,
3385 struct bgp_dest
*dest
)
3387 struct bgp_path_info
*new;
3389 /* Make new BGP info. */
3390 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3392 new->instance
= instance
;
3393 new->sub_type
= sub_type
;
3396 new->uptime
= bgp_clock();
3401 static void overlay_index_update(struct attr
*attr
,
3402 union gw_addr
*gw_ip
)
3406 if (gw_ip
== NULL
) {
3407 struct bgp_route_evpn eo
;
3409 memset(&eo
, 0, sizeof(eo
));
3410 bgp_attr_set_evpn_overlay(attr
, &eo
);
3412 struct bgp_route_evpn eo
= {.gw_ip
= *gw_ip
};
3414 bgp_attr_set_evpn_overlay(attr
, &eo
);
3418 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3419 union gw_addr
*gw_ip
)
3421 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3422 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3428 if (afi
!= AFI_L2VPN
)
3431 path_gw_ip
= eo
->gw_ip
;
3433 if (gw_ip
== NULL
) {
3434 memset(&temp
, 0, sizeof(temp
));
3435 path_gw_ip_remote
= &temp
.ip
;
3437 path_gw_ip_remote
= gw_ip
;
3439 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3442 /* Check if received nexthop is valid or not. */
3443 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3444 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3445 struct bgp_dest
*dest
)
3448 bool is_bgp_static_route
=
3449 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3453 * Only validated for unicast and multicast currently.
3454 * Also valid for EVPN where the nexthop is an IP address.
3455 * If we are a bgp static route being checked then there is
3456 * no need to check to see if the nexthop is martian as
3457 * that it should be ok.
3459 if (is_bgp_static_route
||
3460 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3463 /* If NEXT_HOP is present, validate it. */
3464 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3465 if (attr
->nexthop
.s_addr
== INADDR_ANY
3466 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3467 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3471 /* If MP_NEXTHOP is present, validate it. */
3472 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3473 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3474 * it is not an IPv6 link-local address.
3476 * If we receive an UPDATE with nexthop length set to 32 bytes
3477 * we shouldn't discard an UPDATE if it's set to (::).
3478 * The link-local (2st) is validated along the code path later.
3480 if (attr
->mp_nexthop_len
) {
3481 switch (attr
->mp_nexthop_len
) {
3482 case BGP_ATTR_NHLEN_IPV4
:
3483 case BGP_ATTR_NHLEN_VPNV4
:
3484 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3486 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3487 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3491 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3492 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3493 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3494 &attr
->mp_nexthop_global
)
3495 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3496 || IN6_IS_ADDR_MULTICAST(
3497 &attr
->mp_nexthop_global
)
3498 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3501 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3502 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3503 || IN6_IS_ADDR_MULTICAST(
3504 &attr
->mp_nexthop_global
)
3505 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3518 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3520 struct community
*old
;
3521 struct community
*new;
3522 struct community
*merge
;
3523 struct community
*no_export
;
3525 old
= attr
->community
;
3526 no_export
= community_str2com("no-export");
3531 merge
= community_merge(community_dup(old
), no_export
);
3534 community_free(&old
);
3536 new = community_uniq_sort(merge
);
3537 community_free(&merge
);
3539 new = community_dup(no_export
);
3542 community_free(&no_export
);
3544 attr
->community
= new;
3545 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3548 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3549 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3550 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3551 uint32_t num_labels
, int soft_reconfig
,
3552 struct bgp_route_evpn
*evpn
)
3555 int aspath_loop_count
= 0;
3556 struct bgp_dest
*dest
;
3558 struct attr new_attr
;
3559 struct attr
*attr_new
;
3560 struct bgp_path_info
*pi
;
3561 struct bgp_path_info
*new;
3562 struct bgp_path_info_extra
*extra
;
3564 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3566 int do_loop_check
= 1;
3567 int has_valid_label
= 0;
3569 uint8_t pi_type
= 0;
3570 uint8_t pi_sub_type
= 0;
3572 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3573 char pfxprint
[PREFIX2STR_BUFFER
];
3575 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3576 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3580 #ifdef ENABLE_BGP_VNC
3581 int vnc_implicit_withdraw
= 0;
3585 memset(&new_attr
, 0, sizeof(struct attr
));
3586 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3587 new_attr
.label
= MPLS_INVALID_LABEL
;
3590 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3591 /* TODO: Check to see if we can get rid of "is_valid_label" */
3592 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3593 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3595 has_valid_label
= bgp_is_valid_label(label
);
3597 if (has_valid_label
)
3598 assert(label
!= NULL
);
3600 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3602 * Suppress fib is enabled
3603 * BGP_OPT_NO_FIB is not enabled
3604 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3605 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3607 if (BGP_SUPPRESS_FIB_ENABLED(bgp
) &&
3608 (sub_type
== BGP_ROUTE_NORMAL
) &&
3609 (!bgp_option_check(BGP_OPT_NO_FIB
)) &&
3610 (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3611 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3613 /* When peer's soft reconfiguration enabled. Record input packet in
3616 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3617 && peer
!= bgp
->peer_self
)
3618 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3620 /* Check previously received route. */
3621 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3622 if (pi
->peer
== peer
&& pi
->type
== type
3623 && pi
->sub_type
== sub_type
3624 && pi
->addpath_rx_id
== addpath_id
)
3627 /* AS path local-as loop check. */
3628 if (peer
->change_local_as
) {
3629 if (peer
->allowas_in
[afi
][safi
])
3630 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3631 else if (!CHECK_FLAG(peer
->flags
,
3632 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3633 aspath_loop_count
= 1;
3635 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3636 > aspath_loop_count
) {
3637 peer
->stat_pfx_aspath_loop
++;
3638 reason
= "as-path contains our own AS A;";
3643 /* If the peer is configured for "allowas-in origin" and the last ASN in
3645 * as-path is our ASN then we do not need to call aspath_loop_check
3647 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3648 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3651 /* AS path loop check. */
3652 if (do_loop_check
) {
3653 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3654 > peer
->allowas_in
[afi
][safi
]
3655 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3656 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3657 > peer
->allowas_in
[afi
][safi
])) {
3658 peer
->stat_pfx_aspath_loop
++;
3659 reason
= "as-path contains our own AS;";
3664 /* Route reflector originator ID check. */
3665 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3666 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3667 peer
->stat_pfx_originator_loop
++;
3668 reason
= "originator is us;";
3672 /* Route reflector cluster ID check. */
3673 if (bgp_cluster_filter(peer
, attr
)) {
3674 peer
->stat_pfx_cluster_loop
++;
3675 reason
= "reflected from the same cluster;";
3679 /* Apply incoming filter. */
3680 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3681 peer
->stat_pfx_filter
++;
3686 /* RFC 8212 to prevent route leaks.
3687 * This specification intends to improve this situation by requiring the
3688 * explicit configuration of both BGP Import and Export Policies for any
3689 * External BGP (EBGP) session such as customers, peers, or
3690 * confederation boundaries for all enabled address families. Through
3691 * codification of the aforementioned requirement, operators will
3692 * benefit from consistent behavior across different BGP
3695 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3696 if (!bgp_inbound_policy_exists(peer
,
3697 &peer
->filter
[afi
][safi
])) {
3698 reason
= "inbound policy missing";
3702 /* draft-ietf-idr-deprecate-as-set-confed-set
3703 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3704 * Eventually, This document (if approved) updates RFC 4271
3705 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3706 * and obsoletes RFC 6472.
3708 if (peer
->bgp
->reject_as_sets
)
3709 if (aspath_check_as_sets(attr
->aspath
)) {
3711 "as-path contains AS_SET or AS_CONFED_SET type;";
3717 /* Apply incoming route-map.
3718 * NB: new_attr may now contain newly allocated values from route-map
3720 * commands, so we need bgp_attr_flush in the error paths, until we
3722 * the attr (which takes over the memory references) */
3723 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3726 peer
->stat_pfx_filter
++;
3727 reason
= "route-map;";
3728 bgp_attr_flush(&new_attr
);
3732 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3733 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3734 /* remove from RIB previous entry */
3735 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3738 if (peer
->sort
== BGP_PEER_EBGP
) {
3741 * A BGP speaker receiving an announcement tagged with the
3742 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3743 * NO_EXPORT community as defined in RFC1997, or a
3744 * similar community, to prevent propagation of the
3745 * prefix outside the local AS. The community to prevent
3746 * propagation SHOULD be chosen according to the operator's
3749 if (new_attr
.community
3750 && community_include(new_attr
.community
,
3751 COMMUNITY_BLACKHOLE
))
3752 bgp_attr_add_no_export_community(&new_attr
);
3754 /* If we receive the graceful-shutdown community from an eBGP
3755 * peer we must lower local-preference */
3756 if (new_attr
.community
3757 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3758 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3759 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3761 /* If graceful-shutdown is configured then add the GSHUT
3762 * community to all paths received from eBGP peers */
3763 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3764 bgp_attr_add_gshut_community(&new_attr
);
3769 pi_sub_type
= pi
->sub_type
;
3772 /* next hop check. */
3773 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3774 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3776 peer
->stat_pfx_nh_invalid
++;
3777 reason
= "martian or self next-hop;";
3778 bgp_attr_flush(&new_attr
);
3782 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3783 peer
->stat_pfx_nh_invalid
++;
3784 reason
= "self mac;";
3788 /* Update Overlay Index */
3789 if (afi
== AFI_L2VPN
) {
3790 overlay_index_update(&new_attr
,
3791 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3794 attr_new
= bgp_attr_intern(&new_attr
);
3796 /* If maximum prefix count is configured and current prefix
3799 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3802 /* If the update is implicit withdraw. */
3804 pi
->uptime
= bgp_clock();
3805 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3807 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3809 /* Same attribute comes in. */
3810 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3812 && (!has_valid_label
3813 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3814 num_labels
* sizeof(mpls_label_t
))
3816 && (overlay_index_equal(
3818 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3819 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3820 && peer
->sort
== BGP_PEER_EBGP
3821 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3822 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3823 bgp_debug_rdpfxpath2str(
3824 afi
, safi
, prd
, p
, label
,
3825 num_labels
, addpath_id
? 1 : 0,
3826 addpath_id
, pfx_buf
,
3828 zlog_debug("%s rcvd %s", peer
->host
,
3832 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3833 != BGP_DAMP_SUPPRESSED
) {
3834 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3836 bgp_process(bgp
, dest
, afi
, safi
);
3838 } else /* Duplicate - odd */
3840 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3841 if (!peer
->rcvd_attr_printed
) {
3843 "%s rcvd UPDATE w/ attr: %s",
3845 peer
->rcvd_attr_str
);
3846 peer
->rcvd_attr_printed
= 1;
3849 bgp_debug_rdpfxpath2str(
3850 afi
, safi
, prd
, p
, label
,
3851 num_labels
, addpath_id
? 1 : 0,
3852 addpath_id
, pfx_buf
,
3855 "%s rcvd %s...duplicate ignored",
3856 peer
->host
, pfx_buf
);
3859 /* graceful restart STALE flag unset. */
3860 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3861 bgp_path_info_unset_flag(
3862 dest
, pi
, BGP_PATH_STALE
);
3863 bgp_dest_set_defer_flag(dest
, false);
3864 bgp_process(bgp
, dest
, afi
, safi
);
3868 bgp_dest_unlock_node(dest
);
3869 bgp_attr_unintern(&attr_new
);
3874 /* Withdraw/Announce before we fully processed the withdraw */
3875 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3876 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3877 bgp_debug_rdpfxpath2str(
3878 afi
, safi
, prd
, p
, label
, num_labels
,
3879 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3882 "%s rcvd %s, flapped quicker than processing",
3883 peer
->host
, pfx_buf
);
3886 bgp_path_info_restore(dest
, pi
);
3889 /* Received Logging. */
3890 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3891 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3892 num_labels
, addpath_id
? 1 : 0,
3893 addpath_id
, pfx_buf
,
3895 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3898 /* graceful restart STALE flag unset. */
3899 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3900 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3901 bgp_dest_set_defer_flag(dest
, false);
3904 /* The attribute is changed. */
3905 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3907 /* implicit withdraw, decrement aggregate and pcount here.
3908 * only if update is accepted, they'll increment below.
3910 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3912 /* Update bgp route dampening information. */
3913 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3914 && peer
->sort
== BGP_PEER_EBGP
) {
3915 /* This is implicit withdraw so we should update
3916 * dampening information.
3918 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3919 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3921 #ifdef ENABLE_BGP_VNC
3922 if (safi
== SAFI_MPLS_VPN
) {
3923 struct bgp_dest
*pdest
= NULL
;
3924 struct bgp_table
*table
= NULL
;
3926 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3927 (struct prefix
*)prd
);
3928 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3929 table
= bgp_dest_get_bgp_table_info(pdest
);
3931 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3932 bgp
, prd
, table
, p
, pi
);
3934 bgp_dest_unlock_node(pdest
);
3936 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3937 && (safi
== SAFI_UNICAST
)) {
3938 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3940 * Implicit withdraw case.
3942 ++vnc_implicit_withdraw
;
3943 vnc_import_bgp_del_route(bgp
, p
, pi
);
3944 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3949 /* Special handling for EVPN update of an existing route. If the
3950 * extended community attribute has changed, we need to
3952 * the route using its existing extended community. It will be
3953 * subsequently processed for import with the new extended
3956 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3959 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3961 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3964 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3965 attr_new
->ecommunity
);
3967 if (bgp_debug_update(peer
, p
, NULL
, 1))
3969 "Change in EXT-COMM, existing %s new %s",
3971 pi
->attr
->ecommunity
),
3973 attr_new
->ecommunity
));
3974 if (safi
== SAFI_EVPN
)
3975 bgp_evpn_unimport_route(
3976 bgp
, afi
, safi
, p
, pi
);
3977 else /* SAFI_MPLS_VPN */
3978 vpn_leak_to_vrf_withdraw(bgp
,
3984 /* Update to new attribute. */
3985 bgp_attr_unintern(&pi
->attr
);
3986 pi
->attr
= attr_new
;
3988 /* Update MPLS label */
3989 if (has_valid_label
) {
3990 extra
= bgp_path_info_extra_get(pi
);
3991 if (extra
->label
!= label
) {
3992 memcpy(&extra
->label
, label
,
3993 num_labels
* sizeof(mpls_label_t
));
3994 extra
->num_labels
= num_labels
;
3996 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3997 bgp_set_valid_label(&extra
->label
[0]);
4000 /* Update SRv6 SID */
4001 if (attr
->srv6_l3vpn
) {
4002 extra
= bgp_path_info_extra_get(pi
);
4003 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4004 sid_copy(&extra
->sid
[0],
4005 &attr
->srv6_l3vpn
->sid
);
4006 extra
->num_sids
= 1;
4008 } else if (attr
->srv6_vpn
) {
4009 extra
= bgp_path_info_extra_get(pi
);
4010 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4011 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4012 extra
->num_sids
= 1;
4016 #ifdef ENABLE_BGP_VNC
4017 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4018 && (safi
== SAFI_UNICAST
)) {
4019 if (vnc_implicit_withdraw
) {
4021 * Add back the route with its new attributes
4023 * The route is still selected, until the route
4025 * queued by bgp_process actually runs. We have
4027 * update to the VNC side immediately to avoid
4029 * configuration changes (e.g., route-map
4031 * trigger re-importation of the entire RIB.
4033 vnc_import_bgp_add_route(bgp
, p
, pi
);
4034 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4039 /* Update bgp route dampening information. */
4040 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4041 && peer
->sort
== BGP_PEER_EBGP
) {
4042 /* Now we do normal update dampening. */
4043 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4044 if (ret
== BGP_DAMP_SUPPRESSED
) {
4045 bgp_dest_unlock_node(dest
);
4050 /* Nexthop reachability check - for unicast and
4051 * labeled-unicast.. */
4052 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4053 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4054 || (safi
== SAFI_EVPN
&&
4055 bgp_evpn_is_prefix_nht_supported(p
))) {
4056 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4057 && peer
->ttl
== BGP_DEFAULT_TTL
4058 && !CHECK_FLAG(peer
->flags
,
4059 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4060 && !CHECK_FLAG(bgp
->flags
,
4061 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4066 struct bgp
*bgp_nexthop
= bgp
;
4068 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4069 bgp_nexthop
= pi
->extra
->bgp_orig
;
4071 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4073 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4074 safi
, pi
, NULL
, connected
)
4075 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4076 bgp_path_info_set_flag(dest
, pi
,
4079 if (BGP_DEBUG(nht
, NHT
)) {
4080 zlog_debug("%s(%pI4): NH unresolved",
4082 (in_addr_t
*)&attr_new
->nexthop
);
4084 bgp_path_info_unset_flag(dest
, pi
,
4088 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4090 #ifdef ENABLE_BGP_VNC
4091 if (safi
== SAFI_MPLS_VPN
) {
4092 struct bgp_dest
*pdest
= NULL
;
4093 struct bgp_table
*table
= NULL
;
4095 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4096 (struct prefix
*)prd
);
4097 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4098 table
= bgp_dest_get_bgp_table_info(pdest
);
4100 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4101 bgp
, prd
, table
, p
, pi
);
4103 bgp_dest_unlock_node(pdest
);
4107 /* If this is an EVPN route and some attribute has changed,
4109 * route for import. If the extended community has changed, we
4111 * have done the un-import earlier and the import would result
4113 * route getting injected into appropriate L2 VNIs. If it is
4115 * some other attribute change, the import will result in
4117 * the attributes for the route in the VNI(s).
4119 if (safi
== SAFI_EVPN
&& !same_attr
&&
4120 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4121 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4123 /* Process change. */
4124 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4126 bgp_process(bgp
, dest
, afi
, safi
);
4127 bgp_dest_unlock_node(dest
);
4129 if (SAFI_UNICAST
== safi
4130 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4131 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4133 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4135 if ((SAFI_MPLS_VPN
== safi
)
4136 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4138 vpn_leak_to_vrf_update(bgp
, pi
);
4141 #ifdef ENABLE_BGP_VNC
4142 if (SAFI_MPLS_VPN
== safi
) {
4143 mpls_label_t label_decoded
= decode_label(label
);
4145 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4146 type
, sub_type
, &label_decoded
);
4148 if (SAFI_ENCAP
== safi
) {
4149 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4150 type
, sub_type
, NULL
);
4155 } // End of implicit withdraw
4157 /* Received Logging. */
4158 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4159 if (!peer
->rcvd_attr_printed
) {
4160 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4161 peer
->rcvd_attr_str
);
4162 peer
->rcvd_attr_printed
= 1;
4165 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4166 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4168 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4171 /* Make new BGP info. */
4172 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4174 /* Update MPLS label */
4175 if (has_valid_label
) {
4176 extra
= bgp_path_info_extra_get(new);
4177 if (extra
->label
!= label
) {
4178 memcpy(&extra
->label
, label
,
4179 num_labels
* sizeof(mpls_label_t
));
4180 extra
->num_labels
= num_labels
;
4182 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4183 bgp_set_valid_label(&extra
->label
[0]);
4186 /* Update SRv6 SID */
4187 if (safi
== SAFI_MPLS_VPN
) {
4188 extra
= bgp_path_info_extra_get(new);
4189 if (attr
->srv6_l3vpn
) {
4190 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4191 extra
->num_sids
= 1;
4192 } else if (attr
->srv6_vpn
) {
4193 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4194 extra
->num_sids
= 1;
4198 /* Update Overlay Index */
4199 if (afi
== AFI_L2VPN
) {
4200 overlay_index_update(new->attr
,
4201 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4203 /* Nexthop reachability check. */
4204 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4205 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4206 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4207 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4208 && peer
->ttl
== BGP_DEFAULT_TTL
4209 && !CHECK_FLAG(peer
->flags
,
4210 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4211 && !CHECK_FLAG(bgp
->flags
,
4212 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4217 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4219 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4221 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4222 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4224 if (BGP_DEBUG(nht
, NHT
)) {
4225 char buf1
[INET6_ADDRSTRLEN
];
4227 (const void *)&attr_new
->nexthop
,
4228 buf1
, INET6_ADDRSTRLEN
);
4229 zlog_debug("%s(%s): NH unresolved", __func__
,
4232 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4235 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4238 new->addpath_rx_id
= addpath_id
;
4240 /* Increment prefix */
4241 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4243 /* Register new BGP information. */
4244 bgp_path_info_add(dest
, new);
4246 /* route_node_get lock */
4247 bgp_dest_unlock_node(dest
);
4249 #ifdef ENABLE_BGP_VNC
4250 if (safi
== SAFI_MPLS_VPN
) {
4251 struct bgp_dest
*pdest
= NULL
;
4252 struct bgp_table
*table
= NULL
;
4254 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4255 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4256 table
= bgp_dest_get_bgp_table_info(pdest
);
4258 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4259 bgp
, prd
, table
, p
, new);
4261 bgp_dest_unlock_node(pdest
);
4265 /* If this is an EVPN route, process for import. */
4266 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4267 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4269 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4271 /* Process change. */
4272 bgp_process(bgp
, dest
, afi
, safi
);
4274 if (SAFI_UNICAST
== safi
4275 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4276 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4277 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4279 if ((SAFI_MPLS_VPN
== safi
)
4280 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4282 vpn_leak_to_vrf_update(bgp
, new);
4284 #ifdef ENABLE_BGP_VNC
4285 if (SAFI_MPLS_VPN
== safi
) {
4286 mpls_label_t label_decoded
= decode_label(label
);
4288 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4289 sub_type
, &label_decoded
);
4291 if (SAFI_ENCAP
== safi
) {
4292 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4299 /* This BGP update is filtered. Log the reason then update BGP
4302 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4304 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4305 if (!peer
->rcvd_attr_printed
) {
4306 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4307 peer
->rcvd_attr_str
);
4308 peer
->rcvd_attr_printed
= 1;
4311 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4312 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4314 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4315 peer
->host
, pfx_buf
, reason
);
4319 /* If this is an EVPN route, un-import it as it is now filtered.
4321 if (safi
== SAFI_EVPN
)
4322 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4324 if (SAFI_UNICAST
== safi
4325 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4326 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4328 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4330 if ((SAFI_MPLS_VPN
== safi
)
4331 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4333 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4336 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4339 bgp_dest_unlock_node(dest
);
4341 #ifdef ENABLE_BGP_VNC
4343 * Filtered update is treated as an implicit withdrawal (see
4345 * a few lines above)
4347 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4348 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4356 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4357 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4358 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4359 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4362 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4363 struct bgp_dest
*dest
;
4364 struct bgp_path_info
*pi
;
4366 #ifdef ENABLE_BGP_VNC
4367 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4368 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4376 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4378 /* If peer is soft reconfiguration enabled. Record input packet for
4379 * further calculation.
4381 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4382 * routes that are filtered. This tanks out Quagga RS pretty badly due
4384 * the iteration over all RS clients.
4385 * Since we need to remove the entry from adj_in anyway, do that first
4387 * if there was no entry, we don't need to do anything more.
4389 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4390 && peer
!= bgp
->peer_self
)
4391 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4392 peer
->stat_pfx_dup_withdraw
++;
4394 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4395 bgp_debug_rdpfxpath2str(
4396 afi
, safi
, prd
, p
, label
, num_labels
,
4397 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4400 "%s withdrawing route %s not in adj-in",
4401 peer
->host
, pfx_buf
);
4403 bgp_dest_unlock_node(dest
);
4407 /* Lookup withdrawn route. */
4408 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4409 if (pi
->peer
== peer
&& pi
->type
== type
4410 && pi
->sub_type
== sub_type
4411 && pi
->addpath_rx_id
== addpath_id
)
4415 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4416 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4417 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4419 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4423 /* Withdraw specified route from routing table. */
4424 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4425 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4426 if (SAFI_UNICAST
== safi
4427 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4428 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4429 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4431 if ((SAFI_MPLS_VPN
== safi
)
4432 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4434 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4436 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4437 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4438 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4440 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4443 /* Unlock bgp_node_get() lock. */
4444 bgp_dest_unlock_node(dest
);
4449 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4452 struct update_subgroup
*subgrp
;
4453 subgrp
= peer_subgroup(peer
, afi
, safi
);
4454 subgroup_default_originate(subgrp
, withdraw
);
4459 * bgp_stop_announce_route_timer
4461 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4463 if (!paf
->t_announce_route
)
4466 thread_cancel(&paf
->t_announce_route
);
4470 * bgp_announce_route_timer_expired
4472 * Callback that is invoked when the route announcement timer for a
4475 static int bgp_announce_route_timer_expired(struct thread
*t
)
4477 struct peer_af
*paf
;
4480 paf
= THREAD_ARG(t
);
4483 if (peer
->status
!= Established
)
4486 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4489 peer_af_announce_route(paf
, 1);
4491 /* Notify BGP conditional advertisement scanner percess */
4492 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4498 * bgp_announce_route
4500 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4502 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4504 struct peer_af
*paf
;
4505 struct update_subgroup
*subgrp
;
4507 paf
= peer_af_find(peer
, afi
, safi
);
4510 subgrp
= PAF_SUBGRP(paf
);
4513 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4514 * or a refresh has already been triggered.
4516 if (!subgrp
|| paf
->t_announce_route
)
4520 * Start a timer to stagger/delay the announce. This serves
4521 * two purposes - announcement can potentially be combined for
4522 * multiple peers and the announcement doesn't happen in the
4525 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4526 (subgrp
->peer_count
== 1)
4527 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4528 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4529 &paf
->t_announce_route
);
4533 * Announce routes from all AF tables to a peer.
4535 * This should ONLY be called when there is a need to refresh the
4536 * routes to the peer based on a policy change for this peer alone
4537 * or a route refresh request received from the peer.
4538 * The operation will result in splitting the peer from its existing
4539 * subgroups and putting it in new subgroups.
4541 void bgp_announce_route_all(struct peer
*peer
)
4546 FOREACH_AFI_SAFI (afi
, safi
)
4547 bgp_announce_route(peer
, afi
, safi
);
4550 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4551 struct bgp_table
*table
,
4552 struct prefix_rd
*prd
)
4555 struct bgp_dest
*dest
;
4556 struct bgp_adj_in
*ain
;
4559 table
= peer
->bgp
->rib
[afi
][safi
];
4561 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4562 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4563 if (ain
->peer
!= peer
)
4566 struct bgp_path_info
*pi
;
4567 uint32_t num_labels
= 0;
4568 mpls_label_t
*label_pnt
= NULL
;
4569 struct bgp_route_evpn evpn
;
4571 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4573 if (pi
->peer
== peer
)
4576 if (pi
&& pi
->extra
)
4577 num_labels
= pi
->extra
->num_labels
;
4579 label_pnt
= &pi
->extra
->label
[0];
4582 bgp_attr_get_evpn_overlay(pi
->attr
),
4585 memset(&evpn
, 0, sizeof(evpn
));
4587 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4588 ain
->addpath_rx_id
, ain
->attr
, afi
,
4589 safi
, ZEBRA_ROUTE_BGP
,
4590 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4591 num_labels
, 1, &evpn
);
4594 bgp_dest_unlock_node(dest
);
4600 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4602 struct bgp_dest
*dest
;
4603 struct bgp_table
*table
;
4605 if (peer
->status
!= Established
)
4608 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4609 && (safi
!= SAFI_EVPN
))
4610 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4612 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4613 dest
= bgp_route_next(dest
)) {
4614 table
= bgp_dest_get_bgp_table_info(dest
);
4619 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4620 struct prefix_rd prd
;
4622 prd
.family
= AF_UNSPEC
;
4624 memcpy(&prd
.val
, p
->u
.val
, 8);
4626 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4631 struct bgp_clear_node_queue
{
4632 struct bgp_dest
*dest
;
4635 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4637 struct bgp_clear_node_queue
*cnq
= data
;
4638 struct bgp_dest
*dest
= cnq
->dest
;
4639 struct peer
*peer
= wq
->spec
.data
;
4640 struct bgp_path_info
*pi
;
4642 afi_t afi
= bgp_dest_table(dest
)->afi
;
4643 safi_t safi
= bgp_dest_table(dest
)->safi
;
4645 assert(dest
&& peer
);
4648 /* It is possible that we have multiple paths for a prefix from a peer
4649 * if that peer is using AddPath.
4651 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4652 if (pi
->peer
!= peer
)
4655 /* graceful restart STALE flag set. */
4656 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4657 && peer
->nsf
[afi
][safi
])
4658 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4659 PEER_STATUS_ENHANCED_REFRESH
))
4660 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4661 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4662 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4664 /* If this is an EVPN route, process for
4666 if (safi
== SAFI_EVPN
)
4667 bgp_evpn_unimport_route(
4669 bgp_dest_get_prefix(dest
), pi
);
4670 /* Handle withdraw for VRF route-leaking and L3VPN */
4671 if (SAFI_UNICAST
== safi
4672 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4673 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4674 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4677 if (SAFI_MPLS_VPN
== safi
&&
4678 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4679 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4682 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4688 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4690 struct bgp_clear_node_queue
*cnq
= data
;
4691 struct bgp_dest
*dest
= cnq
->dest
;
4692 struct bgp_table
*table
= bgp_dest_table(dest
);
4694 bgp_dest_unlock_node(dest
);
4695 bgp_table_unlock(table
);
4696 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4699 static void bgp_clear_node_complete(struct work_queue
*wq
)
4701 struct peer
*peer
= wq
->spec
.data
;
4703 /* Tickle FSM to start moving again */
4704 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4706 peer_unlock(peer
); /* bgp_clear_route */
4709 static void bgp_clear_node_queue_init(struct peer
*peer
)
4711 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4713 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4714 #undef CLEAR_QUEUE_NAME_LEN
4716 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4717 peer
->clear_node_queue
->spec
.hold
= 10;
4718 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4719 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4720 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4721 peer
->clear_node_queue
->spec
.max_retries
= 0;
4723 /* we only 'lock' this peer reference when the queue is actually active
4725 peer
->clear_node_queue
->spec
.data
= peer
;
4728 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4729 struct bgp_table
*table
)
4731 struct bgp_dest
*dest
;
4732 int force
= peer
->bgp
->process_queue
? 0 : 1;
4735 table
= peer
->bgp
->rib
[afi
][safi
];
4737 /* If still no table => afi/safi isn't configured at all or smth. */
4741 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4742 struct bgp_path_info
*pi
, *next
;
4743 struct bgp_adj_in
*ain
;
4744 struct bgp_adj_in
*ain_next
;
4746 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4747 * queued for every clearing peer, regardless of whether it is
4748 * relevant to the peer at hand.
4750 * Overview: There are 3 different indices which need to be
4751 * scrubbed, potentially, when a peer is removed:
4753 * 1 peer's routes visible via the RIB (ie accepted routes)
4754 * 2 peer's routes visible by the (optional) peer's adj-in index
4755 * 3 other routes visible by the peer's adj-out index
4757 * 3 there is no hurry in scrubbing, once the struct peer is
4758 * removed from bgp->peer, we could just GC such deleted peer's
4759 * adj-outs at our leisure.
4761 * 1 and 2 must be 'scrubbed' in some way, at least made
4762 * invisible via RIB index before peer session is allowed to be
4763 * brought back up. So one needs to know when such a 'search' is
4768 * - there'd be a single global queue or a single RIB walker
4769 * - rather than tracking which route_nodes still need to be
4770 * examined on a peer basis, we'd track which peers still
4773 * Given that our per-peer prefix-counts now should be reliable,
4774 * this may actually be achievable. It doesn't seem to be a huge
4775 * problem at this time,
4777 * It is possible that we have multiple paths for a prefix from
4779 * if that peer is using AddPath.
4783 ain_next
= ain
->next
;
4785 if (ain
->peer
== peer
) {
4786 bgp_adj_in_remove(dest
, ain
);
4787 bgp_dest_unlock_node(dest
);
4793 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4795 if (pi
->peer
!= peer
)
4799 bgp_path_info_reap(dest
, pi
);
4801 struct bgp_clear_node_queue
*cnq
;
4803 /* both unlocked in bgp_clear_node_queue_del */
4804 bgp_table_lock(bgp_dest_table(dest
));
4805 bgp_dest_lock_node(dest
);
4807 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4808 sizeof(struct bgp_clear_node_queue
));
4810 work_queue_add(peer
->clear_node_queue
, cnq
);
4818 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4820 struct bgp_dest
*dest
;
4821 struct bgp_table
*table
;
4823 if (peer
->clear_node_queue
== NULL
)
4824 bgp_clear_node_queue_init(peer
);
4826 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4827 * Idle until it receives a Clearing_Completed event. This protects
4828 * against peers which flap faster than we can we clear, which could
4831 * a) race with routes from the new session being installed before
4832 * clear_route_node visits the node (to delete the route of that
4834 * b) resource exhaustion, clear_route_node likely leads to an entry
4835 * on the process_main queue. Fast-flapping could cause that queue
4839 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4840 * the unlock will happen upon work-queue completion; other wise, the
4841 * unlock happens at the end of this function.
4843 if (!peer
->clear_node_queue
->thread
)
4846 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4847 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4849 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4850 dest
= bgp_route_next(dest
)) {
4851 table
= bgp_dest_get_bgp_table_info(dest
);
4855 bgp_clear_route_table(peer
, afi
, safi
, table
);
4858 /* unlock if no nodes got added to the clear-node-queue. */
4859 if (!peer
->clear_node_queue
->thread
)
4863 void bgp_clear_route_all(struct peer
*peer
)
4868 FOREACH_AFI_SAFI (afi
, safi
)
4869 bgp_clear_route(peer
, afi
, safi
);
4871 #ifdef ENABLE_BGP_VNC
4872 rfapiProcessPeerDown(peer
);
4876 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4878 struct bgp_table
*table
;
4879 struct bgp_dest
*dest
;
4880 struct bgp_adj_in
*ain
;
4881 struct bgp_adj_in
*ain_next
;
4883 table
= peer
->bgp
->rib
[afi
][safi
];
4885 /* It is possible that we have multiple paths for a prefix from a peer
4886 * if that peer is using AddPath.
4888 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4892 ain_next
= ain
->next
;
4894 if (ain
->peer
== peer
) {
4895 bgp_adj_in_remove(dest
, ain
);
4896 bgp_dest_unlock_node(dest
);
4904 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4906 struct bgp_dest
*dest
;
4907 struct bgp_path_info
*pi
;
4908 struct bgp_table
*table
;
4910 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4911 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4912 dest
= bgp_route_next(dest
)) {
4913 struct bgp_dest
*rm
;
4915 /* look for neighbor in tables */
4916 table
= bgp_dest_get_bgp_table_info(dest
);
4920 for (rm
= bgp_table_top(table
); rm
;
4921 rm
= bgp_route_next(rm
))
4922 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4924 if (pi
->peer
!= peer
)
4926 if (!CHECK_FLAG(pi
->flags
,
4930 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4935 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4936 dest
= bgp_route_next(dest
))
4937 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4939 if (pi
->peer
!= peer
)
4941 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4943 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4949 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4951 struct bgp_dest
*dest
, *ndest
;
4952 struct bgp_path_info
*pi
;
4953 struct bgp_table
*table
;
4955 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4956 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4957 dest
= bgp_route_next(dest
)) {
4958 table
= bgp_dest_get_bgp_table_info(dest
);
4962 for (ndest
= bgp_table_top(table
); ndest
;
4963 ndest
= bgp_route_next(ndest
)) {
4964 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
4966 if (pi
->peer
!= peer
)
4970 peer
->af_sflags
[afi
][safi
],
4971 PEER_STATUS_ENHANCED_REFRESH
))
4972 && !CHECK_FLAG(pi
->flags
,
4976 BGP_PATH_UNUSEABLE
)) {
4977 if (bgp_debug_neighbor_events(
4980 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4984 bgp_dest_get_prefix(
4987 bgp_path_info_set_flag(
4995 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4996 dest
= bgp_route_next(dest
)) {
4997 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4999 if (pi
->peer
!= peer
)
5002 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5003 PEER_STATUS_ENHANCED_REFRESH
))
5004 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5005 && !CHECK_FLAG(pi
->flags
,
5006 BGP_PATH_UNUSEABLE
)) {
5007 if (bgp_debug_neighbor_events(peer
))
5009 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5013 bgp_dest_get_prefix(
5016 bgp_path_info_set_flag(dest
, pi
,
5024 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5026 if (peer
->sort
== BGP_PEER_IBGP
)
5029 if (peer
->sort
== BGP_PEER_EBGP
5030 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5031 || FILTER_LIST_OUT_NAME(filter
)
5032 || DISTRIBUTE_OUT_NAME(filter
)))
5037 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5039 if (peer
->sort
== BGP_PEER_IBGP
)
5042 if (peer
->sort
== BGP_PEER_EBGP
5043 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5044 || FILTER_LIST_IN_NAME(filter
)
5045 || DISTRIBUTE_IN_NAME(filter
)))
5050 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5053 struct bgp_dest
*dest
;
5054 struct bgp_path_info
*pi
;
5055 struct bgp_path_info
*next
;
5057 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5058 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5059 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5063 /* Unimport EVPN routes from VRFs */
5064 if (safi
== SAFI_EVPN
)
5065 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5068 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5069 && pi
->type
== ZEBRA_ROUTE_BGP
5070 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5071 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5072 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5074 if (bgp_fibupd_safi(safi
))
5075 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5078 bgp_path_info_reap(dest
, pi
);
5082 /* Delete all kernel routes. */
5083 void bgp_cleanup_routes(struct bgp
*bgp
)
5086 struct bgp_dest
*dest
;
5087 struct bgp_table
*table
;
5089 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5090 if (afi
== AFI_L2VPN
)
5092 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5095 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5097 if (afi
!= AFI_L2VPN
) {
5099 safi
= SAFI_MPLS_VPN
;
5100 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5101 dest
= bgp_route_next(dest
)) {
5102 table
= bgp_dest_get_bgp_table_info(dest
);
5103 if (table
!= NULL
) {
5104 bgp_cleanup_table(bgp
, table
, safi
);
5105 bgp_table_finish(&table
);
5106 bgp_dest_set_bgp_table_info(dest
, NULL
);
5107 bgp_dest_unlock_node(dest
);
5111 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5112 dest
= bgp_route_next(dest
)) {
5113 table
= bgp_dest_get_bgp_table_info(dest
);
5114 if (table
!= NULL
) {
5115 bgp_cleanup_table(bgp
, table
, safi
);
5116 bgp_table_finish(&table
);
5117 bgp_dest_set_bgp_table_info(dest
, NULL
);
5118 bgp_dest_unlock_node(dest
);
5123 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5124 dest
= bgp_route_next(dest
)) {
5125 table
= bgp_dest_get_bgp_table_info(dest
);
5126 if (table
!= NULL
) {
5127 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5128 bgp_table_finish(&table
);
5129 bgp_dest_set_bgp_table_info(dest
, NULL
);
5130 bgp_dest_unlock_node(dest
);
5135 void bgp_reset(void)
5138 bgp_zclient_reset();
5139 access_list_reset();
5140 prefix_list_reset();
5143 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5145 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5146 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5147 PEER_CAP_ADDPATH_AF_TX_RCV
));
5150 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5152 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5153 struct bgp_nlri
*packet
)
5162 int addpath_encoded
;
5163 uint32_t addpath_id
;
5166 lim
= pnt
+ packet
->length
;
5168 safi
= packet
->safi
;
5170 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5172 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5173 syntactic validity. If the field is syntactically incorrect,
5174 then the Error Subcode is set to Invalid Network Field. */
5175 for (; pnt
< lim
; pnt
+= psize
) {
5176 /* Clear prefix structure. */
5177 memset(&p
, 0, sizeof(struct prefix
));
5179 if (addpath_encoded
) {
5181 /* When packet overflow occurs return immediately. */
5182 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5183 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5185 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5186 addpath_id
= ntohl(addpath_id
);
5187 pnt
+= BGP_ADDPATH_ID_LEN
;
5190 /* Fetch prefix length. */
5191 p
.prefixlen
= *pnt
++;
5192 /* afi/safi validity already verified by caller,
5193 * bgp_update_receive */
5194 p
.family
= afi2family(afi
);
5196 /* Prefix length check. */
5197 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5200 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5201 peer
->host
, p
.prefixlen
, packet
->afi
);
5202 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5205 /* Packet size overflow check. */
5206 psize
= PSIZE(p
.prefixlen
);
5208 /* When packet overflow occur return immediately. */
5209 if (pnt
+ psize
> lim
) {
5212 "%s [Error] Update packet error (prefix length %d overflows packet)",
5213 peer
->host
, p
.prefixlen
);
5214 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5217 /* Defensive coding, double-check the psize fits in a struct
5219 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5222 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5223 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5224 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5227 /* Fetch prefix from NLRI packet. */
5228 memcpy(p
.u
.val
, pnt
, psize
);
5230 /* Check address. */
5231 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5232 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5233 /* From RFC4271 Section 6.3:
5235 * If a prefix in the NLRI field is semantically
5237 * (e.g., an unexpected multicast IP address),
5239 * be logged locally, and the prefix SHOULD be
5244 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5245 peer
->host
, &p
.u
.prefix4
);
5250 /* Check address. */
5251 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5252 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5257 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5259 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5264 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5269 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5271 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
5278 /* Normal process. */
5280 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5281 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5282 NULL
, NULL
, 0, 0, NULL
);
5284 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5285 safi
, ZEBRA_ROUTE_BGP
,
5286 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5289 /* Do not send BGP notification twice when maximum-prefix count
5291 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5292 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5294 /* Address family configuration mismatch. */
5296 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5299 /* Packet length consistency check. */
5303 "%s [Error] Update packet error (prefix length mismatch with total length)",
5305 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5308 return BGP_NLRI_PARSE_OK
;
5311 static struct bgp_static
*bgp_static_new(void)
5313 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5316 static void bgp_static_free(struct bgp_static
*bgp_static
)
5318 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5319 route_map_counter_decrement(bgp_static
->rmap
.map
);
5321 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5322 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5325 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5326 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5328 struct bgp_dest
*dest
;
5329 struct bgp_path_info
*pi
;
5330 struct bgp_path_info
*new;
5331 struct bgp_path_info rmap_path
;
5333 struct attr
*attr_new
;
5334 route_map_result_t ret
;
5335 #ifdef ENABLE_BGP_VNC
5336 int vnc_implicit_withdraw
= 0;
5341 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5343 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5345 attr
.nexthop
= bgp_static
->igpnexthop
;
5346 attr
.med
= bgp_static
->igpmetric
;
5347 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5349 if (bgp_static
->atomic
)
5350 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5352 /* Store label index, if required. */
5353 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5354 attr
.label_index
= bgp_static
->label_index
;
5355 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5358 /* Apply route-map. */
5359 if (bgp_static
->rmap
.name
) {
5360 struct attr attr_tmp
= attr
;
5362 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5363 rmap_path
.peer
= bgp
->peer_self
;
5364 rmap_path
.attr
= &attr_tmp
;
5366 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5368 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5370 bgp
->peer_self
->rmap_type
= 0;
5372 if (ret
== RMAP_DENYMATCH
) {
5373 /* Free uninterned attribute. */
5374 bgp_attr_flush(&attr_tmp
);
5376 /* Unintern original. */
5377 aspath_unintern(&attr
.aspath
);
5378 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5382 if (bgp_in_graceful_shutdown(bgp
))
5383 bgp_attr_add_gshut_community(&attr_tmp
);
5385 attr_new
= bgp_attr_intern(&attr_tmp
);
5388 if (bgp_in_graceful_shutdown(bgp
))
5389 bgp_attr_add_gshut_community(&attr
);
5391 attr_new
= bgp_attr_intern(&attr
);
5394 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5395 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5396 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5400 if (attrhash_cmp(pi
->attr
, attr_new
)
5401 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5402 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5403 bgp_dest_unlock_node(dest
);
5404 bgp_attr_unintern(&attr_new
);
5405 aspath_unintern(&attr
.aspath
);
5408 /* The attribute is changed. */
5409 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5411 /* Rewrite BGP route information. */
5412 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5413 bgp_path_info_restore(dest
, pi
);
5415 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5416 #ifdef ENABLE_BGP_VNC
5417 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5418 && (safi
== SAFI_UNICAST
)) {
5419 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5421 * Implicit withdraw case.
5422 * We have to do this before pi is
5425 ++vnc_implicit_withdraw
;
5426 vnc_import_bgp_del_route(bgp
, p
, pi
);
5427 vnc_import_bgp_exterior_del_route(
5432 bgp_attr_unintern(&pi
->attr
);
5433 pi
->attr
= attr_new
;
5434 pi
->uptime
= bgp_clock();
5435 #ifdef ENABLE_BGP_VNC
5436 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5437 && (safi
== SAFI_UNICAST
)) {
5438 if (vnc_implicit_withdraw
) {
5439 vnc_import_bgp_add_route(bgp
, p
, pi
);
5440 vnc_import_bgp_exterior_add_route(
5446 /* Nexthop reachability check. */
5447 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5448 && (safi
== SAFI_UNICAST
5449 || safi
== SAFI_LABELED_UNICAST
)) {
5451 struct bgp
*bgp_nexthop
= bgp
;
5453 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5454 bgp_nexthop
= pi
->extra
->bgp_orig
;
5456 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5457 afi
, safi
, pi
, NULL
,
5459 bgp_path_info_set_flag(dest
, pi
,
5462 if (BGP_DEBUG(nht
, NHT
)) {
5463 char buf1
[INET6_ADDRSTRLEN
];
5464 inet_ntop(p
->family
,
5468 "%s(%s): Route not in table, not advertising",
5471 bgp_path_info_unset_flag(
5472 dest
, pi
, BGP_PATH_VALID
);
5475 /* Delete the NHT structure if any, if we're
5477 * enabling/disabling import check. We
5478 * deregister the route
5479 * from NHT to avoid overloading NHT and the
5480 * process interaction
5482 bgp_unlink_nexthop(pi
);
5483 bgp_path_info_set_flag(dest
, pi
,
5486 /* Process change. */
5487 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5488 bgp_process(bgp
, dest
, afi
, safi
);
5490 if (SAFI_UNICAST
== safi
5491 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5493 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5494 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5498 bgp_dest_unlock_node(dest
);
5499 aspath_unintern(&attr
.aspath
);
5504 /* Make new BGP info. */
5505 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5507 /* Nexthop reachability check. */
5508 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5509 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5510 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0))
5511 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5513 if (BGP_DEBUG(nht
, NHT
)) {
5514 char buf1
[INET6_ADDRSTRLEN
];
5515 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5518 "%s(%s): Route not in table, not advertising",
5521 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5524 /* Delete the NHT structure if any, if we're toggling between
5525 * enabling/disabling import check. We deregister the route
5526 * from NHT to avoid overloading NHT and the process interaction
5528 bgp_unlink_nexthop(new);
5530 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5533 /* Aggregate address increment. */
5534 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5536 /* Register new BGP information. */
5537 bgp_path_info_add(dest
, new);
5539 /* route_node_get lock */
5540 bgp_dest_unlock_node(dest
);
5542 /* Process change. */
5543 bgp_process(bgp
, dest
, afi
, safi
);
5545 if (SAFI_UNICAST
== safi
5546 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5547 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5548 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5551 /* Unintern original. */
5552 aspath_unintern(&attr
.aspath
);
5555 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5558 struct bgp_dest
*dest
;
5559 struct bgp_path_info
*pi
;
5561 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5563 /* Check selected route and self inserted route. */
5564 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5565 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5566 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5569 /* Withdraw static BGP route from routing table. */
5571 if (SAFI_UNICAST
== safi
5572 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5573 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5574 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5576 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5577 bgp_unlink_nexthop(pi
);
5578 bgp_path_info_delete(dest
, pi
);
5579 bgp_process(bgp
, dest
, afi
, safi
);
5582 /* Unlock bgp_node_lookup. */
5583 bgp_dest_unlock_node(dest
);
5587 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5589 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5590 afi_t afi
, safi_t safi
,
5591 struct prefix_rd
*prd
)
5593 struct bgp_dest
*dest
;
5594 struct bgp_path_info
*pi
;
5596 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5598 /* Check selected route and self inserted route. */
5599 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5600 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5601 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5604 /* Withdraw static BGP route from routing table. */
5606 #ifdef ENABLE_BGP_VNC
5607 rfapiProcessWithdraw(
5608 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5609 1); /* Kill, since it is an administrative change */
5611 if (SAFI_MPLS_VPN
== safi
5612 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5613 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5615 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5616 bgp_path_info_delete(dest
, pi
);
5617 bgp_process(bgp
, dest
, afi
, safi
);
5620 /* Unlock bgp_node_lookup. */
5621 bgp_dest_unlock_node(dest
);
5624 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5625 struct bgp_static
*bgp_static
, afi_t afi
,
5628 struct bgp_dest
*dest
;
5629 struct bgp_path_info
*new;
5630 struct attr
*attr_new
;
5631 struct attr attr
= {0};
5632 struct bgp_path_info
*pi
;
5633 #ifdef ENABLE_BGP_VNC
5634 mpls_label_t label
= 0;
5636 uint32_t num_labels
= 0;
5641 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5643 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5646 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5648 attr
.nexthop
= bgp_static
->igpnexthop
;
5649 attr
.med
= bgp_static
->igpmetric
;
5650 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5652 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5653 || (safi
== SAFI_ENCAP
)) {
5654 if (afi
== AFI_IP
) {
5655 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5656 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5659 if (afi
== AFI_L2VPN
) {
5660 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5662 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5663 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5664 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5665 sizeof(struct in6_addr
));
5666 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5667 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5668 struct bgp_encap_type_vxlan bet
;
5669 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5670 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5671 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5673 if (bgp_static
->router_mac
) {
5674 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5677 /* Apply route-map. */
5678 if (bgp_static
->rmap
.name
) {
5679 struct attr attr_tmp
= attr
;
5680 struct bgp_path_info rmap_path
;
5681 route_map_result_t ret
;
5683 rmap_path
.peer
= bgp
->peer_self
;
5684 rmap_path
.attr
= &attr_tmp
;
5686 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5688 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5690 bgp
->peer_self
->rmap_type
= 0;
5692 if (ret
== RMAP_DENYMATCH
) {
5693 /* Free uninterned attribute. */
5694 bgp_attr_flush(&attr_tmp
);
5696 /* Unintern original. */
5697 aspath_unintern(&attr
.aspath
);
5698 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5703 attr_new
= bgp_attr_intern(&attr_tmp
);
5705 attr_new
= bgp_attr_intern(&attr
);
5708 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5709 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5710 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5714 memset(&add
, 0, sizeof(union gw_addr
));
5715 if (attrhash_cmp(pi
->attr
, attr_new
)
5716 && overlay_index_equal(afi
, pi
, &add
)
5717 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5718 bgp_dest_unlock_node(dest
);
5719 bgp_attr_unintern(&attr_new
);
5720 aspath_unintern(&attr
.aspath
);
5723 /* The attribute is changed. */
5724 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5726 /* Rewrite BGP route information. */
5727 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5728 bgp_path_info_restore(dest
, pi
);
5730 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5731 bgp_attr_unintern(&pi
->attr
);
5732 pi
->attr
= attr_new
;
5733 pi
->uptime
= bgp_clock();
5734 #ifdef ENABLE_BGP_VNC
5736 label
= decode_label(&pi
->extra
->label
[0]);
5739 /* Process change. */
5740 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5741 bgp_process(bgp
, dest
, afi
, safi
);
5743 if (SAFI_MPLS_VPN
== safi
5744 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5745 vpn_leak_to_vrf_update(bgp
, pi
);
5747 #ifdef ENABLE_BGP_VNC
5748 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5749 pi
->attr
, afi
, safi
, pi
->type
,
5750 pi
->sub_type
, &label
);
5752 bgp_dest_unlock_node(dest
);
5753 aspath_unintern(&attr
.aspath
);
5759 /* Make new BGP info. */
5760 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5762 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5763 new->extra
= bgp_path_info_extra_new();
5765 new->extra
->label
[0] = bgp_static
->label
;
5766 new->extra
->num_labels
= num_labels
;
5768 #ifdef ENABLE_BGP_VNC
5769 label
= decode_label(&bgp_static
->label
);
5772 /* Aggregate address increment. */
5773 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5775 /* Register new BGP information. */
5776 bgp_path_info_add(dest
, new);
5777 /* route_node_get lock */
5778 bgp_dest_unlock_node(dest
);
5780 /* Process change. */
5781 bgp_process(bgp
, dest
, afi
, safi
);
5783 if (SAFI_MPLS_VPN
== safi
5784 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5785 vpn_leak_to_vrf_update(bgp
, new);
5787 #ifdef ENABLE_BGP_VNC
5788 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5789 safi
, new->type
, new->sub_type
, &label
);
5792 /* Unintern original. */
5793 aspath_unintern(&attr
.aspath
);
5796 /* Configure static BGP network. When user don't run zebra, static
5797 route should be installed as valid. */
5798 int bgp_static_set(struct bgp
*bgp
, const char *negate
, struct prefix
*pfx
,
5799 afi_t afi
, safi_t safi
, const char *rmap
, int backdoor
,
5800 uint32_t label_index
, char *errmsg
, size_t errmsg_len
)
5803 struct bgp_static
*bgp_static
;
5804 struct bgp_dest
*dest
;
5805 uint8_t need_update
= 0;
5807 prefix_copy(&p
, pfx
);
5812 /* Set BGP static route configuration. */
5813 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5816 snprintf(errmsg
, errmsg_len
,
5817 "Can't find static route specified\n");
5821 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5823 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5824 && (label_index
!= bgp_static
->label_index
)) {
5825 snprintf(errmsg
, errmsg_len
,
5826 "label-index doesn't match static route\n");
5830 if ((rmap
&& bgp_static
->rmap
.name
)
5831 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5832 snprintf(errmsg
, errmsg_len
,
5833 "route-map name doesn't match static route\n");
5837 /* Update BGP RIB. */
5838 if (!bgp_static
->backdoor
)
5839 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5841 /* Clear configuration. */
5842 bgp_static_free(bgp_static
);
5843 bgp_dest_set_bgp_static_info(dest
, NULL
);
5844 bgp_dest_unlock_node(dest
);
5845 bgp_dest_unlock_node(dest
);
5848 /* Set BGP static route configuration. */
5849 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5850 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5852 /* Configuration change. */
5853 /* Label index cannot be changed. */
5854 if (bgp_static
->label_index
!= label_index
) {
5855 snprintf(errmsg
, errmsg_len
,
5856 "cannot change label-index\n");
5860 /* Check previous routes are installed into BGP. */
5861 if (bgp_static
->valid
5862 && bgp_static
->backdoor
!= backdoor
)
5865 bgp_static
->backdoor
= backdoor
;
5868 XFREE(MTYPE_ROUTE_MAP_NAME
,
5869 bgp_static
->rmap
.name
);
5870 route_map_counter_decrement(
5871 bgp_static
->rmap
.map
);
5872 bgp_static
->rmap
.name
=
5873 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5874 bgp_static
->rmap
.map
=
5875 route_map_lookup_by_name(rmap
);
5876 route_map_counter_increment(
5877 bgp_static
->rmap
.map
);
5879 XFREE(MTYPE_ROUTE_MAP_NAME
,
5880 bgp_static
->rmap
.name
);
5881 route_map_counter_decrement(
5882 bgp_static
->rmap
.map
);
5883 bgp_static
->rmap
.map
= NULL
;
5884 bgp_static
->valid
= 0;
5886 bgp_dest_unlock_node(dest
);
5888 /* New configuration. */
5889 bgp_static
= bgp_static_new();
5890 bgp_static
->backdoor
= backdoor
;
5891 bgp_static
->valid
= 0;
5892 bgp_static
->igpmetric
= 0;
5893 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5894 bgp_static
->label_index
= label_index
;
5897 XFREE(MTYPE_ROUTE_MAP_NAME
,
5898 bgp_static
->rmap
.name
);
5899 route_map_counter_decrement(
5900 bgp_static
->rmap
.map
);
5901 bgp_static
->rmap
.name
=
5902 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5903 bgp_static
->rmap
.map
=
5904 route_map_lookup_by_name(rmap
);
5905 route_map_counter_increment(
5906 bgp_static
->rmap
.map
);
5908 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5911 bgp_static
->valid
= 1;
5913 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5915 if (!bgp_static
->backdoor
)
5916 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5922 void bgp_static_add(struct bgp
*bgp
)
5926 struct bgp_dest
*dest
;
5927 struct bgp_dest
*rm
;
5928 struct bgp_table
*table
;
5929 struct bgp_static
*bgp_static
;
5931 FOREACH_AFI_SAFI (afi
, safi
)
5932 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5933 dest
= bgp_route_next(dest
)) {
5934 if (!bgp_dest_has_bgp_path_info_data(dest
))
5937 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5938 || (safi
== SAFI_EVPN
)) {
5939 table
= bgp_dest_get_bgp_table_info(dest
);
5941 for (rm
= bgp_table_top(table
); rm
;
5942 rm
= bgp_route_next(rm
)) {
5944 bgp_dest_get_bgp_static_info(
5946 bgp_static_update_safi(
5947 bgp
, bgp_dest_get_prefix(rm
),
5948 bgp_static
, afi
, safi
);
5952 bgp
, bgp_dest_get_prefix(dest
),
5953 bgp_dest_get_bgp_static_info(dest
), afi
,
5959 /* Called from bgp_delete(). Delete all static routes from the BGP
5961 void bgp_static_delete(struct bgp
*bgp
)
5965 struct bgp_dest
*dest
;
5966 struct bgp_dest
*rm
;
5967 struct bgp_table
*table
;
5968 struct bgp_static
*bgp_static
;
5970 FOREACH_AFI_SAFI (afi
, safi
)
5971 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5972 dest
= bgp_route_next(dest
)) {
5973 if (!bgp_dest_has_bgp_path_info_data(dest
))
5976 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5977 || (safi
== SAFI_EVPN
)) {
5978 table
= bgp_dest_get_bgp_table_info(dest
);
5980 for (rm
= bgp_table_top(table
); rm
;
5981 rm
= bgp_route_next(rm
)) {
5983 bgp_dest_get_bgp_static_info(
5988 bgp_static_withdraw_safi(
5989 bgp
, bgp_dest_get_prefix(rm
),
5991 (struct prefix_rd
*)
5992 bgp_dest_get_prefix(
5994 bgp_static_free(bgp_static
);
5995 bgp_dest_set_bgp_static_info(rm
,
5997 bgp_dest_unlock_node(rm
);
6000 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6001 bgp_static_withdraw(bgp
,
6002 bgp_dest_get_prefix(dest
),
6004 bgp_static_free(bgp_static
);
6005 bgp_dest_set_bgp_static_info(dest
, NULL
);
6006 bgp_dest_unlock_node(dest
);
6011 void bgp_static_redo_import_check(struct bgp
*bgp
)
6015 struct bgp_dest
*dest
;
6016 struct bgp_dest
*rm
;
6017 struct bgp_table
*table
;
6018 struct bgp_static
*bgp_static
;
6020 /* Use this flag to force reprocessing of the route */
6021 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6022 FOREACH_AFI_SAFI (afi
, safi
) {
6023 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6024 dest
= bgp_route_next(dest
)) {
6025 if (!bgp_dest_has_bgp_path_info_data(dest
))
6028 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6029 || (safi
== SAFI_EVPN
)) {
6030 table
= bgp_dest_get_bgp_table_info(dest
);
6032 for (rm
= bgp_table_top(table
); rm
;
6033 rm
= bgp_route_next(rm
)) {
6035 bgp_dest_get_bgp_static_info(
6037 bgp_static_update_safi(
6038 bgp
, bgp_dest_get_prefix(rm
),
6039 bgp_static
, afi
, safi
);
6042 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6043 bgp_static_update(bgp
,
6044 bgp_dest_get_prefix(dest
),
6045 bgp_static
, afi
, safi
);
6049 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6052 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6055 struct bgp_table
*table
;
6056 struct bgp_dest
*dest
;
6057 struct bgp_path_info
*pi
;
6059 /* Do not install the aggregate route if BGP is in the
6060 * process of termination.
6062 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6063 || (bgp
->peer_self
== NULL
))
6066 table
= bgp
->rib
[afi
][safi
];
6067 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6068 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6069 if (pi
->peer
== bgp
->peer_self
6070 && ((pi
->type
== ZEBRA_ROUTE_BGP
6071 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6072 || (pi
->type
!= ZEBRA_ROUTE_BGP
6074 == BGP_ROUTE_REDISTRIBUTE
))) {
6075 bgp_aggregate_decrement(
6076 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6078 bgp_unlink_nexthop(pi
);
6079 bgp_path_info_delete(dest
, pi
);
6080 bgp_process(bgp
, dest
, afi
, safi
);
6087 * Purge all networks and redistributed routes from routing table.
6088 * Invoked upon the instance going down.
6090 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6095 FOREACH_AFI_SAFI (afi
, safi
)
6096 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6101 * Currently this is used to set static routes for VPN and ENCAP.
6102 * I think it can probably be factored with bgp_static_set.
6104 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6105 const char *ip_str
, const char *rd_str
,
6106 const char *label_str
, const char *rmap_str
,
6107 int evpn_type
, const char *esi
, const char *gwip
,
6108 const char *ethtag
, const char *routermac
)
6110 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6113 struct prefix_rd prd
;
6114 struct bgp_dest
*pdest
;
6115 struct bgp_dest
*dest
;
6116 struct bgp_table
*table
;
6117 struct bgp_static
*bgp_static
;
6118 mpls_label_t label
= MPLS_INVALID_LABEL
;
6119 struct prefix gw_ip
;
6121 /* validate ip prefix */
6122 ret
= str2prefix(ip_str
, &p
);
6124 vty_out(vty
, "%% Malformed prefix\n");
6125 return CMD_WARNING_CONFIG_FAILED
;
6128 if ((afi
== AFI_L2VPN
)
6129 && (bgp_build_evpn_prefix(evpn_type
,
6130 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6131 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6132 return CMD_WARNING_CONFIG_FAILED
;
6135 ret
= str2prefix_rd(rd_str
, &prd
);
6137 vty_out(vty
, "%% Malformed rd\n");
6138 return CMD_WARNING_CONFIG_FAILED
;
6142 unsigned long label_val
;
6143 label_val
= strtoul(label_str
, NULL
, 10);
6144 encode_label(label_val
, &label
);
6147 if (safi
== SAFI_EVPN
) {
6148 if (esi
&& str2esi(esi
, NULL
) == 0) {
6149 vty_out(vty
, "%% Malformed ESI\n");
6150 return CMD_WARNING_CONFIG_FAILED
;
6152 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6153 vty_out(vty
, "%% Malformed Router MAC\n");
6154 return CMD_WARNING_CONFIG_FAILED
;
6157 memset(&gw_ip
, 0, sizeof(struct prefix
));
6158 ret
= str2prefix(gwip
, &gw_ip
);
6160 vty_out(vty
, "%% Malformed GatewayIp\n");
6161 return CMD_WARNING_CONFIG_FAILED
;
6163 if ((gw_ip
.family
== AF_INET
6164 && is_evpn_prefix_ipaddr_v6(
6165 (struct prefix_evpn
*)&p
))
6166 || (gw_ip
.family
== AF_INET6
6167 && is_evpn_prefix_ipaddr_v4(
6168 (struct prefix_evpn
*)&p
))) {
6170 "%% GatewayIp family differs with IP prefix\n");
6171 return CMD_WARNING_CONFIG_FAILED
;
6175 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6176 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6177 bgp_dest_set_bgp_table_info(pdest
,
6178 bgp_table_init(bgp
, afi
, safi
));
6179 table
= bgp_dest_get_bgp_table_info(pdest
);
6181 dest
= bgp_node_get(table
, &p
);
6183 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6184 vty_out(vty
, "%% Same network configuration exists\n");
6185 bgp_dest_unlock_node(dest
);
6187 /* New configuration. */
6188 bgp_static
= bgp_static_new();
6189 bgp_static
->backdoor
= 0;
6190 bgp_static
->valid
= 0;
6191 bgp_static
->igpmetric
= 0;
6192 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6193 bgp_static
->label
= label
;
6194 bgp_static
->prd
= prd
;
6197 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6198 route_map_counter_decrement(bgp_static
->rmap
.map
);
6199 bgp_static
->rmap
.name
=
6200 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6201 bgp_static
->rmap
.map
=
6202 route_map_lookup_by_name(rmap_str
);
6203 route_map_counter_increment(bgp_static
->rmap
.map
);
6206 if (safi
== SAFI_EVPN
) {
6208 bgp_static
->eth_s_id
=
6211 str2esi(esi
, bgp_static
->eth_s_id
);
6214 bgp_static
->router_mac
=
6215 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6216 (void)prefix_str2mac(routermac
,
6217 bgp_static
->router_mac
);
6220 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6222 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6224 bgp_static
->valid
= 1;
6225 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6231 /* Configure static BGP network. */
6232 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6233 const char *ip_str
, const char *rd_str
,
6234 const char *label_str
, int evpn_type
, const char *esi
,
6235 const char *gwip
, const char *ethtag
)
6237 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6240 struct prefix_rd prd
;
6241 struct bgp_dest
*pdest
;
6242 struct bgp_dest
*dest
;
6243 struct bgp_table
*table
;
6244 struct bgp_static
*bgp_static
;
6245 mpls_label_t label
= MPLS_INVALID_LABEL
;
6247 /* Convert IP prefix string to struct prefix. */
6248 ret
= str2prefix(ip_str
, &p
);
6250 vty_out(vty
, "%% Malformed prefix\n");
6251 return CMD_WARNING_CONFIG_FAILED
;
6254 if ((afi
== AFI_L2VPN
)
6255 && (bgp_build_evpn_prefix(evpn_type
,
6256 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6257 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6258 return CMD_WARNING_CONFIG_FAILED
;
6260 ret
= str2prefix_rd(rd_str
, &prd
);
6262 vty_out(vty
, "%% Malformed rd\n");
6263 return CMD_WARNING_CONFIG_FAILED
;
6267 unsigned long label_val
;
6268 label_val
= strtoul(label_str
, NULL
, 10);
6269 encode_label(label_val
, &label
);
6272 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6273 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6274 bgp_dest_set_bgp_table_info(pdest
,
6275 bgp_table_init(bgp
, afi
, safi
));
6277 bgp_dest_unlock_node(pdest
);
6278 table
= bgp_dest_get_bgp_table_info(pdest
);
6280 dest
= bgp_node_lookup(table
, &p
);
6283 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6285 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6286 bgp_static_free(bgp_static
);
6287 bgp_dest_set_bgp_static_info(dest
, NULL
);
6288 bgp_dest_unlock_node(dest
);
6289 bgp_dest_unlock_node(dest
);
6291 vty_out(vty
, "%% Can't find the route\n");
6296 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6297 const char *rmap_name
)
6299 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6300 struct bgp_rmap
*rmap
;
6302 rmap
= &bgp
->table_map
[afi
][safi
];
6304 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6305 route_map_counter_decrement(rmap
->map
);
6306 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6307 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6308 route_map_counter_increment(rmap
->map
);
6310 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6311 route_map_counter_decrement(rmap
->map
);
6315 if (bgp_fibupd_safi(safi
))
6316 bgp_zebra_announce_table(bgp
, afi
, safi
);
6321 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6322 const char *rmap_name
)
6324 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6325 struct bgp_rmap
*rmap
;
6327 rmap
= &bgp
->table_map
[afi
][safi
];
6328 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6329 route_map_counter_decrement(rmap
->map
);
6332 if (bgp_fibupd_safi(safi
))
6333 bgp_zebra_announce_table(bgp
, afi
, safi
);
6338 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6341 if (bgp
->table_map
[afi
][safi
].name
) {
6342 vty_out(vty
, " table-map %s\n",
6343 bgp
->table_map
[afi
][safi
].name
);
6347 DEFUN (bgp_table_map
,
6350 "BGP table to RIB route download filter\n"
6351 "Name of the route map\n")
6354 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6355 argv
[idx_word
]->arg
);
6357 DEFUN (no_bgp_table_map
,
6358 no_bgp_table_map_cmd
,
6359 "no table-map WORD",
6361 "BGP table to RIB route download filter\n"
6362 "Name of the route map\n")
6365 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6366 argv
[idx_word
]->arg
);
6369 DEFPY_YANG (bgp_network
, bgp_network_cmd
,
6371 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6372 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6373 backdoor$backdoor}]",
6375 "Specify a network to announce via BGP\n"
6380 "Route-map to modify the attributes\n"
6381 "Name of the route map\n"
6382 "Label index to associate with the prefix\n"
6383 "Label index value\n"
6384 "Specify a BGP backdoor route\n")
6386 char addr_prefix_str
[PREFIX_STRLEN
];
6387 char base_xpath
[XPATH_MAXLEN
];
6394 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6396 sizeof(addr_prefix_str
));
6398 vty_out(vty
, "%% Inconsistent address and mask\n");
6399 return CMD_WARNING_CONFIG_FAILED
;
6403 afi
= bgp_node_afi(vty
);
6404 safi
= bgp_node_safi(vty
);
6407 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6409 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6412 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6413 NB_OP_CREATE
, map_name
);
6415 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6416 NB_OP_DESTROY
, NULL
);
6418 if (label_index_str
)
6419 nb_cli_enqueue_change(vty
, "./label-index",
6420 NB_OP_MODIFY
, label_index_str
);
6422 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6423 backdoor
? "true" : "false");
6427 base_xpath
, sizeof(base_xpath
),
6428 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6429 yang_afi_safi_value2identity(afi
, safi
),
6430 bgp_afi_safi_get_container_str(afi
, safi
),
6431 address_str
? addr_prefix_str
: prefix_str
);
6433 return nb_cli_apply_changes(vty
, base_xpath
);
6436 DEFPY_YANG (ipv6_bgp_network
,
6437 ipv6_bgp_network_cmd
,
6438 "[no] network X:X::X:X/M$prefix \
6439 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6441 "Specify a network to announce via BGP\n"
6443 "Route-map to modify the attributes\n"
6444 "Name of the route map\n"
6445 "Label index to associate with the prefix\n"
6446 "Label index value\n")
6448 char base_xpath
[XPATH_MAXLEN
];
6452 afi
= bgp_node_afi(vty
);
6453 safi
= bgp_node_safi(vty
);
6456 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6458 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6461 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6462 NB_OP_MODIFY
, map_name
);
6464 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6465 NB_OP_DESTROY
, NULL
);
6467 if (label_index_str
)
6468 nb_cli_enqueue_change(vty
, "./label-index",
6469 NB_OP_MODIFY
, label_index_str
);
6473 base_xpath
, sizeof(base_xpath
),
6474 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6475 yang_afi_safi_value2identity(afi
, safi
),
6476 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6478 return nb_cli_apply_changes(vty
, base_xpath
);
6481 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6482 struct lyd_node
*dnode
,
6485 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6487 if (yang_dnode_exists(dnode
, "./label-index"))
6488 vty_out(vty
, " label-index %s",
6489 yang_dnode_get_string(dnode
, "./label-index"));
6491 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6492 vty_out(vty
, " route-map %s",
6493 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6495 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6496 vty_out(vty
, " backdoor");
6501 static struct bgp_aggregate
*bgp_aggregate_new(void)
6503 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6506 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6508 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6509 route_map_counter_decrement(aggregate
->suppress_map
);
6510 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6511 route_map_counter_decrement(aggregate
->rmap
.map
);
6512 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6516 * Helper function to avoid repeated code: prepare variables for a
6517 * `route_map_apply` call.
6519 * \returns `true` on route map match, otherwise `false`.
6521 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6522 struct bgp_aggregate
*aggregate
,
6523 struct bgp_path_info
*pi
)
6525 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6526 route_map_result_t rmr
= RMAP_DENYMATCH
;
6527 struct bgp_path_info rmap_path
= {};
6528 struct attr attr
= {};
6530 /* No route map entries created, just don't match. */
6531 if (aggregate
->suppress_map
== NULL
)
6534 /* Call route map matching and return result. */
6535 attr
.aspath
= aspath_empty();
6536 rmap_path
.peer
= bgp
->peer_self
;
6537 rmap_path
.attr
= &attr
;
6539 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6540 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6541 bgp
->peer_self
->rmap_type
= 0;
6543 bgp_attr_flush(&attr
);
6545 return rmr
== RMAP_PERMITMATCH
;
6548 /** Test whether the aggregation has suppressed this path or not. */
6549 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6550 struct bgp_path_info
*pi
)
6552 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6555 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6559 * Suppress this path and keep the reference.
6561 * \returns `true` if needs processing otherwise `false`.
6563 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6564 struct bgp_path_info
*pi
)
6566 struct bgp_path_info_extra
*pie
;
6568 /* Path is already suppressed by this aggregation. */
6569 if (aggr_suppress_exists(aggregate
, pi
))
6572 pie
= bgp_path_info_extra_get(pi
);
6574 /* This is the first suppression, allocate memory and list it. */
6575 if (pie
->aggr_suppressors
== NULL
)
6576 pie
->aggr_suppressors
= list_new();
6578 listnode_add(pie
->aggr_suppressors
, aggregate
);
6580 /* Only mark for processing if suppressed. */
6581 if (listcount(pie
->aggr_suppressors
) == 1) {
6582 if (BGP_DEBUG(update
, UPDATE_OUT
))
6583 zlog_debug("aggregate-address suppressing: %pFX",
6584 bgp_dest_get_prefix(pi
->net
));
6586 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6594 * Unsuppress this path and remove the reference.
6596 * \returns `true` if needs processing otherwise `false`.
6598 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6599 struct bgp_path_info
*pi
)
6601 /* Path wasn't suppressed. */
6602 if (!aggr_suppress_exists(aggregate
, pi
))
6605 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6607 /* Unsuppress and free extra memory if last item. */
6608 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6609 if (BGP_DEBUG(update
, UPDATE_OUT
))
6610 zlog_debug("aggregate-address unsuppressing: %pFX",
6611 bgp_dest_get_prefix(pi
->net
));
6613 list_delete(&pi
->extra
->aggr_suppressors
);
6614 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6621 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6622 struct aspath
*aspath
,
6623 struct community
*comm
,
6624 struct ecommunity
*ecomm
,
6625 struct lcommunity
*lcomm
)
6627 static struct aspath
*ae
= NULL
;
6630 ae
= aspath_empty();
6635 if (origin
!= pi
->attr
->origin
)
6638 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6641 if (!community_cmp(pi
->attr
->community
, comm
))
6644 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6647 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6650 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6656 static void bgp_aggregate_install(
6657 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6658 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6659 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6660 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6662 struct bgp_dest
*dest
;
6663 struct bgp_table
*table
;
6664 struct bgp_path_info
*pi
, *orig
, *new;
6667 table
= bgp
->rib
[afi
][safi
];
6669 dest
= bgp_node_get(table
, p
);
6671 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6672 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6673 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6677 * If we have paths with different MEDs, then don't install
6678 * (or uninstall) the aggregate route.
6680 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6681 goto uninstall_aggregate_route
;
6683 if (aggregate
->count
> 0) {
6685 * If the aggregate information has not changed
6686 * no need to re-install it again.
6688 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6689 ecommunity
, lcommunity
)) {
6690 bgp_dest_unlock_node(dest
);
6693 aspath_free(aspath
);
6695 community_free(&community
);
6697 ecommunity_free(&ecommunity
);
6699 lcommunity_free(&lcommunity
);
6705 * Mark the old as unusable
6708 bgp_path_info_delete(dest
, pi
);
6710 attr
= bgp_attr_aggregate_intern(
6711 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6712 aggregate
, atomic_aggregate
, p
);
6715 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6716 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6717 zlog_debug("%s: %pFX null attribute", __func__
,
6722 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6723 bgp
->peer_self
, attr
, dest
);
6725 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6727 bgp_path_info_add(dest
, new);
6728 bgp_process(bgp
, dest
, afi
, safi
);
6730 uninstall_aggregate_route
:
6731 for (pi
= orig
; pi
; pi
= pi
->next
)
6732 if (pi
->peer
== bgp
->peer_self
6733 && pi
->type
== ZEBRA_ROUTE_BGP
6734 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6737 /* Withdraw static BGP route from routing table. */
6739 bgp_path_info_delete(dest
, pi
);
6740 bgp_process(bgp
, dest
, afi
, safi
);
6744 bgp_dest_unlock_node(dest
);
6748 * Check if the current path has different MED than other known paths.
6750 * \returns `true` if the MED matched the others else `false`.
6752 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6753 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6755 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6757 /* This is the first route being analyzed. */
6758 if (!aggregate
->med_initialized
) {
6759 aggregate
->med_initialized
= true;
6760 aggregate
->med_mismatched
= false;
6761 aggregate
->med_matched_value
= cur_med
;
6763 /* Check if routes with different MED showed up. */
6764 if (cur_med
!= aggregate
->med_matched_value
)
6765 aggregate
->med_mismatched
= true;
6768 return !aggregate
->med_mismatched
;
6772 * Initializes and tests all routes in the aggregate address path for MED
6775 * \returns `true` if all MEDs are the same otherwise `false`.
6777 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6778 struct bgp
*bgp
, const struct prefix
*p
,
6779 afi_t afi
, safi_t safi
)
6781 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6782 const struct prefix
*dest_p
;
6783 struct bgp_dest
*dest
, *top
;
6784 struct bgp_path_info
*pi
;
6785 bool med_matched
= true;
6787 aggregate
->med_initialized
= false;
6789 top
= bgp_node_get(table
, p
);
6790 for (dest
= bgp_node_get(table
, p
); dest
;
6791 dest
= bgp_route_next_until(dest
, top
)) {
6792 dest_p
= bgp_dest_get_prefix(dest
);
6793 if (dest_p
->prefixlen
<= p
->prefixlen
)
6796 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6797 if (BGP_PATH_HOLDDOWN(pi
))
6799 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6801 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6802 med_matched
= false;
6809 bgp_dest_unlock_node(top
);
6815 * Toggles the route suppression status for this aggregate address
6818 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6819 struct bgp
*bgp
, const struct prefix
*p
,
6820 afi_t afi
, safi_t safi
, bool suppress
)
6822 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6823 const struct prefix
*dest_p
;
6824 struct bgp_dest
*dest
, *top
;
6825 struct bgp_path_info
*pi
;
6826 bool toggle_suppression
;
6828 /* We've found a different MED we must revert any suppressed routes. */
6829 top
= bgp_node_get(table
, p
);
6830 for (dest
= bgp_node_get(table
, p
); dest
;
6831 dest
= bgp_route_next_until(dest
, top
)) {
6832 dest_p
= bgp_dest_get_prefix(dest
);
6833 if (dest_p
->prefixlen
<= p
->prefixlen
)
6836 toggle_suppression
= false;
6837 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6838 if (BGP_PATH_HOLDDOWN(pi
))
6840 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6843 /* We are toggling suppression back. */
6845 /* Suppress route if not suppressed already. */
6846 if (aggr_suppress_path(aggregate
, pi
))
6847 toggle_suppression
= true;
6851 /* Install route if there is no more suppression. */
6852 if (aggr_unsuppress_path(aggregate
, pi
))
6853 toggle_suppression
= true;
6856 if (toggle_suppression
)
6857 bgp_process(bgp
, dest
, afi
, safi
);
6859 bgp_dest_unlock_node(top
);
6863 * Aggregate address MED matching incremental test: this function is called
6864 * when the initial aggregation occurred and we are only testing a single
6867 * In addition to testing and setting the MED validity it also installs back
6868 * suppressed routes (if summary is configured).
6870 * Must not be called in `bgp_aggregate_route`.
6872 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6873 struct bgp
*bgp
, const struct prefix
*p
,
6874 afi_t afi
, safi_t safi
,
6875 struct bgp_path_info
*pi
, bool is_adding
)
6877 /* MED matching disabled. */
6878 if (!aggregate
->match_med
)
6881 /* Aggregation with different MED, nothing to do. */
6882 if (aggregate
->med_mismatched
)
6886 * Test the current entry:
6888 * is_adding == true: if the new entry doesn't match then we must
6889 * install all suppressed routes.
6891 * is_adding == false: if the entry being removed was the last
6892 * unmatching entry then we can suppress all routes.
6895 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6896 && aggregate
->summary_only
)
6897 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6900 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6902 /* No mismatches, just quit. */
6903 if (!aggregate
->med_mismatched
)
6906 /* Route summarization is disabled. */
6907 if (!aggregate
->summary_only
)
6910 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6913 /* Update an aggregate as routes are added/removed from the BGP table */
6914 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6915 safi_t safi
, struct bgp_aggregate
*aggregate
)
6917 struct bgp_table
*table
;
6918 struct bgp_dest
*top
;
6919 struct bgp_dest
*dest
;
6921 struct aspath
*aspath
= NULL
;
6922 struct community
*community
= NULL
;
6923 struct ecommunity
*ecommunity
= NULL
;
6924 struct lcommunity
*lcommunity
= NULL
;
6925 struct bgp_path_info
*pi
;
6926 unsigned long match
= 0;
6927 uint8_t atomic_aggregate
= 0;
6929 /* If the bgp instance is being deleted or self peer is deleted
6930 * then do not create aggregate route
6932 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6933 || (bgp
->peer_self
== NULL
))
6936 /* Initialize and test routes for MED difference. */
6937 if (aggregate
->match_med
)
6938 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6941 * Reset aggregate count: we might've been called from route map
6942 * update so in that case we must retest all more specific routes.
6944 * \see `bgp_route_map_process_update`.
6946 aggregate
->count
= 0;
6947 aggregate
->incomplete_origin_count
= 0;
6948 aggregate
->incomplete_origin_count
= 0;
6949 aggregate
->egp_origin_count
= 0;
6951 /* ORIGIN attribute: If at least one route among routes that are
6952 aggregated has ORIGIN with the value INCOMPLETE, then the
6953 aggregated route must have the ORIGIN attribute with the value
6954 INCOMPLETE. Otherwise, if at least one route among routes that
6955 are aggregated has ORIGIN with the value EGP, then the aggregated
6956 route must have the origin attribute with the value EGP. In all
6957 other case the value of the ORIGIN attribute of the aggregated
6958 route is INTERNAL. */
6959 origin
= BGP_ORIGIN_IGP
;
6961 table
= bgp
->rib
[afi
][safi
];
6963 top
= bgp_node_get(table
, p
);
6964 for (dest
= bgp_node_get(table
, p
); dest
;
6965 dest
= bgp_route_next_until(dest
, top
)) {
6966 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6968 if (dest_p
->prefixlen
<= p
->prefixlen
)
6971 /* If suppress fib is enabled and route not installed
6972 * in FIB, skip the route
6974 if (!bgp_check_advertise(bgp
, dest
))
6979 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6980 if (BGP_PATH_HOLDDOWN(pi
))
6984 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6985 atomic_aggregate
= 1;
6987 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6991 * summary-only aggregate route suppress
6992 * aggregated route announcements.
6995 * Don't create summaries if MED didn't match
6996 * otherwise neither the specific routes and the
6997 * aggregation will be announced.
6999 if (aggregate
->summary_only
7000 && AGGREGATE_MED_VALID(aggregate
)) {
7001 if (aggr_suppress_path(aggregate
, pi
))
7006 * Suppress more specific routes that match the route
7010 * Don't suppress routes if MED matching is enabled and
7011 * it mismatched otherwise we might end up with no
7012 * routes for this path.
7014 if (aggregate
->suppress_map_name
7015 && AGGREGATE_MED_VALID(aggregate
)
7016 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7017 if (aggr_suppress_path(aggregate
, pi
))
7024 * If at least one route among routes that are
7025 * aggregated has ORIGIN with the value INCOMPLETE,
7026 * then the aggregated route MUST have the ORIGIN
7027 * attribute with the value INCOMPLETE. Otherwise, if
7028 * at least one route among routes that are aggregated
7029 * has ORIGIN with the value EGP, then the aggregated
7030 * route MUST have the ORIGIN attribute with the value
7033 switch (pi
->attr
->origin
) {
7034 case BGP_ORIGIN_INCOMPLETE
:
7035 aggregate
->incomplete_origin_count
++;
7037 case BGP_ORIGIN_EGP
:
7038 aggregate
->egp_origin_count
++;
7046 if (!aggregate
->as_set
)
7050 * as-set aggregate route generate origin, as path,
7051 * and community aggregation.
7053 /* Compute aggregate route's as-path.
7055 bgp_compute_aggregate_aspath_hash(aggregate
,
7058 /* Compute aggregate route's community.
7060 if (pi
->attr
->community
)
7061 bgp_compute_aggregate_community_hash(
7063 pi
->attr
->community
);
7065 /* Compute aggregate route's extended community.
7067 if (pi
->attr
->ecommunity
)
7068 bgp_compute_aggregate_ecommunity_hash(
7070 pi
->attr
->ecommunity
);
7072 /* Compute aggregate route's large community.
7074 if (pi
->attr
->lcommunity
)
7075 bgp_compute_aggregate_lcommunity_hash(
7077 pi
->attr
->lcommunity
);
7080 bgp_process(bgp
, dest
, afi
, safi
);
7082 if (aggregate
->as_set
) {
7083 bgp_compute_aggregate_aspath_val(aggregate
);
7084 bgp_compute_aggregate_community_val(aggregate
);
7085 bgp_compute_aggregate_ecommunity_val(aggregate
);
7086 bgp_compute_aggregate_lcommunity_val(aggregate
);
7090 bgp_dest_unlock_node(top
);
7093 if (aggregate
->incomplete_origin_count
> 0)
7094 origin
= BGP_ORIGIN_INCOMPLETE
;
7095 else if (aggregate
->egp_origin_count
> 0)
7096 origin
= BGP_ORIGIN_EGP
;
7098 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7099 origin
= aggregate
->origin
;
7101 if (aggregate
->as_set
) {
7102 if (aggregate
->aspath
)
7103 /* Retrieve aggregate route's as-path.
7105 aspath
= aspath_dup(aggregate
->aspath
);
7107 if (aggregate
->community
)
7108 /* Retrieve aggregate route's community.
7110 community
= community_dup(aggregate
->community
);
7112 if (aggregate
->ecommunity
)
7113 /* Retrieve aggregate route's ecommunity.
7115 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7117 if (aggregate
->lcommunity
)
7118 /* Retrieve aggregate route's lcommunity.
7120 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7123 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7124 ecommunity
, lcommunity
, atomic_aggregate
,
7128 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7129 safi_t safi
, struct bgp_aggregate
*aggregate
)
7131 struct bgp_table
*table
;
7132 struct bgp_dest
*top
;
7133 struct bgp_dest
*dest
;
7134 struct bgp_path_info
*pi
;
7135 unsigned long match
;
7137 table
= bgp
->rib
[afi
][safi
];
7139 /* If routes exists below this node, generate aggregate routes. */
7140 top
= bgp_node_get(table
, p
);
7141 for (dest
= bgp_node_get(table
, p
); dest
;
7142 dest
= bgp_route_next_until(dest
, top
)) {
7143 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7145 if (dest_p
->prefixlen
<= p
->prefixlen
)
7149 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7150 if (BGP_PATH_HOLDDOWN(pi
))
7153 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7156 if (aggregate
->summary_only
&& pi
->extra
7157 && AGGREGATE_MED_VALID(aggregate
)) {
7158 if (aggr_unsuppress_path(aggregate
, pi
))
7162 if (aggregate
->suppress_map_name
7163 && AGGREGATE_MED_VALID(aggregate
)
7164 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7165 if (aggr_unsuppress_path(aggregate
, pi
))
7171 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7172 aggregate
->incomplete_origin_count
--;
7173 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7174 aggregate
->egp_origin_count
--;
7176 if (aggregate
->as_set
) {
7177 /* Remove as-path from aggregate.
7179 bgp_remove_aspath_from_aggregate_hash(
7183 if (pi
->attr
->community
)
7184 /* Remove community from aggregate.
7186 bgp_remove_comm_from_aggregate_hash(
7188 pi
->attr
->community
);
7190 if (pi
->attr
->ecommunity
)
7191 /* Remove ecommunity from aggregate.
7193 bgp_remove_ecomm_from_aggregate_hash(
7195 pi
->attr
->ecommunity
);
7197 if (pi
->attr
->lcommunity
)
7198 /* Remove lcommunity from aggregate.
7200 bgp_remove_lcomm_from_aggregate_hash(
7202 pi
->attr
->lcommunity
);
7206 /* If this node was suppressed, process the change. */
7208 bgp_process(bgp
, dest
, afi
, safi
);
7210 if (aggregate
->as_set
) {
7211 aspath_free(aggregate
->aspath
);
7212 aggregate
->aspath
= NULL
;
7213 if (aggregate
->community
)
7214 community_free(&aggregate
->community
);
7215 if (aggregate
->ecommunity
)
7216 ecommunity_free(&aggregate
->ecommunity
);
7217 if (aggregate
->lcommunity
)
7218 lcommunity_free(&aggregate
->lcommunity
);
7221 bgp_dest_unlock_node(top
);
7224 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7225 const struct prefix
*aggr_p
,
7226 struct bgp_path_info
*pinew
, afi_t afi
,
7228 struct bgp_aggregate
*aggregate
)
7231 struct aspath
*aspath
= NULL
;
7232 uint8_t atomic_aggregate
= 0;
7233 struct community
*community
= NULL
;
7234 struct ecommunity
*ecommunity
= NULL
;
7235 struct lcommunity
*lcommunity
= NULL
;
7237 /* If the bgp instance is being deleted or self peer is deleted
7238 * then do not create aggregate route
7240 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7241 || (bgp
->peer_self
== NULL
))
7244 /* ORIGIN attribute: If at least one route among routes that are
7245 * aggregated has ORIGIN with the value INCOMPLETE, then the
7246 * aggregated route must have the ORIGIN attribute with the value
7247 * INCOMPLETE. Otherwise, if at least one route among routes that
7248 * are aggregated has ORIGIN with the value EGP, then the aggregated
7249 * route must have the origin attribute with the value EGP. In all
7250 * other case the value of the ORIGIN attribute of the aggregated
7251 * route is INTERNAL.
7253 origin
= BGP_ORIGIN_IGP
;
7258 * This must be called before `summary` check to avoid
7259 * "suppressing" twice.
7261 if (aggregate
->match_med
)
7262 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7265 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7266 aggr_suppress_path(aggregate
, pinew
);
7268 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7269 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7270 aggr_suppress_path(aggregate
, pinew
);
7272 switch (pinew
->attr
->origin
) {
7273 case BGP_ORIGIN_INCOMPLETE
:
7274 aggregate
->incomplete_origin_count
++;
7276 case BGP_ORIGIN_EGP
:
7277 aggregate
->egp_origin_count
++;
7285 if (aggregate
->incomplete_origin_count
> 0)
7286 origin
= BGP_ORIGIN_INCOMPLETE
;
7287 else if (aggregate
->egp_origin_count
> 0)
7288 origin
= BGP_ORIGIN_EGP
;
7290 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7291 origin
= aggregate
->origin
;
7293 if (aggregate
->as_set
) {
7294 /* Compute aggregate route's as-path.
7296 bgp_compute_aggregate_aspath(aggregate
,
7297 pinew
->attr
->aspath
);
7299 /* Compute aggregate route's community.
7301 if (pinew
->attr
->community
)
7302 bgp_compute_aggregate_community(
7304 pinew
->attr
->community
);
7306 /* Compute aggregate route's extended community.
7308 if (pinew
->attr
->ecommunity
)
7309 bgp_compute_aggregate_ecommunity(
7311 pinew
->attr
->ecommunity
);
7313 /* Compute aggregate route's large community.
7315 if (pinew
->attr
->lcommunity
)
7316 bgp_compute_aggregate_lcommunity(
7318 pinew
->attr
->lcommunity
);
7320 /* Retrieve aggregate route's as-path.
7322 if (aggregate
->aspath
)
7323 aspath
= aspath_dup(aggregate
->aspath
);
7325 /* Retrieve aggregate route's community.
7327 if (aggregate
->community
)
7328 community
= community_dup(aggregate
->community
);
7330 /* Retrieve aggregate route's ecommunity.
7332 if (aggregate
->ecommunity
)
7333 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7335 /* Retrieve aggregate route's lcommunity.
7337 if (aggregate
->lcommunity
)
7338 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7341 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7342 aspath
, community
, ecommunity
,
7343 lcommunity
, atomic_aggregate
, aggregate
);
7346 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7348 struct bgp_path_info
*pi
,
7349 struct bgp_aggregate
*aggregate
,
7350 const struct prefix
*aggr_p
)
7353 struct aspath
*aspath
= NULL
;
7354 uint8_t atomic_aggregate
= 0;
7355 struct community
*community
= NULL
;
7356 struct ecommunity
*ecommunity
= NULL
;
7357 struct lcommunity
*lcommunity
= NULL
;
7358 unsigned long match
= 0;
7360 /* If the bgp instance is being deleted or self peer is deleted
7361 * then do not create aggregate route
7363 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7364 || (bgp
->peer_self
== NULL
))
7367 if (BGP_PATH_HOLDDOWN(pi
))
7370 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7373 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7374 if (aggr_unsuppress_path(aggregate
, pi
))
7377 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7378 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7379 if (aggr_unsuppress_path(aggregate
, pi
))
7383 * This must be called after `summary`, `suppress-map` check to avoid
7384 * "unsuppressing" twice.
7386 if (aggregate
->match_med
)
7387 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7390 if (aggregate
->count
> 0)
7393 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7394 aggregate
->incomplete_origin_count
--;
7395 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7396 aggregate
->egp_origin_count
--;
7398 if (aggregate
->as_set
) {
7399 /* Remove as-path from aggregate.
7401 bgp_remove_aspath_from_aggregate(aggregate
,
7404 if (pi
->attr
->community
)
7405 /* Remove community from aggregate.
7407 bgp_remove_community_from_aggregate(
7409 pi
->attr
->community
);
7411 if (pi
->attr
->ecommunity
)
7412 /* Remove ecommunity from aggregate.
7414 bgp_remove_ecommunity_from_aggregate(
7416 pi
->attr
->ecommunity
);
7418 if (pi
->attr
->lcommunity
)
7419 /* Remove lcommunity from aggregate.
7421 bgp_remove_lcommunity_from_aggregate(
7423 pi
->attr
->lcommunity
);
7426 /* If this node was suppressed, process the change. */
7428 bgp_process(bgp
, pi
->net
, afi
, safi
);
7430 origin
= BGP_ORIGIN_IGP
;
7431 if (aggregate
->incomplete_origin_count
> 0)
7432 origin
= BGP_ORIGIN_INCOMPLETE
;
7433 else if (aggregate
->egp_origin_count
> 0)
7434 origin
= BGP_ORIGIN_EGP
;
7436 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7437 origin
= aggregate
->origin
;
7439 if (aggregate
->as_set
) {
7440 /* Retrieve aggregate route's as-path.
7442 if (aggregate
->aspath
)
7443 aspath
= aspath_dup(aggregate
->aspath
);
7445 /* Retrieve aggregate route's community.
7447 if (aggregate
->community
)
7448 community
= community_dup(aggregate
->community
);
7450 /* Retrieve aggregate route's ecommunity.
7452 if (aggregate
->ecommunity
)
7453 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7455 /* Retrieve aggregate route's lcommunity.
7457 if (aggregate
->lcommunity
)
7458 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7461 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7462 aspath
, community
, ecommunity
,
7463 lcommunity
, atomic_aggregate
, aggregate
);
7466 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7467 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7469 struct bgp_dest
*child
;
7470 struct bgp_dest
*dest
;
7471 struct bgp_aggregate
*aggregate
;
7472 struct bgp_table
*table
;
7474 table
= bgp
->aggregate
[afi
][safi
];
7476 /* No aggregates configured. */
7477 if (bgp_table_top_nolock(table
) == NULL
)
7480 if (p
->prefixlen
== 0)
7483 if (BGP_PATH_HOLDDOWN(pi
))
7486 /* If suppress fib is enabled and route not installed
7487 * in FIB, do not update the aggregate route
7489 if (!bgp_check_advertise(bgp
, pi
->net
))
7492 child
= bgp_node_get(table
, p
);
7494 /* Aggregate address configuration check. */
7495 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7496 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7498 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7499 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7500 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7504 bgp_dest_unlock_node(child
);
7507 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7508 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7510 struct bgp_dest
*child
;
7511 struct bgp_dest
*dest
;
7512 struct bgp_aggregate
*aggregate
;
7513 struct bgp_table
*table
;
7515 table
= bgp
->aggregate
[afi
][safi
];
7517 /* No aggregates configured. */
7518 if (bgp_table_top_nolock(table
) == NULL
)
7521 if (p
->prefixlen
== 0)
7524 child
= bgp_node_get(table
, p
);
7526 /* Aggregate address configuration check. */
7527 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7528 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7530 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7531 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7532 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7536 bgp_dest_unlock_node(child
);
7539 /* Aggregate route attribute. */
7540 #define AGGREGATE_SUMMARY_ONLY 1
7541 #define AGGREGATE_AS_SET 1
7542 #define AGGREGATE_AS_UNSET 0
7544 static const char *bgp_origin2str(uint8_t origin
)
7547 case BGP_ORIGIN_IGP
:
7549 case BGP_ORIGIN_EGP
:
7551 case BGP_ORIGIN_INCOMPLETE
:
7552 return "incomplete";
7557 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7558 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7560 struct bgp_dest
*dest
;
7561 struct bgp_aggregate
*aggregate
;
7563 /* If the bgp instance is being deleted or self peer is deleted
7564 * then do not create aggregate route
7566 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7567 || (bgp
->peer_self
== NULL
))
7571 /* Old configuration check. */
7572 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7574 snprintf(errmsg
, errmsg_len
,
7575 "There is no aggregate-address configuration.\n");
7579 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7580 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7581 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7584 /* Unlock aggregate address configuration. */
7585 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7587 if (aggregate
->community
)
7588 community_free(&aggregate
->community
);
7590 if (aggregate
->community_hash
) {
7591 /* Delete all communities in the hash.
7593 hash_clean(aggregate
->community_hash
,
7594 bgp_aggr_community_remove
);
7595 /* Free up the community_hash.
7597 hash_free(aggregate
->community_hash
);
7600 if (aggregate
->ecommunity
)
7601 ecommunity_free(&aggregate
->ecommunity
);
7603 if (aggregate
->ecommunity_hash
) {
7604 /* Delete all ecommunities in the hash.
7606 hash_clean(aggregate
->ecommunity_hash
,
7607 bgp_aggr_ecommunity_remove
);
7608 /* Free up the ecommunity_hash.
7610 hash_free(aggregate
->ecommunity_hash
);
7613 if (aggregate
->lcommunity
)
7614 lcommunity_free(&aggregate
->lcommunity
);
7616 if (aggregate
->lcommunity_hash
) {
7617 /* Delete all lcommunities in the hash.
7619 hash_clean(aggregate
->lcommunity_hash
,
7620 bgp_aggr_lcommunity_remove
);
7621 /* Free up the lcommunity_hash.
7623 hash_free(aggregate
->lcommunity_hash
);
7626 if (aggregate
->aspath
)
7627 aspath_free(aggregate
->aspath
);
7629 if (aggregate
->aspath_hash
) {
7630 /* Delete all as-paths in the hash.
7632 hash_clean(aggregate
->aspath_hash
,
7633 bgp_aggr_aspath_remove
);
7634 /* Free up the aspath_hash.
7636 hash_free(aggregate
->aspath_hash
);
7639 bgp_aggregate_free(aggregate
);
7640 bgp_dest_unlock_node(dest
);
7641 bgp_dest_unlock_node(dest
);
7646 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7647 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7648 uint8_t as_set
, uint8_t origin
, bool match_med
,
7649 const char *suppress_map
,
7650 char *errmsg
, size_t errmsg_len
)
7653 struct bgp_dest
*dest
;
7654 struct bgp_aggregate
*aggregate
;
7655 uint8_t as_set_new
= as_set
;
7656 char buf
[PREFIX2STR_BUFFER
];
7658 if (suppress_map
&& summary_only
) {
7659 snprintf(errmsg
, errmsg_len
,
7660 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7666 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7667 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7670 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7671 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7675 /* Old configuration check. */
7676 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7677 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7680 snprintf(errmsg
, errmsg_len
,
7681 "There is already same aggregate network.\n");
7682 /* try to remove the old entry */
7683 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7686 snprintf(errmsg
, errmsg_len
,
7687 "Error deleting aggregate.\n");
7688 bgp_dest_unlock_node(dest
);
7693 /* Make aggregate address structure. */
7694 aggregate
= bgp_aggregate_new();
7695 aggregate
->summary_only
= summary_only
;
7696 aggregate
->match_med
= match_med
;
7698 /* Network operators MUST NOT locally generate any new
7699 * announcements containing AS_SET or AS_CONFED_SET. If they have
7700 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7701 * SHOULD withdraw those routes and re-announce routes for the
7702 * aggregate or component prefixes (i.e., the more-specific routes
7703 * subsumed by the previously aggregated route) without AS_SET
7704 * or AS_CONFED_SET in the updates.
7706 if (bgp
->reject_as_sets
) {
7707 if (as_set
== AGGREGATE_AS_SET
) {
7708 as_set_new
= AGGREGATE_AS_UNSET
;
7710 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7714 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7718 aggregate
->as_set
= as_set_new
;
7719 aggregate
->safi
= safi
;
7720 /* Override ORIGIN attribute if defined.
7721 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7722 * to IGP which is not what rfc4271 says.
7723 * This enables the same behavior, optionally.
7725 aggregate
->origin
= origin
;
7728 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7729 route_map_counter_decrement(aggregate
->rmap
.map
);
7730 aggregate
->rmap
.name
=
7731 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7732 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7733 route_map_counter_increment(aggregate
->rmap
.map
);
7737 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7738 route_map_counter_decrement(aggregate
->suppress_map
);
7740 aggregate
->suppress_map_name
=
7741 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7742 aggregate
->suppress_map
=
7743 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7744 route_map_counter_increment(aggregate
->suppress_map
);
7747 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7749 /* Aggregate address insert into BGP routing table. */
7750 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
7756 aggregate_addressv4
, aggregate_addressv4_cmd
,
7757 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7759 "|summary-only$summary_only"
7760 "|route-map WORD$rmap_name"
7761 "|origin <egp|igp|incomplete>$origin_s"
7762 "|matching-MED-only$match_med"
7763 "|suppress-map WORD$suppress_map"
7766 "Configure BGP aggregate entries\n"
7767 "Aggregate prefix\n"
7768 "Aggregate address\n"
7770 "Generate AS set path information\n"
7771 "Filter more specific routes from updates\n"
7772 "Apply route map to aggregate network\n"
7777 "Unknown heritage\n"
7778 "Only aggregate routes with matching MED\n"
7779 "Suppress the selected more specific routes\n"
7780 "Route map with the route selectors\n")
7782 char base_xpath
[XPATH_MAXLEN
];
7783 safi_t safi
= bgp_node_safi(vty
);
7784 char prefix_buf
[PREFIX2STR_BUFFER
];
7787 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
7790 vty_out(vty
, "%% Inconsistent address and mask\n");
7791 return CMD_WARNING_CONFIG_FAILED
;
7794 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
7797 if (!no
&& origin_s
)
7798 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7800 if (!no
&& as_set_s
)
7801 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7803 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7805 if (!no
&& summary_only
)
7806 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7809 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7812 if (!no
&& match_med
)
7813 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7815 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7819 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7822 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
7823 NB_OP_DESTROY
, NULL
);
7826 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7829 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7833 base_xpath
, sizeof(base_xpath
),
7834 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7835 yang_afi_safi_value2identity(AFI_IP
, safi
),
7836 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
7839 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7841 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7843 return nb_cli_apply_changes(vty
, base_xpath
);
7846 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
7847 "[no] aggregate-address X:X::X:X/M$prefix {"
7849 "|summary-only$summary_only"
7850 "|route-map WORD$rmap_name"
7851 "|origin <egp|igp|incomplete>$origin_s"
7852 "|matching-MED-only$match_med"
7853 "|suppress-map WORD$suppress_map"
7856 "Configure BGP aggregate entries\n"
7857 "Aggregate prefix\n"
7858 "Generate AS set path information\n"
7859 "Filter more specific routes from updates\n"
7860 "Apply route map to aggregate network\n"
7865 "Unknown heritage\n"
7866 "Only aggregate routes with matching MED\n"
7867 "Suppress the selected more specific routes\n"
7868 "Route map with the route selectors\n")
7870 char base_xpath
[XPATH_MAXLEN
];
7871 safi_t safi
= bgp_node_safi(vty
);
7873 if (!no
&& origin_s
)
7874 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7876 if (!no
&& as_set_s
)
7877 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7879 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7881 if (!no
&& summary_only
)
7882 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7885 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7888 if (!no
&& match_med
)
7889 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7891 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7895 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7899 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7902 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7906 base_xpath
, sizeof(base_xpath
),
7907 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7908 yang_afi_safi_value2identity(AFI_IP6
, safi
),
7909 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
7912 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7914 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7916 return nb_cli_apply_changes(vty
, base_xpath
);
7919 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7920 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
7924 vty_out(vty
, " aggregate-address %s",
7925 yang_dnode_get_string(dnode
, "./prefix"));
7927 if (yang_dnode_get_bool(dnode
, "./as-set"))
7928 vty_out(vty
, " as-set");
7930 if (yang_dnode_get_bool(dnode
, "./summary-only"))
7931 vty_out(vty
, " summary-only");
7933 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
7934 vty_out(vty
, " route-map %s",
7935 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
7937 origin
= yang_dnode_get_enum(dnode
, "./origin");
7938 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
7939 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
7941 if (yang_dnode_get_bool(dnode
, "./match-med"))
7942 vty_out(vty
, " matching-MED-only");
7947 /* Redistribute route treatment. */
7948 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7949 const union g_addr
*nexthop
, ifindex_t ifindex
,
7950 enum nexthop_types_t nhtype
, uint32_t metric
,
7951 uint8_t type
, unsigned short instance
,
7954 struct bgp_path_info
*new;
7955 struct bgp_path_info
*bpi
;
7956 struct bgp_path_info rmap_path
;
7957 struct bgp_dest
*bn
;
7959 struct attr
*new_attr
;
7961 route_map_result_t ret
;
7962 struct bgp_redist
*red
;
7964 /* Make default attribute. */
7965 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7967 * This must not be NULL to satisfy Coverity SA
7969 assert(attr
.aspath
);
7972 case NEXTHOP_TYPE_IFINDEX
:
7974 case NEXTHOP_TYPE_IPV4
:
7975 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7976 attr
.nexthop
= nexthop
->ipv4
;
7978 case NEXTHOP_TYPE_IPV6
:
7979 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7980 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7981 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7983 case NEXTHOP_TYPE_BLACKHOLE
:
7984 switch (p
->family
) {
7986 attr
.nexthop
.s_addr
= INADDR_ANY
;
7989 memset(&attr
.mp_nexthop_global
, 0,
7990 sizeof(attr
.mp_nexthop_global
));
7991 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7996 attr
.nh_ifindex
= ifindex
;
7999 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8002 afi
= family2afi(p
->family
);
8004 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8006 struct attr attr_new
;
8008 /* Copy attribute for modification. */
8011 if (red
->redist_metric_flag
)
8012 attr_new
.med
= red
->redist_metric
;
8014 /* Apply route-map. */
8015 if (red
->rmap
.name
) {
8016 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8017 rmap_path
.peer
= bgp
->peer_self
;
8018 rmap_path
.attr
= &attr_new
;
8020 SET_FLAG(bgp
->peer_self
->rmap_type
,
8021 PEER_RMAP_TYPE_REDISTRIBUTE
);
8023 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8025 bgp
->peer_self
->rmap_type
= 0;
8027 if (ret
== RMAP_DENYMATCH
) {
8028 /* Free uninterned attribute. */
8029 bgp_attr_flush(&attr_new
);
8031 /* Unintern original. */
8032 aspath_unintern(&attr
.aspath
);
8033 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8038 if (bgp_in_graceful_shutdown(bgp
))
8039 bgp_attr_add_gshut_community(&attr_new
);
8041 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8042 SAFI_UNICAST
, p
, NULL
);
8044 new_attr
= bgp_attr_intern(&attr_new
);
8046 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8047 if (bpi
->peer
== bgp
->peer_self
8048 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8052 /* Ensure the (source route) type is updated. */
8054 if (attrhash_cmp(bpi
->attr
, new_attr
)
8055 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8056 bgp_attr_unintern(&new_attr
);
8057 aspath_unintern(&attr
.aspath
);
8058 bgp_dest_unlock_node(bn
);
8061 /* The attribute is changed. */
8062 bgp_path_info_set_flag(bn
, bpi
,
8063 BGP_PATH_ATTR_CHANGED
);
8065 /* Rewrite BGP route information. */
8066 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8067 bgp_path_info_restore(bn
, bpi
);
8069 bgp_aggregate_decrement(
8070 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8071 bgp_attr_unintern(&bpi
->attr
);
8072 bpi
->attr
= new_attr
;
8073 bpi
->uptime
= bgp_clock();
8075 /* Process change. */
8076 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8078 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8079 bgp_dest_unlock_node(bn
);
8080 aspath_unintern(&attr
.aspath
);
8082 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8084 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8086 vpn_leak_from_vrf_update(
8087 bgp_get_default(), bgp
, bpi
);
8093 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8094 bgp
->peer_self
, new_attr
, bn
);
8095 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8097 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8098 bgp_path_info_add(bn
, new);
8099 bgp_dest_unlock_node(bn
);
8100 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8102 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8103 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8105 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8109 /* Unintern original. */
8110 aspath_unintern(&attr
.aspath
);
8113 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8114 unsigned short instance
)
8117 struct bgp_dest
*dest
;
8118 struct bgp_path_info
*pi
;
8119 struct bgp_redist
*red
;
8121 afi
= family2afi(p
->family
);
8123 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8125 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8126 SAFI_UNICAST
, p
, NULL
);
8128 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8129 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8133 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8134 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8136 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8139 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8140 bgp_path_info_delete(dest
, pi
);
8141 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8143 bgp_dest_unlock_node(dest
);
8147 /* Withdraw specified route type's route. */
8148 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8149 unsigned short instance
)
8151 struct bgp_dest
*dest
;
8152 struct bgp_path_info
*pi
;
8153 struct bgp_table
*table
;
8155 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8157 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8158 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8159 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8160 && pi
->instance
== instance
)
8164 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8165 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8167 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8170 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8171 pi
, afi
, SAFI_UNICAST
);
8172 bgp_path_info_delete(dest
, pi
);
8173 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8178 /* Static function to display route. */
8179 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
8180 json_object
*json
, bool wide
)
8186 if (p
->family
== AF_INET
) {
8188 len
= vty_out(vty
, "%pFX", p
);
8190 json_object_string_add(json
, "prefix",
8191 inet_ntop(p
->family
,
8194 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8195 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8196 json_object_string_add(json
, "network", buf2
);
8198 } else if (p
->family
== AF_ETHERNET
) {
8199 len
= vty_out(vty
, "%pFX", p
);
8200 } else if (p
->family
== AF_EVPN
) {
8202 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8204 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8205 } else if (p
->family
== AF_FLOWSPEC
) {
8206 route_vty_out_flowspec(vty
, p
, NULL
,
8208 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8209 NLRI_STRING_FORMAT_MIN
, json
);
8212 len
= vty_out(vty
, "%pFX", p
);
8214 json_object_string_add(json
, "prefix",
8215 inet_ntop(p
->family
,
8218 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8219 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8220 json_object_string_add(json
, "network", buf2
);
8225 len
= wide
? (45 - len
) : (17 - len
);
8227 vty_out(vty
, "\n%*s", 20, " ");
8229 vty_out(vty
, "%*s", len
, " ");
8233 enum bgp_display_type
{
8238 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8241 case bgp_path_selection_none
:
8242 return "Nothing to Select";
8243 case bgp_path_selection_first
:
8244 return "First path received";
8245 case bgp_path_selection_evpn_sticky_mac
:
8246 return "EVPN Sticky Mac";
8247 case bgp_path_selection_evpn_seq
:
8248 return "EVPN sequence number";
8249 case bgp_path_selection_evpn_lower_ip
:
8250 return "EVPN lower IP";
8251 case bgp_path_selection_evpn_local_path
:
8252 return "EVPN local ES path";
8253 case bgp_path_selection_evpn_non_proxy
:
8254 return "EVPN non proxy";
8255 case bgp_path_selection_weight
:
8257 case bgp_path_selection_local_pref
:
8258 return "Local Pref";
8259 case bgp_path_selection_local_route
:
8260 return "Local Route";
8261 case bgp_path_selection_confed_as_path
:
8262 return "Confederation based AS Path";
8263 case bgp_path_selection_as_path
:
8265 case bgp_path_selection_origin
:
8267 case bgp_path_selection_med
:
8269 case bgp_path_selection_peer
:
8271 case bgp_path_selection_confed
:
8272 return "Confed Peer Type";
8273 case bgp_path_selection_igp_metric
:
8274 return "IGP Metric";
8275 case bgp_path_selection_older
:
8276 return "Older Path";
8277 case bgp_path_selection_router_id
:
8279 case bgp_path_selection_cluster_length
:
8280 return "Cluster length";
8281 case bgp_path_selection_stale
:
8282 return "Path Staleness";
8283 case bgp_path_selection_local_configured
:
8284 return "Locally configured route";
8285 case bgp_path_selection_neighbor_ip
:
8286 return "Neighbor IP";
8287 case bgp_path_selection_default
:
8288 return "Nothing left to compare";
8290 return "Invalid (internal error)";
8293 /* Print the short form route status for a bgp_path_info */
8294 static void route_vty_short_status_out(struct vty
*vty
,
8295 struct bgp_path_info
*path
,
8296 json_object
*json_path
)
8300 /* Route status display. */
8301 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8302 json_object_boolean_true_add(json_path
, "removed");
8304 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8305 json_object_boolean_true_add(json_path
, "stale");
8307 if (path
->extra
&& bgp_path_suppressed(path
))
8308 json_object_boolean_true_add(json_path
, "suppressed");
8310 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8311 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8312 json_object_boolean_true_add(json_path
, "valid");
8315 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8316 json_object_boolean_true_add(json_path
, "history");
8318 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8319 json_object_boolean_true_add(json_path
, "damped");
8321 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8322 json_object_boolean_true_add(json_path
, "bestpath");
8323 json_object_string_add(json_path
, "selectionReason",
8324 bgp_path_selection_reason2str(
8325 path
->net
->reason
));
8328 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8329 json_object_boolean_true_add(json_path
, "multipath");
8331 /* Internal route. */
8332 if ((path
->peer
->as
)
8333 && (path
->peer
->as
== path
->peer
->local_as
))
8334 json_object_string_add(json_path
, "pathFrom",
8337 json_object_string_add(json_path
, "pathFrom",
8343 /* Route status display. */
8344 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8346 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8348 else if (bgp_path_suppressed(path
))
8350 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8351 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8357 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8359 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8361 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8363 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8368 /* Internal route. */
8369 if (path
->peer
&& (path
->peer
->as
)
8370 && (path
->peer
->as
== path
->peer
->local_as
))
8376 static char *bgp_nexthop_hostname(struct peer
*peer
,
8377 struct bgp_nexthop_cache
*bnc
)
8380 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8381 return peer
->hostname
;
8385 /* called from terminal list command */
8386 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8387 struct bgp_path_info
*path
, int display
, safi_t safi
,
8388 json_object
*json_paths
, bool wide
)
8391 struct attr
*attr
= path
->attr
;
8392 json_object
*json_path
= NULL
;
8393 json_object
*json_nexthops
= NULL
;
8394 json_object
*json_nexthop_global
= NULL
;
8395 json_object
*json_nexthop_ll
= NULL
;
8396 json_object
*json_ext_community
= NULL
;
8397 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8399 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8400 bool nexthop_othervrf
= false;
8401 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8402 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8403 char *nexthop_hostname
=
8404 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8405 char esi_buf
[ESI_STR_LEN
];
8408 json_path
= json_object_new_object();
8410 /* short status lead text */
8411 route_vty_short_status_out(vty
, path
, json_path
);
8414 /* print prefix and mask */
8416 route_vty_out_route(p
, vty
, json_path
, wide
);
8418 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8420 route_vty_out_route(p
, vty
, json_path
, wide
);
8424 * If vrf id of nexthop is different from that of prefix,
8425 * set up printable string to append
8427 if (path
->extra
&& path
->extra
->bgp_orig
) {
8428 const char *self
= "";
8433 nexthop_othervrf
= true;
8434 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8436 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8437 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8438 "@%s%s", VRFID_NONE_STR
, self
);
8440 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8441 path
->extra
->bgp_orig
->vrf_id
, self
);
8443 if (path
->extra
->bgp_orig
->inst_type
8444 != BGP_INSTANCE_TYPE_DEFAULT
)
8446 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8448 const char *self
= "";
8453 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8457 * For ENCAP and EVPN routes, nexthop address family is not
8458 * neccessarily the same as the prefix address family.
8459 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8460 * EVPN routes are also exchanged with a MP nexthop. Currently,
8462 * is only IPv4, the value will be present in either
8464 * attr->mp_nexthop_global_in
8466 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8469 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8473 snprintf(nexthop
, sizeof(nexthop
), "%s",
8474 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8478 snprintf(nexthop
, sizeof(nexthop
), "%s",
8479 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8483 snprintf(nexthop
, sizeof(nexthop
), "?");
8488 json_nexthop_global
= json_object_new_object();
8490 json_object_string_add(json_nexthop_global
, "ip",
8493 if (path
->peer
->hostname
)
8494 json_object_string_add(json_nexthop_global
,
8496 path
->peer
->hostname
);
8498 json_object_string_add(json_nexthop_global
, "afi",
8499 (af
== AF_INET
) ? "ipv4"
8501 json_object_boolean_true_add(json_nexthop_global
,
8504 if (nexthop_hostname
)
8505 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8506 nexthop_hostname
, vrf_id_str
);
8508 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8510 len
= wide
? (41 - len
) : (16 - len
);
8512 vty_out(vty
, "\n%*s", 36, " ");
8514 vty_out(vty
, "%*s", len
, " ");
8516 } else if (safi
== SAFI_EVPN
) {
8518 char buf
[BUFSIZ
] = {0};
8520 json_nexthop_global
= json_object_new_object();
8522 json_object_string_add(json_nexthop_global
, "ip",
8524 &attr
->nexthop
, buf
,
8527 if (path
->peer
->hostname
)
8528 json_object_string_add(json_nexthop_global
,
8530 path
->peer
->hostname
);
8532 json_object_string_add(json_nexthop_global
, "afi",
8534 json_object_boolean_true_add(json_nexthop_global
,
8537 if (nexthop_hostname
)
8538 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8539 nexthop_hostname
, vrf_id_str
);
8541 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8544 len
= wide
? (41 - len
) : (16 - len
);
8546 vty_out(vty
, "\n%*s", 36, " ");
8548 vty_out(vty
, "%*s", len
, " ");
8550 } else if (safi
== SAFI_FLOWSPEC
) {
8551 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8553 char buf
[BUFSIZ
] = {0};
8555 json_nexthop_global
= json_object_new_object();
8557 json_object_string_add(json_nexthop_global
,
8559 json_object_string_add(
8560 json_nexthop_global
, "ip",
8561 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8564 if (path
->peer
->hostname
)
8565 json_object_string_add(
8566 json_nexthop_global
, "hostname",
8567 path
->peer
->hostname
);
8569 json_object_boolean_true_add(
8570 json_nexthop_global
,
8573 if (nexthop_hostname
)
8574 len
= vty_out(vty
, "%pI4(%s)%s",
8579 len
= vty_out(vty
, "%pI4%s",
8583 len
= wide
? (41 - len
) : (16 - len
);
8585 vty_out(vty
, "\n%*s", 36, " ");
8587 vty_out(vty
, "%*s", len
, " ");
8590 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8592 char buf
[BUFSIZ
] = {0};
8594 json_nexthop_global
= json_object_new_object();
8596 json_object_string_add(json_nexthop_global
, "ip",
8598 &attr
->nexthop
, buf
,
8601 if (path
->peer
->hostname
)
8602 json_object_string_add(json_nexthop_global
,
8604 path
->peer
->hostname
);
8606 json_object_string_add(json_nexthop_global
, "afi",
8608 json_object_boolean_true_add(json_nexthop_global
,
8611 if (nexthop_hostname
)
8612 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8613 nexthop_hostname
, vrf_id_str
);
8615 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8618 len
= wide
? (41 - len
) : (16 - len
);
8620 vty_out(vty
, "\n%*s", 36, " ");
8622 vty_out(vty
, "%*s", len
, " ");
8627 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8631 json_nexthop_global
= json_object_new_object();
8632 json_object_string_add(
8633 json_nexthop_global
, "ip",
8634 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8637 if (path
->peer
->hostname
)
8638 json_object_string_add(json_nexthop_global
,
8640 path
->peer
->hostname
);
8642 json_object_string_add(json_nexthop_global
, "afi",
8644 json_object_string_add(json_nexthop_global
, "scope",
8647 /* We display both LL & GL if both have been
8649 if ((attr
->mp_nexthop_len
8650 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8651 || (path
->peer
->conf_if
)) {
8652 json_nexthop_ll
= json_object_new_object();
8653 json_object_string_add(
8654 json_nexthop_ll
, "ip",
8656 &attr
->mp_nexthop_local
, buf
,
8659 if (path
->peer
->hostname
)
8660 json_object_string_add(
8661 json_nexthop_ll
, "hostname",
8662 path
->peer
->hostname
);
8664 json_object_string_add(json_nexthop_ll
, "afi",
8666 json_object_string_add(json_nexthop_ll
, "scope",
8669 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8670 &attr
->mp_nexthop_local
)
8672 && !attr
->mp_nexthop_prefer_global
)
8673 json_object_boolean_true_add(
8674 json_nexthop_ll
, "used");
8676 json_object_boolean_true_add(
8677 json_nexthop_global
, "used");
8679 json_object_boolean_true_add(
8680 json_nexthop_global
, "used");
8682 /* Display LL if LL/Global both in table unless
8683 * prefer-global is set */
8684 if (((attr
->mp_nexthop_len
8685 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8686 && !attr
->mp_nexthop_prefer_global
)
8687 || (path
->peer
->conf_if
)) {
8688 if (path
->peer
->conf_if
) {
8689 len
= vty_out(vty
, "%s",
8690 path
->peer
->conf_if
);
8691 /* len of IPv6 addr + max len of def
8693 len
= wide
? (41 - len
) : (16 - len
);
8696 vty_out(vty
, "\n%*s", 36, " ");
8698 vty_out(vty
, "%*s", len
, " ");
8700 if (nexthop_hostname
)
8703 &attr
->mp_nexthop_local
,
8709 &attr
->mp_nexthop_local
,
8712 len
= wide
? (41 - len
) : (16 - len
);
8715 vty_out(vty
, "\n%*s", 36, " ");
8717 vty_out(vty
, "%*s", len
, " ");
8720 if (nexthop_hostname
)
8721 len
= vty_out(vty
, "%pI6(%s)%s",
8722 &attr
->mp_nexthop_global
,
8726 len
= vty_out(vty
, "%pI6%s",
8727 &attr
->mp_nexthop_global
,
8730 len
= wide
? (41 - len
) : (16 - len
);
8733 vty_out(vty
, "\n%*s", 36, " ");
8735 vty_out(vty
, "%*s", len
, " ");
8741 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8743 json_object_int_add(json_path
, "metric", attr
->med
);
8745 vty_out(vty
, "%7u", attr
->med
);
8747 vty_out(vty
, "%10u", attr
->med
);
8748 else if (!json_paths
) {
8750 vty_out(vty
, "%*s", 7, " ");
8752 vty_out(vty
, "%*s", 10, " ");
8756 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8758 json_object_int_add(json_path
, "locPrf",
8761 vty_out(vty
, "%7u", attr
->local_pref
);
8762 else if (!json_paths
)
8766 json_object_int_add(json_path
, "weight", attr
->weight
);
8768 vty_out(vty
, "%7u ", attr
->weight
);
8772 json_object_string_add(
8773 json_path
, "peerId",
8774 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8780 json_object_string_add(json_path
, "path",
8783 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8788 json_object_string_add(json_path
, "origin",
8789 bgp_origin_long_str
[attr
->origin
]);
8791 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8794 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8795 json_object_string_add(json_path
, "esi",
8796 esi_to_str(&attr
->esi
,
8797 esi_buf
, sizeof(esi_buf
)));
8799 if (safi
== SAFI_EVPN
&&
8800 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8801 json_ext_community
= json_object_new_object();
8802 json_object_string_add(json_ext_community
,
8804 attr
->ecommunity
->str
);
8805 json_object_object_add(json_path
,
8806 "extendedCommunity",
8807 json_ext_community
);
8811 json_object_boolean_true_add(json_path
,
8812 "announceNexthopSelf");
8813 if (nexthop_othervrf
) {
8814 json_object_string_add(json_path
, "nhVrfName",
8817 json_object_int_add(json_path
, "nhVrfId",
8818 ((nexthop_vrfid
== VRF_UNKNOWN
)
8820 : (int)nexthop_vrfid
));
8825 if (json_nexthop_global
|| json_nexthop_ll
) {
8826 json_nexthops
= json_object_new_array();
8828 if (json_nexthop_global
)
8829 json_object_array_add(json_nexthops
,
8830 json_nexthop_global
);
8832 if (json_nexthop_ll
)
8833 json_object_array_add(json_nexthops
,
8836 json_object_object_add(json_path
, "nexthops",
8840 json_object_array_add(json_paths
, json_path
);
8844 if (safi
== SAFI_EVPN
) {
8845 struct bgp_path_es_info
*path_es_info
= NULL
;
8848 path_es_info
= path
->extra
->es_info
;
8850 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8851 /* XXX - add these params to the json out */
8852 vty_out(vty
, "%*s", 20, " ");
8853 vty_out(vty
, "ESI:%s",
8854 esi_to_str(&attr
->esi
, esi_buf
,
8856 if (path_es_info
&& path_es_info
->es
)
8857 vty_out(vty
, " VNI: %u",
8862 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8863 vty_out(vty
, "%*s", 20, " ");
8864 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8868 #ifdef ENABLE_BGP_VNC
8869 /* prints an additional line, indented, with VNC info, if
8871 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8872 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8877 /* called from terminal list command */
8878 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8879 struct attr
*attr
, safi_t safi
, bool use_json
,
8880 json_object
*json_ar
, bool wide
)
8882 json_object
*json_status
= NULL
;
8883 json_object
*json_net
= NULL
;
8887 /* Route status display. */
8889 json_status
= json_object_new_object();
8890 json_net
= json_object_new_object();
8897 /* print prefix and mask */
8899 if (safi
== SAFI_EVPN
)
8900 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8901 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8902 json_object_string_add(
8903 json_net
, "addrPrefix",
8904 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8906 json_object_int_add(json_net
, "prefixLen",
8908 prefix2str(p
, buff
, PREFIX_STRLEN
);
8909 json_object_string_add(json_net
, "network", buff
);
8912 route_vty_out_route(p
, vty
, NULL
, wide
);
8914 /* Print attribute */
8917 char buf
[BUFSIZ
] = {0};
8919 if (p
->family
== AF_INET
8920 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8921 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8922 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8923 json_object_string_add(
8924 json_net
, "nextHop",
8927 &attr
->mp_nexthop_global_in
,
8930 json_object_string_add(
8931 json_net
, "nextHop",
8933 &attr
->nexthop
, buf
,
8935 } else if (p
->family
== AF_INET6
8936 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8939 json_object_string_add(
8940 json_net
, "nextHopGlobal",
8942 &attr
->mp_nexthop_global
, buf
,
8944 } else if (p
->family
== AF_EVPN
8945 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8946 char buf
[BUFSIZ
] = {0};
8948 json_object_string_add(
8949 json_net
, "nextHop",
8951 &attr
->mp_nexthop_global_in
,
8956 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8957 json_object_int_add(json_net
, "metric",
8960 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8961 json_object_int_add(json_net
, "locPrf",
8964 json_object_int_add(json_net
, "weight", attr
->weight
);
8968 json_object_string_add(json_net
, "path",
8972 json_object_string_add(json_net
, "bgpOriginCode",
8973 bgp_origin_str
[attr
->origin
]);
8975 if (p
->family
== AF_INET
8976 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8977 || safi
== SAFI_EVPN
8978 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8979 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8980 || safi
== SAFI_EVPN
)
8981 vty_out(vty
, "%-16pI4",
8982 &attr
->mp_nexthop_global_in
);
8984 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
8986 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
8987 } else if (p
->family
== AF_INET6
8988 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8994 &attr
->mp_nexthop_global
, buf
,
8996 len
= wide
? (41 - len
) : (16 - len
);
8998 vty_out(vty
, "\n%*s", 36, " ");
9000 vty_out(vty
, "%*s", len
, " ");
9003 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9005 vty_out(vty
, "%7u", attr
->med
);
9007 vty_out(vty
, "%10u", attr
->med
);
9013 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9014 vty_out(vty
, "%7u", attr
->local_pref
);
9018 vty_out(vty
, "%7u ", attr
->weight
);
9022 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9025 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9029 json_object_boolean_true_add(json_status
, "*");
9030 json_object_boolean_true_add(json_status
, ">");
9031 json_object_object_add(json_net
, "appliedStatusSymbols",
9034 prefix2str(p
, buff
, PREFIX_STRLEN
);
9035 json_object_object_add(json_ar
, buff
, json_net
);
9040 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9041 struct bgp_path_info
*path
, int display
, safi_t safi
,
9044 json_object
*json_out
= NULL
;
9046 mpls_label_t label
= MPLS_INVALID_LABEL
;
9052 json_out
= json_object_new_object();
9054 /* short status lead text */
9055 route_vty_short_status_out(vty
, path
, json_out
);
9057 /* print prefix and mask */
9060 route_vty_out_route(p
, vty
, NULL
, false);
9062 vty_out(vty
, "%*s", 17, " ");
9065 /* Print attribute */
9067 if (((p
->family
== AF_INET
)
9068 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9069 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9070 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9071 char buf
[BUFSIZ
] = {0};
9073 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9074 || safi
== SAFI_EVPN
) {
9076 json_object_string_add(
9077 json_out
, "mpNexthopGlobalIn",
9079 &attr
->mp_nexthop_global_in
,
9082 vty_out(vty
, "%-16pI4",
9083 &attr
->mp_nexthop_global_in
);
9086 json_object_string_add(
9087 json_out
, "nexthop",
9088 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9091 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9093 } else if (((p
->family
== AF_INET6
)
9094 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9095 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9096 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9099 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9101 json_object_string_add(
9102 json_out
, "mpNexthopGlobalIn",
9104 &attr
->mp_nexthop_global
,
9105 buf_a
, sizeof(buf_a
)));
9109 &attr
->mp_nexthop_global
,
9110 buf_a
, sizeof(buf_a
)));
9111 } else if (attr
->mp_nexthop_len
9112 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9113 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9114 &attr
->mp_nexthop_global
,
9115 &attr
->mp_nexthop_local
);
9117 json_object_string_add(json_out
,
9118 "mpNexthopGlobalLocal",
9121 vty_out(vty
, "%s", buf_a
);
9125 label
= decode_label(&path
->extra
->label
[0]);
9127 if (bgp_is_valid_label(&label
)) {
9129 json_object_int_add(json_out
, "notag", label
);
9130 json_object_array_add(json
, json_out
);
9132 vty_out(vty
, "notag/%d", label
);
9138 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9139 struct bgp_path_info
*path
, int display
,
9140 json_object
*json_paths
)
9143 char buf
[BUFSIZ
] = {0};
9144 json_object
*json_path
= NULL
;
9145 json_object
*json_nexthop
= NULL
;
9146 json_object
*json_overlay
= NULL
;
9152 json_path
= json_object_new_object();
9153 json_overlay
= json_object_new_object();
9154 json_nexthop
= json_object_new_object();
9157 /* short status lead text */
9158 route_vty_short_status_out(vty
, path
, json_path
);
9160 /* print prefix and mask */
9162 route_vty_out_route(p
, vty
, json_path
, false);
9164 vty_out(vty
, "%*s", 17, " ");
9166 /* Print attribute */
9169 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9173 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9175 vty_out(vty
, "%-16s", buf
);
9177 json_object_string_add(json_nexthop
, "ip", buf
);
9179 json_object_string_add(json_nexthop
, "afi", "ipv4");
9181 json_object_object_add(json_path
, "nexthop",
9186 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9187 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9189 vty_out(vty
, "%s(%s)", buf
, buf1
);
9191 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9193 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9196 json_object_string_add(json_nexthop
, "afi", "ipv6");
9198 json_object_object_add(json_path
, "nexthop",
9206 json_object_string_add(json_nexthop
, "Error",
9207 "Unsupported address-family");
9211 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9213 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9214 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9215 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9216 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9219 vty_out(vty
, "/%s", buf
);
9221 json_object_string_add(json_overlay
, "gw", buf
);
9223 if (attr
->ecommunity
) {
9225 struct ecommunity_val
*routermac
= ecommunity_lookup(
9226 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9227 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9230 mac
= ecom_mac2str((char *)routermac
->val
);
9233 vty_out(vty
, "/%s", mac
);
9235 json_object_string_add(json_overlay
, "rmac",
9238 XFREE(MTYPE_TMP
, mac
);
9245 json_object_object_add(json_path
, "overlay", json_overlay
);
9247 json_object_array_add(json_paths
, json_path
);
9251 /* dampening route */
9252 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9253 struct bgp_path_info
*path
, int display
,
9254 afi_t afi
, safi_t safi
, bool use_json
,
9259 char timebuf
[BGP_UPTIME_LEN
];
9261 /* short status lead text */
9262 route_vty_short_status_out(vty
, path
, json
);
9264 /* print prefix and mask */
9267 route_vty_out_route(p
, vty
, NULL
, false);
9269 vty_out(vty
, "%*s", 17, " ");
9272 len
= vty_out(vty
, "%s", path
->peer
->host
);
9276 vty_out(vty
, "\n%*s", 34, " ");
9279 json_object_int_add(json
, "peerHost", len
);
9281 vty_out(vty
, "%*s", len
, " ");
9285 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9286 safi
, use_json
, json
);
9289 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9290 BGP_UPTIME_LEN
, afi
, safi
,
9293 /* Print attribute */
9299 json_object_string_add(json
, "asPath",
9302 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9307 json_object_string_add(json
, "origin",
9308 bgp_origin_str
[attr
->origin
]);
9310 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9317 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9318 struct bgp_path_info
*path
, int display
,
9319 afi_t afi
, safi_t safi
, bool use_json
,
9323 struct bgp_damp_info
*bdi
;
9324 char timebuf
[BGP_UPTIME_LEN
];
9330 bdi
= path
->extra
->damp_info
;
9332 /* short status lead text */
9333 route_vty_short_status_out(vty
, path
, json
);
9335 /* print prefix and mask */
9338 route_vty_out_route(p
, vty
, NULL
, false);
9340 vty_out(vty
, "%*s", 17, " ");
9343 len
= vty_out(vty
, "%s", path
->peer
->host
);
9347 vty_out(vty
, "\n%*s", 33, " ");
9350 json_object_int_add(json
, "peerHost", len
);
9352 vty_out(vty
, "%*s", len
, " ");
9355 len
= vty_out(vty
, "%d", bdi
->flap
);
9362 json_object_int_add(json
, "bdiFlap", len
);
9364 vty_out(vty
, "%*s", len
, " ");
9368 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9371 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9372 BGP_UPTIME_LEN
, 0, NULL
));
9374 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9375 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9377 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9378 BGP_UPTIME_LEN
, afi
, safi
,
9382 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9383 BGP_UPTIME_LEN
, afi
,
9384 safi
, use_json
, json
));
9387 vty_out(vty
, "%*s ", 8, " ");
9390 /* Print attribute */
9396 json_object_string_add(json
, "asPath",
9399 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9404 json_object_string_add(json
, "origin",
9405 bgp_origin_str
[attr
->origin
]);
9407 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9413 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9414 int *first
, const char *header
,
9415 json_object
*json_adv_to
)
9417 char buf1
[INET6_ADDRSTRLEN
];
9418 json_object
*json_peer
= NULL
;
9421 /* 'advertised-to' is a dictionary of peers we have advertised
9423 * prefix too. The key is the peer's IP or swpX, the value is
9425 * hostname if we know it and "" if not.
9427 json_peer
= json_object_new_object();
9430 json_object_string_add(json_peer
, "hostname",
9434 json_object_object_add(json_adv_to
, peer
->conf_if
,
9437 json_object_object_add(
9439 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9443 vty_out(vty
, "%s", header
);
9448 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9450 vty_out(vty
, " %s(%s)", peer
->hostname
,
9453 vty_out(vty
, " %s(%s)", peer
->hostname
,
9454 sockunion2str(&peer
->su
, buf1
,
9458 vty_out(vty
, " %s", peer
->conf_if
);
9461 sockunion2str(&peer
->su
, buf1
,
9467 static void route_vty_out_tx_ids(struct vty
*vty
,
9468 struct bgp_addpath_info_data
*d
)
9472 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9473 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9474 d
->addpath_tx_id
[i
],
9475 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9479 static void route_vty_out_detail_es_info(struct vty
*vty
,
9480 struct bgp_path_info
*pi
,
9482 json_object
*json_path
)
9484 char esi_buf
[ESI_STR_LEN
];
9485 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9486 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9487 ATTR_ES_PEER_ROUTER
);
9488 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9489 ATTR_ES_PEER_ACTIVE
);
9490 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9491 ATTR_ES_PEER_PROXY
);
9492 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9494 json_object
*json_es_info
= NULL
;
9496 json_object_string_add(
9499 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9500 json_es_info
= json_object_new_object();
9502 json_object_boolean_true_add(
9503 json_es_info
, "localEs");
9505 json_object_boolean_true_add(
9506 json_es_info
, "peerActive");
9508 json_object_boolean_true_add(
9509 json_es_info
, "peerProxy");
9511 json_object_boolean_true_add(
9512 json_es_info
, "peerRouter");
9513 if (attr
->mm_sync_seqnum
)
9514 json_object_int_add(
9515 json_es_info
, "peerSeq",
9516 attr
->mm_sync_seqnum
);
9517 json_object_object_add(
9518 json_path
, "es_info",
9522 if (bgp_evpn_attr_is_sync(attr
))
9524 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9526 es_local
? "local-es":"",
9527 peer_proxy
? "proxy " : "",
9528 peer_active
? "active ":"",
9529 peer_router
? "router ":"",
9530 attr
->mm_sync_seqnum
);
9532 vty_out(vty
, " ESI %s %s\n",
9534 es_local
? "local-es":"");
9538 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
9539 struct bgp_dest
*bn
, struct bgp_path_info
*path
,
9540 afi_t afi
, safi_t safi
, json_object
*json_paths
)
9542 char buf
[INET6_ADDRSTRLEN
];
9544 struct attr
*attr
= path
->attr
;
9545 int sockunion_vty_out(struct vty
*, union sockunion
*);
9547 json_object
*json_bestpath
= NULL
;
9548 json_object
*json_cluster_list
= NULL
;
9549 json_object
*json_cluster_list_list
= NULL
;
9550 json_object
*json_ext_community
= NULL
;
9551 json_object
*json_last_update
= NULL
;
9552 json_object
*json_pmsi
= NULL
;
9553 json_object
*json_nexthop_global
= NULL
;
9554 json_object
*json_nexthop_ll
= NULL
;
9555 json_object
*json_nexthops
= NULL
;
9556 json_object
*json_path
= NULL
;
9557 json_object
*json_peer
= NULL
;
9558 json_object
*json_string
= NULL
;
9559 json_object
*json_adv_to
= NULL
;
9561 struct listnode
*node
, *nnode
;
9563 int addpath_capable
;
9565 unsigned int first_as
;
9567 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9569 char *nexthop_hostname
=
9570 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9573 json_path
= json_object_new_object();
9574 json_peer
= json_object_new_object();
9575 json_nexthop_global
= json_object_new_object();
9582 if (path
->extra
&& path
->extra
->num_labels
) {
9583 bgp_evpn_label2str(path
->extra
->label
,
9584 path
->extra
->num_labels
, tag_buf
,
9587 if (safi
== SAFI_EVPN
) {
9589 vty_out(vty
, " Route %pFX",
9590 (struct prefix_evpn
*)
9591 bgp_dest_get_prefix(bn
));
9592 if (tag_buf
[0] != '\0')
9593 vty_out(vty
, " VNI %s", tag_buf
);
9597 json_object_string_add(json_path
, "VNI",
9602 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9603 struct bgp_path_info
*parent_ri
;
9604 struct bgp_dest
*dest
, *pdest
;
9606 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9607 dest
= parent_ri
->net
;
9608 if (dest
&& dest
->pdest
) {
9609 pdest
= dest
->pdest
;
9611 (struct prefix_rd
*)bgp_dest_get_prefix(
9613 buf1
, sizeof(buf1
));
9614 if (is_pi_family_evpn(parent_ri
)) {
9616 " Imported from %s:%pFX, VNI %s\n",
9618 (struct prefix_evpn
*)
9619 bgp_dest_get_prefix(
9624 " Imported from %s:%pFX\n",
9626 (struct prefix_evpn
*)
9627 bgp_dest_get_prefix(
9633 /* Line1 display AS-path, Aggregator */
9636 if (!attr
->aspath
->json
)
9637 aspath_str_update(attr
->aspath
, true);
9638 json_object_lock(attr
->aspath
->json
);
9639 json_object_object_add(json_path
, "aspath",
9640 attr
->aspath
->json
);
9642 if (attr
->aspath
->segments
)
9643 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9645 vty_out(vty
, " Local");
9649 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9651 json_object_boolean_true_add(json_path
, "removed");
9653 vty_out(vty
, ", (removed)");
9656 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9658 json_object_boolean_true_add(json_path
, "stale");
9660 vty_out(vty
, ", (stale)");
9663 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9665 char buf
[BUFSIZ
] = {0};
9667 json_object_int_add(json_path
, "aggregatorAs",
9668 attr
->aggregator_as
);
9669 json_object_string_add(json_path
, "aggregatorId",
9671 &attr
->aggregator_addr
,
9674 vty_out(vty
, ", (aggregated by %u %pI4)",
9675 attr
->aggregator_as
, &attr
->aggregator_addr
);
9679 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9680 PEER_FLAG_REFLECTOR_CLIENT
)) {
9682 json_object_boolean_true_add(json_path
,
9683 "rxedFromRrClient");
9685 vty_out(vty
, ", (Received from a RR-client)");
9688 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9689 PEER_FLAG_RSERVER_CLIENT
)) {
9691 json_object_boolean_true_add(json_path
,
9692 "rxedFromRsClient");
9694 vty_out(vty
, ", (Received from a RS-client)");
9697 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9699 json_object_boolean_true_add(json_path
,
9700 "dampeningHistoryEntry");
9702 vty_out(vty
, ", (history entry)");
9703 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9705 json_object_boolean_true_add(json_path
,
9706 "dampeningSuppressed");
9708 vty_out(vty
, ", (suppressed due to dampening)");
9714 /* Line2 display Next-hop, Neighbor, Router-id */
9715 /* Display the nexthop */
9716 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9718 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9719 || bn_p
->family
== AF_EVPN
)
9720 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9721 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9722 char buf
[BUFSIZ
] = {0};
9724 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9725 || safi
== SAFI_EVPN
) {
9727 json_object_string_add(
9728 json_nexthop_global
, "ip",
9730 &attr
->mp_nexthop_global_in
,
9733 if (path
->peer
->hostname
)
9734 json_object_string_add(
9735 json_nexthop_global
, "hostname",
9736 path
->peer
->hostname
);
9738 if (nexthop_hostname
)
9739 vty_out(vty
, " %pI4(%s)",
9740 &attr
->mp_nexthop_global_in
,
9743 vty_out(vty
, " %pI4",
9744 &attr
->mp_nexthop_global_in
);
9748 json_object_string_add(
9749 json_nexthop_global
, "ip",
9750 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9753 if (path
->peer
->hostname
)
9754 json_object_string_add(
9755 json_nexthop_global
, "hostname",
9756 path
->peer
->hostname
);
9758 if (nexthop_hostname
)
9759 vty_out(vty
, " %pI4(%s)",
9763 vty_out(vty
, " %pI4",
9769 json_object_string_add(json_nexthop_global
, "afi",
9773 json_object_string_add(
9774 json_nexthop_global
, "ip",
9775 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9776 buf
, INET6_ADDRSTRLEN
));
9778 if (path
->peer
->hostname
)
9779 json_object_string_add(json_nexthop_global
,
9781 path
->peer
->hostname
);
9783 json_object_string_add(json_nexthop_global
, "afi",
9785 json_object_string_add(json_nexthop_global
, "scope",
9788 if (nexthop_hostname
)
9789 vty_out(vty
, " %pI6(%s)",
9790 &attr
->mp_nexthop_global
,
9793 vty_out(vty
, " %pI6",
9794 &attr
->mp_nexthop_global
);
9798 /* Display the IGP cost or 'inaccessible' */
9799 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9801 json_object_boolean_false_add(json_nexthop_global
,
9804 vty_out(vty
, " (inaccessible)");
9806 if (path
->extra
&& path
->extra
->igpmetric
) {
9808 json_object_int_add(json_nexthop_global
,
9810 path
->extra
->igpmetric
);
9812 vty_out(vty
, " (metric %u)",
9813 path
->extra
->igpmetric
);
9816 /* IGP cost is 0, display this only for json */
9819 json_object_int_add(json_nexthop_global
,
9824 json_object_boolean_true_add(json_nexthop_global
,
9828 /* Display peer "from" output */
9829 /* This path was originated locally */
9830 if (path
->peer
== bgp
->peer_self
) {
9832 if (safi
== SAFI_EVPN
9833 || (bn_p
->family
== AF_INET
9834 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9836 json_object_string_add(json_peer
, "peerId",
9839 vty_out(vty
, " from 0.0.0.0 ");
9842 json_object_string_add(json_peer
, "peerId",
9845 vty_out(vty
, " from :: ");
9849 char buf
[BUFSIZ
] = {0};
9851 json_object_string_add(json_peer
, "routerId",
9853 &bgp
->router_id
, buf
,
9856 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
9860 /* We RXed this path from one of our peers */
9864 json_object_string_add(json_peer
, "peerId",
9865 sockunion2str(&path
->peer
->su
,
9868 json_object_string_add(json_peer
, "routerId",
9870 &path
->peer
->remote_id
,
9871 buf1
, sizeof(buf1
)));
9873 if (path
->peer
->hostname
)
9874 json_object_string_add(json_peer
, "hostname",
9875 path
->peer
->hostname
);
9877 if (path
->peer
->domainname
)
9878 json_object_string_add(json_peer
, "domainname",
9879 path
->peer
->domainname
);
9881 if (path
->peer
->conf_if
)
9882 json_object_string_add(json_peer
, "interface",
9883 path
->peer
->conf_if
);
9885 if (path
->peer
->conf_if
) {
9886 if (path
->peer
->hostname
9887 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9888 BGP_FLAG_SHOW_HOSTNAME
))
9889 vty_out(vty
, " from %s(%s)",
9890 path
->peer
->hostname
,
9891 path
->peer
->conf_if
);
9893 vty_out(vty
, " from %s",
9894 path
->peer
->conf_if
);
9896 if (path
->peer
->hostname
9897 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9898 BGP_FLAG_SHOW_HOSTNAME
))
9899 vty_out(vty
, " from %s(%s)",
9900 path
->peer
->hostname
,
9903 vty_out(vty
, " from %s",
9904 sockunion2str(&path
->peer
->su
,
9909 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9910 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
9912 vty_out(vty
, " (%s)",
9914 &path
->peer
->remote_id
, buf1
,
9920 * Note when vrfid of nexthop is different from that of prefix
9922 if (path
->extra
&& path
->extra
->bgp_orig
) {
9923 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9928 if (path
->extra
->bgp_orig
->inst_type
9929 == BGP_INSTANCE_TYPE_DEFAULT
)
9930 vn
= VRF_DEFAULT_NAME
;
9932 vn
= path
->extra
->bgp_orig
->name
;
9934 json_object_string_add(json_path
, "nhVrfName", vn
);
9936 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9937 json_object_int_add(json_path
, "nhVrfId", -1);
9939 json_object_int_add(json_path
, "nhVrfId",
9940 (int)nexthop_vrfid
);
9943 if (nexthop_vrfid
== VRF_UNKNOWN
)
9944 vty_out(vty
, " vrf ?");
9948 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9949 vty_out(vty
, " vrf %s(%u)",
9950 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9957 json_object_boolean_true_add(json_path
,
9958 "announceNexthopSelf");
9960 vty_out(vty
, " announce-nh-self");
9967 /* display the link-local nexthop */
9968 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9970 json_nexthop_ll
= json_object_new_object();
9971 json_object_string_add(
9972 json_nexthop_ll
, "ip",
9973 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9974 buf
, INET6_ADDRSTRLEN
));
9976 if (path
->peer
->hostname
)
9977 json_object_string_add(json_nexthop_ll
,
9979 path
->peer
->hostname
);
9981 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9982 json_object_string_add(json_nexthop_ll
, "scope",
9985 json_object_boolean_true_add(json_nexthop_ll
,
9988 if (!attr
->mp_nexthop_prefer_global
)
9989 json_object_boolean_true_add(json_nexthop_ll
,
9992 json_object_boolean_true_add(
9993 json_nexthop_global
, "used");
9995 vty_out(vty
, " (%s) %s\n",
9996 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9997 buf
, INET6_ADDRSTRLEN
),
9998 attr
->mp_nexthop_prefer_global
10003 /* If we do not have a link-local nexthop then we must flag the
10004 global as "used" */
10007 json_object_boolean_true_add(json_nexthop_global
,
10011 if (safi
== SAFI_EVPN
&&
10012 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10013 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10016 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10017 * Int/Ext/Local, Atomic, best */
10019 json_object_string_add(json_path
, "origin",
10020 bgp_origin_long_str
[attr
->origin
]);
10022 vty_out(vty
, " Origin %s",
10023 bgp_origin_long_str
[attr
->origin
]);
10025 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10027 json_object_int_add(json_path
, "metric", attr
->med
);
10029 vty_out(vty
, ", metric %u", attr
->med
);
10032 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10034 json_object_int_add(json_path
, "locPrf",
10037 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10040 if (attr
->weight
!= 0) {
10042 json_object_int_add(json_path
, "weight", attr
->weight
);
10044 vty_out(vty
, ", weight %u", attr
->weight
);
10047 if (attr
->tag
!= 0) {
10049 json_object_int_add(json_path
, "tag", attr
->tag
);
10051 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10054 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10056 json_object_boolean_false_add(json_path
, "valid");
10058 vty_out(vty
, ", invalid");
10059 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10061 json_object_boolean_true_add(json_path
, "valid");
10063 vty_out(vty
, ", valid");
10066 if (path
->peer
!= bgp
->peer_self
) {
10067 if (path
->peer
->as
== path
->peer
->local_as
) {
10068 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10070 json_object_string_add(
10072 "confed-internal");
10074 vty_out(vty
, ", confed-internal");
10077 json_object_string_add(
10078 json_peer
, "type", "internal");
10080 vty_out(vty
, ", internal");
10083 if (bgp_confederation_peers_check(bgp
,
10086 json_object_string_add(
10088 "confed-external");
10090 vty_out(vty
, ", confed-external");
10093 json_object_string_add(
10094 json_peer
, "type", "external");
10096 vty_out(vty
, ", external");
10099 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10101 json_object_boolean_true_add(json_path
, "aggregated");
10102 json_object_boolean_true_add(json_path
, "local");
10104 vty_out(vty
, ", aggregated, local");
10106 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10108 json_object_boolean_true_add(json_path
, "sourced");
10110 vty_out(vty
, ", sourced");
10113 json_object_boolean_true_add(json_path
, "sourced");
10114 json_object_boolean_true_add(json_path
, "local");
10116 vty_out(vty
, ", sourced, local");
10120 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10122 json_object_boolean_true_add(json_path
,
10123 "atomicAggregate");
10125 vty_out(vty
, ", atomic-aggregate");
10128 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10129 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10130 && bgp_path_info_mpath_count(path
))) {
10132 json_object_boolean_true_add(json_path
, "multipath");
10134 vty_out(vty
, ", multipath");
10137 // Mark the bestpath(s)
10138 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10139 first_as
= aspath_get_first_as(attr
->aspath
);
10142 if (!json_bestpath
)
10143 json_bestpath
= json_object_new_object();
10144 json_object_int_add(json_bestpath
, "bestpathFromAs",
10148 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10150 vty_out(vty
, ", bestpath-from-AS Local");
10154 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10156 if (!json_bestpath
)
10157 json_bestpath
= json_object_new_object();
10158 json_object_boolean_true_add(json_bestpath
, "overall");
10159 json_object_string_add(
10160 json_bestpath
, "selectionReason",
10161 bgp_path_selection_reason2str(bn
->reason
));
10163 vty_out(vty
, ", best");
10164 vty_out(vty
, " (%s)",
10165 bgp_path_selection_reason2str(bn
->reason
));
10170 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10173 vty_out(vty
, "\n");
10175 /* Line 4 display Community */
10176 if (attr
->community
) {
10178 if (!attr
->community
->json
)
10179 community_str(attr
->community
, true);
10180 json_object_lock(attr
->community
->json
);
10181 json_object_object_add(json_path
, "community",
10182 attr
->community
->json
);
10184 vty_out(vty
, " Community: %s\n",
10185 attr
->community
->str
);
10189 /* Line 5 display Extended-community */
10190 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10192 json_ext_community
= json_object_new_object();
10193 json_object_string_add(json_ext_community
, "string",
10194 attr
->ecommunity
->str
);
10195 json_object_object_add(json_path
, "extendedCommunity",
10196 json_ext_community
);
10198 vty_out(vty
, " Extended Community: %s\n",
10199 attr
->ecommunity
->str
);
10203 /* Line 6 display Large community */
10204 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10206 if (!attr
->lcommunity
->json
)
10207 lcommunity_str(attr
->lcommunity
, true);
10208 json_object_lock(attr
->lcommunity
->json
);
10209 json_object_object_add(json_path
, "largeCommunity",
10210 attr
->lcommunity
->json
);
10212 vty_out(vty
, " Large Community: %s\n",
10213 attr
->lcommunity
->str
);
10217 /* Line 7 display Originator, Cluster-id */
10218 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10219 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10220 char buf
[BUFSIZ
] = {0};
10222 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10224 json_object_string_add(
10225 json_path
, "originatorId",
10226 inet_ntop(AF_INET
, &attr
->originator_id
,
10227 buf
, sizeof(buf
)));
10229 vty_out(vty
, " Originator: %pI4",
10230 &attr
->originator_id
);
10233 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10234 struct cluster_list
*cluster
=
10235 bgp_attr_get_cluster(attr
);
10239 json_cluster_list
= json_object_new_object();
10240 json_cluster_list_list
=
10241 json_object_new_array();
10243 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10244 json_string
= json_object_new_string(
10247 buf
, sizeof(buf
)));
10248 json_object_array_add(
10249 json_cluster_list_list
,
10254 * struct cluster_list does not have
10255 * "str" variable like aspath and community
10256 * do. Add this someday if someone asks
10258 * json_object_string_add(json_cluster_list,
10259 * "string", cluster->str);
10261 json_object_object_add(json_cluster_list
,
10263 json_cluster_list_list
);
10264 json_object_object_add(json_path
, "clusterList",
10265 json_cluster_list
);
10267 vty_out(vty
, ", Cluster list: ");
10269 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10270 vty_out(vty
, "%pI4 ",
10271 &cluster
->list
[i
]);
10277 vty_out(vty
, "\n");
10280 if (path
->extra
&& path
->extra
->damp_info
)
10281 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10284 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10285 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10286 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10289 json_object_int_add(json_path
, "remoteLabel", label
);
10291 vty_out(vty
, " Remote label: %d\n", label
);
10295 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10296 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10298 json_object_string_add(json_path
, "remoteSid", buf
);
10300 vty_out(vty
, " Remote SID: %s\n", buf
);
10304 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10306 json_object_int_add(json_path
, "labelIndex",
10307 attr
->label_index
);
10309 vty_out(vty
, " Label Index: %d\n",
10310 attr
->label_index
);
10313 /* Line 8 display Addpath IDs */
10314 if (path
->addpath_rx_id
10315 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10317 json_object_int_add(json_path
, "addpathRxId",
10318 path
->addpath_rx_id
);
10320 /* Keep backwards compatibility with the old API
10321 * by putting TX All's ID in the old field
10323 json_object_int_add(
10324 json_path
, "addpathTxId",
10326 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10328 /* ... but create a specific field for each
10331 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10332 json_object_int_add(
10334 bgp_addpath_names(i
)->id_json_name
,
10335 path
->tx_addpath
.addpath_tx_id
[i
]);
10338 vty_out(vty
, " AddPath ID: RX %u, ",
10339 path
->addpath_rx_id
);
10341 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10345 /* If we used addpath to TX a non-bestpath we need to display
10346 * "Advertised to" on a path-by-path basis
10348 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10351 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10353 bgp_addpath_encode_tx(peer
, afi
, safi
);
10354 has_adj
= bgp_adj_out_lookup(
10356 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10357 &path
->tx_addpath
));
10359 if ((addpath_capable
&& has_adj
)
10360 || (!addpath_capable
&& has_adj
10361 && CHECK_FLAG(path
->flags
,
10362 BGP_PATH_SELECTED
))) {
10363 if (json_path
&& !json_adv_to
)
10364 json_adv_to
= json_object_new_object();
10366 route_vty_out_advertised_to(
10368 " Advertised to:", json_adv_to
);
10374 json_object_object_add(
10375 json_path
, "advertisedTo", json_adv_to
);
10379 vty_out(vty
, "\n");
10384 /* Line 9 display Uptime */
10385 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10387 json_last_update
= json_object_new_object();
10388 json_object_int_add(json_last_update
, "epoch", tbuf
);
10389 json_object_string_add(json_last_update
, "string",
10391 json_object_object_add(json_path
, "lastUpdate",
10394 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10396 /* Line 10 display PMSI tunnel attribute, if present */
10397 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10398 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10399 bgp_attr_get_pmsi_tnl_type(attr
),
10400 PMSI_TNLTYPE_STR_DEFAULT
);
10403 json_pmsi
= json_object_new_object();
10404 json_object_string_add(json_pmsi
, "tunnelType", str
);
10405 json_object_int_add(json_pmsi
, "label",
10406 label2vni(&attr
->label
));
10407 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10409 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10410 str
, label2vni(&attr
->label
));
10413 /* Output some debug about internal state of the dest flags */
10415 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10416 json_object_boolean_true_add(json_path
, "processScheduled");
10417 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10418 json_object_boolean_true_add(json_path
, "userCleared");
10419 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10420 json_object_boolean_true_add(json_path
, "labelChanged");
10421 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10422 json_object_boolean_true_add(json_path
, "registeredForLabel");
10423 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10424 json_object_boolean_true_add(json_path
, "selectDefered");
10425 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10426 json_object_boolean_true_add(json_path
, "fibInstalled");
10427 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10428 json_object_boolean_true_add(json_path
, "fibPending");
10431 /* We've constructed the json object for this path, add it to the json
10435 if (json_nexthop_global
|| json_nexthop_ll
) {
10436 json_nexthops
= json_object_new_array();
10438 if (json_nexthop_global
)
10439 json_object_array_add(json_nexthops
,
10440 json_nexthop_global
);
10442 if (json_nexthop_ll
)
10443 json_object_array_add(json_nexthops
,
10446 json_object_object_add(json_path
, "nexthops",
10450 json_object_object_add(json_path
, "peer", json_peer
);
10451 json_object_array_add(json_paths
, json_path
);
10455 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10456 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10457 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10459 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10460 const char *prefix_list_str
, afi_t afi
,
10461 safi_t safi
, enum bgp_show_type type
);
10462 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10463 const char *filter
, afi_t afi
, safi_t safi
,
10464 enum bgp_show_type type
);
10465 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10466 const char *rmap_str
, afi_t afi
, safi_t safi
,
10467 enum bgp_show_type type
);
10468 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10469 const char *com
, int exact
, afi_t afi
,
10471 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10472 const char *prefix
, afi_t afi
, safi_t safi
,
10473 enum bgp_show_type type
);
10474 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10475 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10477 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10478 const char *comstr
, int exact
, afi_t afi
,
10479 safi_t safi
, uint8_t show_flags
);
10482 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10483 struct bgp_table
*table
, enum bgp_show_type type
,
10484 void *output_arg
, char *rd
, int is_last
,
10485 unsigned long *output_cum
, unsigned long *total_cum
,
10486 unsigned long *json_header_depth
, uint8_t show_flags
)
10488 struct bgp_path_info
*pi
;
10489 struct bgp_dest
*dest
;
10492 unsigned long output_count
= 0;
10493 unsigned long total_count
= 0;
10495 json_object
*json_paths
= NULL
;
10497 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10498 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10499 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10501 if (output_cum
&& *output_cum
!= 0)
10504 if (use_json
&& !*json_header_depth
) {
10506 *json_header_depth
= 1;
10508 vty_out(vty
, "{\n");
10509 *json_header_depth
= 2;
10513 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10514 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10515 " \"localAS\": %u,\n \"routes\": { ",
10516 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10517 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10520 table
->version
, &bgp
->router_id
,
10521 bgp
->default_local_pref
, bgp
->as
);
10523 vty_out(vty
, " \"routeDistinguishers\" : {");
10524 ++*json_header_depth
;
10528 if (use_json
&& rd
) {
10529 vty_out(vty
, " \"%s\" : { ", rd
);
10532 /* Start processing of routes. */
10533 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10534 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10536 pi
= bgp_dest_get_bgp_path_info(dest
);
10542 json_paths
= json_object_new_array();
10546 for (; pi
; pi
= pi
->next
) {
10548 if (type
== bgp_show_type_flap_statistics
10549 || type
== bgp_show_type_flap_neighbor
10550 || type
== bgp_show_type_dampend_paths
10551 || type
== bgp_show_type_damp_neighbor
) {
10552 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10555 if (type
== bgp_show_type_regexp
) {
10556 regex_t
*regex
= output_arg
;
10558 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10562 if (type
== bgp_show_type_prefix_list
) {
10563 struct prefix_list
*plist
= output_arg
;
10565 if (prefix_list_apply(plist
, dest_p
)
10569 if (type
== bgp_show_type_filter_list
) {
10570 struct as_list
*as_list
= output_arg
;
10572 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10573 != AS_FILTER_PERMIT
)
10576 if (type
== bgp_show_type_route_map
) {
10577 struct route_map
*rmap
= output_arg
;
10578 struct bgp_path_info path
;
10579 struct attr dummy_attr
;
10580 route_map_result_t ret
;
10582 dummy_attr
= *pi
->attr
;
10584 path
.peer
= pi
->peer
;
10585 path
.attr
= &dummy_attr
;
10587 ret
= route_map_apply(rmap
, dest_p
, &path
);
10588 if (ret
== RMAP_DENYMATCH
)
10591 if (type
== bgp_show_type_neighbor
10592 || type
== bgp_show_type_flap_neighbor
10593 || type
== bgp_show_type_damp_neighbor
) {
10594 union sockunion
*su
= output_arg
;
10596 if (pi
->peer
== NULL
10597 || pi
->peer
->su_remote
== NULL
10598 || !sockunion_same(pi
->peer
->su_remote
, su
))
10601 if (type
== bgp_show_type_cidr_only
) {
10602 uint32_t destination
;
10604 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10605 if (IN_CLASSC(destination
)
10606 && dest_p
->prefixlen
== 24)
10608 if (IN_CLASSB(destination
)
10609 && dest_p
->prefixlen
== 16)
10611 if (IN_CLASSA(destination
)
10612 && dest_p
->prefixlen
== 8)
10615 if (type
== bgp_show_type_prefix_longer
) {
10617 if (!prefix_match(p
, dest_p
))
10620 if (type
== bgp_show_type_community_all
) {
10621 if (!pi
->attr
->community
)
10624 if (type
== bgp_show_type_community
) {
10625 struct community
*com
= output_arg
;
10627 if (!pi
->attr
->community
10628 || !community_match(pi
->attr
->community
,
10632 if (type
== bgp_show_type_community_exact
) {
10633 struct community
*com
= output_arg
;
10635 if (!pi
->attr
->community
10636 || !community_cmp(pi
->attr
->community
, com
))
10639 if (type
== bgp_show_type_community_list
) {
10640 struct community_list
*list
= output_arg
;
10642 if (!community_list_match(pi
->attr
->community
,
10646 if (type
== bgp_show_type_community_list_exact
) {
10647 struct community_list
*list
= output_arg
;
10649 if (!community_list_exact_match(
10650 pi
->attr
->community
, list
))
10653 if (type
== bgp_show_type_lcommunity
) {
10654 struct lcommunity
*lcom
= output_arg
;
10656 if (!pi
->attr
->lcommunity
10657 || !lcommunity_match(pi
->attr
->lcommunity
,
10662 if (type
== bgp_show_type_lcommunity_exact
) {
10663 struct lcommunity
*lcom
= output_arg
;
10665 if (!pi
->attr
->lcommunity
10666 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10670 if (type
== bgp_show_type_lcommunity_list
) {
10671 struct community_list
*list
= output_arg
;
10673 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10678 == bgp_show_type_lcommunity_list_exact
) {
10679 struct community_list
*list
= output_arg
;
10681 if (!lcommunity_list_exact_match(
10682 pi
->attr
->lcommunity
, list
))
10685 if (type
== bgp_show_type_lcommunity_all
) {
10686 if (!pi
->attr
->lcommunity
)
10689 if (type
== bgp_show_type_dampend_paths
10690 || type
== bgp_show_type_damp_neighbor
) {
10691 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10692 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10696 if (!use_json
&& header
) {
10698 "BGP table version is %" PRIu64
10699 ", local router ID is %pI4, vrf id ",
10700 table
->version
, &bgp
->router_id
);
10701 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10702 vty_out(vty
, "%s", VRFID_NONE_STR
);
10704 vty_out(vty
, "%u", bgp
->vrf_id
);
10705 vty_out(vty
, "\n");
10706 vty_out(vty
, "Default local pref %u, ",
10707 bgp
->default_local_pref
);
10708 vty_out(vty
, "local AS %u\n", bgp
->as
);
10709 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10710 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10711 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10712 if (type
== bgp_show_type_dampend_paths
10713 || type
== bgp_show_type_damp_neighbor
)
10714 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10715 else if (type
== bgp_show_type_flap_statistics
10716 || type
== bgp_show_type_flap_neighbor
)
10717 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10719 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10720 : BGP_SHOW_HEADER
));
10723 if (rd
!= NULL
&& !display
&& !output_count
) {
10726 "Route Distinguisher: %s\n",
10729 if (type
== bgp_show_type_dampend_paths
10730 || type
== bgp_show_type_damp_neighbor
)
10731 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10732 AFI_IP
, safi
, use_json
,
10734 else if (type
== bgp_show_type_flap_statistics
10735 || type
== bgp_show_type_flap_neighbor
)
10736 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10737 AFI_IP
, safi
, use_json
,
10740 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10750 /* encode prefix */
10751 if (dest_p
->family
== AF_FLOWSPEC
) {
10752 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10755 bgp_fs_nlri_get_string(
10757 dest_p
->u
.prefix_flowspec
.ptr
,
10758 dest_p
->u
.prefix_flowspec
.prefixlen
,
10759 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10760 family2afi(dest_p
->u
10761 .prefix_flowspec
.family
));
10763 vty_out(vty
, "\"%s/%d\": ", retstr
,
10764 dest_p
->u
.prefix_flowspec
10767 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10768 dest_p
->u
.prefix_flowspec
10772 vty_out(vty
, "\"%pFX\": ", dest_p
);
10774 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10777 json_object_to_json_string_ext(
10778 json_paths
, JSON_C_TO_STRING_PRETTY
));
10779 json_object_free(json_paths
);
10783 json_object_free(json_paths
);
10787 output_count
+= *output_cum
;
10788 *output_cum
= output_count
;
10791 total_count
+= *total_cum
;
10792 *total_cum
= total_count
;
10796 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10800 for (i
= 0; i
< *json_header_depth
; ++i
)
10801 vty_out(vty
, " } ");
10803 vty_out(vty
, "\n");
10807 /* No route is displayed */
10808 if (output_count
== 0) {
10809 if (type
== bgp_show_type_normal
)
10811 "No BGP prefixes displayed, %ld exist\n",
10815 "\nDisplayed %ld routes and %ld total paths\n",
10816 output_count
, total_count
);
10820 return CMD_SUCCESS
;
10823 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10824 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10825 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10827 struct bgp_dest
*dest
, *next
;
10828 unsigned long output_cum
= 0;
10829 unsigned long total_cum
= 0;
10830 unsigned long json_header_depth
= 0;
10831 struct bgp_table
*itable
;
10833 uint8_t show_flags
= 0;
10835 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10838 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10840 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10841 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10843 next
= bgp_route_next(dest
);
10844 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10847 itable
= bgp_dest_get_bgp_table_info(dest
);
10848 if (itable
!= NULL
) {
10849 struct prefix_rd prd
;
10850 char rd
[RD_ADDRSTRLEN
];
10852 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10853 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10854 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10855 rd
, next
== NULL
, &output_cum
,
10856 &total_cum
, &json_header_depth
,
10863 if (output_cum
== 0)
10864 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10868 "\nDisplayed %ld routes and %ld total paths\n",
10869 output_cum
, total_cum
);
10871 return CMD_SUCCESS
;
10873 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10874 enum bgp_show_type type
, void *output_arg
,
10875 uint8_t show_flags
)
10877 struct bgp_table
*table
;
10878 unsigned long json_header_depth
= 0;
10879 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10882 bgp
= bgp_get_default();
10887 vty_out(vty
, "No BGP process is configured\n");
10889 vty_out(vty
, "{}\n");
10890 return CMD_WARNING
;
10893 table
= bgp
->rib
[afi
][safi
];
10894 /* use MPLS and ENCAP specific shows until they are merged */
10895 if (safi
== SAFI_MPLS_VPN
) {
10896 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10897 output_arg
, use_json
);
10900 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10901 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10902 output_arg
, use_json
,
10905 /* labeled-unicast routes live in the unicast table */
10906 else if (safi
== SAFI_LABELED_UNICAST
)
10907 safi
= SAFI_UNICAST
;
10909 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10910 NULL
, NULL
, &json_header_depth
, show_flags
);
10913 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10914 safi_t safi
, uint8_t show_flags
)
10916 struct listnode
*node
, *nnode
;
10919 bool route_output
= false;
10920 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10923 vty_out(vty
, "{\n");
10925 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10926 route_output
= true;
10929 vty_out(vty
, ",\n");
10933 vty_out(vty
, "\"%s\":",
10934 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10938 vty_out(vty
, "\nInstance %s:\n",
10939 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10943 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10948 vty_out(vty
, "}\n");
10949 else if (!route_output
)
10950 vty_out(vty
, "%% BGP instance not found\n");
10953 /* Header of detailed BGP route information */
10954 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10955 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10956 afi_t afi
, safi_t safi
, json_object
*json
)
10958 struct bgp_path_info
*pi
;
10959 const struct prefix
*p
;
10961 struct listnode
*node
, *nnode
;
10962 char buf1
[RD_ADDRSTRLEN
];
10963 char prefix_str
[BUFSIZ
];
10967 int accept_own
= 0;
10968 int route_filter_translated_v4
= 0;
10969 int route_filter_v4
= 0;
10970 int route_filter_translated_v6
= 0;
10971 int route_filter_v6
= 0;
10972 int llgr_stale
= 0;
10974 int accept_own_nexthop
= 0;
10977 int no_advertise
= 0;
10981 int has_valid_label
= 0;
10982 mpls_label_t label
= 0;
10983 json_object
*json_adv_to
= NULL
;
10985 p
= bgp_dest_get_prefix(dest
);
10986 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
10988 if (has_valid_label
)
10989 label
= label_pton(&dest
->local_label
);
10991 if (safi
== SAFI_EVPN
) {
10994 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
10995 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10997 prd
? ":" : "", (struct prefix_evpn
*)p
);
10999 json_object_string_add(json
, "rd",
11000 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11002 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11006 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11007 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11008 ? prefix_rd2str(prd
, buf1
,
11011 safi
== SAFI_MPLS_VPN
? ":" : "", p
);
11014 json_object_string_add(json
, "prefix",
11015 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11018 if (has_valid_label
) {
11020 json_object_int_add(json
, "localLabel", label
);
11022 vty_out(vty
, "Local label: %d\n", label
);
11026 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11027 vty_out(vty
, "not allocated\n");
11029 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11031 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11033 if (bgp_path_suppressed(pi
))
11036 if (pi
->attr
->community
== NULL
)
11039 no_advertise
+= community_include(
11040 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11041 no_export
+= community_include(pi
->attr
->community
,
11042 COMMUNITY_NO_EXPORT
);
11043 local_as
+= community_include(pi
->attr
->community
,
11044 COMMUNITY_LOCAL_AS
);
11045 accept_own
+= community_include(pi
->attr
->community
,
11046 COMMUNITY_ACCEPT_OWN
);
11047 route_filter_translated_v4
+= community_include(
11048 pi
->attr
->community
,
11049 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11050 route_filter_translated_v6
+= community_include(
11051 pi
->attr
->community
,
11052 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11053 route_filter_v4
+= community_include(
11054 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11055 route_filter_v6
+= community_include(
11056 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11057 llgr_stale
+= community_include(pi
->attr
->community
,
11058 COMMUNITY_LLGR_STALE
);
11059 no_llgr
+= community_include(pi
->attr
->community
,
11060 COMMUNITY_NO_LLGR
);
11061 accept_own_nexthop
+=
11062 community_include(pi
->attr
->community
,
11063 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11064 blackhole
+= community_include(pi
->attr
->community
,
11065 COMMUNITY_BLACKHOLE
);
11066 no_peer
+= community_include(pi
->attr
->community
,
11067 COMMUNITY_NO_PEER
);
11072 vty_out(vty
, "Paths: (%d available", count
);
11074 vty_out(vty
, ", best #%d", best
);
11075 if (safi
== SAFI_UNICAST
) {
11076 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11077 vty_out(vty
, ", table %s",
11080 vty_out(vty
, ", vrf %s",
11084 vty_out(vty
, ", no best path");
11088 ", accept own local route exported and imported in different VRF");
11089 else if (route_filter_translated_v4
)
11091 ", mark translated RTs for VPNv4 route filtering");
11092 else if (route_filter_v4
)
11094 ", attach RT as-is for VPNv4 route filtering");
11095 else if (route_filter_translated_v6
)
11097 ", mark translated RTs for VPNv6 route filtering");
11098 else if (route_filter_v6
)
11100 ", attach RT as-is for VPNv6 route filtering");
11101 else if (llgr_stale
)
11103 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11106 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11107 else if (accept_own_nexthop
)
11109 ", accept local nexthop");
11110 else if (blackhole
)
11111 vty_out(vty
, ", inform peer to blackhole prefix");
11112 else if (no_export
)
11113 vty_out(vty
, ", not advertised to EBGP peer");
11114 else if (no_advertise
)
11115 vty_out(vty
, ", not advertised to any peer");
11117 vty_out(vty
, ", not advertised outside local AS");
11120 ", inform EBGP peer not to advertise to their EBGP peers");
11124 ", Advertisements suppressed by an aggregate.");
11125 vty_out(vty
, ")\n");
11128 /* If we are not using addpath then we can display Advertised to and
11130 * show what peers we advertised the bestpath to. If we are using
11132 * though then we must display Advertised to on a path-by-path basis. */
11133 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11134 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11135 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11136 if (json
&& !json_adv_to
)
11137 json_adv_to
= json_object_new_object();
11139 route_vty_out_advertised_to(
11141 " Advertised to non peer-group peers:\n ",
11148 json_object_object_add(json
, "advertisedTo",
11153 vty_out(vty
, " Not advertised to any peer");
11154 vty_out(vty
, "\n");
11159 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11160 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11161 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11162 json_object
*json
, enum bgp_path_type pathtype
,
11165 struct bgp_path_info
*pi
;
11167 char rdbuf
[RD_ADDRSTRLEN
];
11168 json_object
*json_header
= NULL
;
11169 json_object
*json_paths
= NULL
;
11171 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11173 if (json
&& !json_paths
) {
11174 /* Instantiate json_paths only if path is valid */
11175 json_paths
= json_object_new_array();
11177 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11178 json_header
= json_object_new_object();
11180 json_header
= json
;
11184 route_vty_out_detail_header(
11185 vty
, bgp
, bgp_node
, pfx_rd
,
11186 AFI_IP
, safi
, json_header
);
11191 if (pathtype
== BGP_PATH_SHOW_ALL
11192 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11193 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11194 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11195 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11196 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11197 route_vty_out_detail(vty
, bgp
, bgp_node
,
11202 if (json
&& json_paths
) {
11203 json_object_object_add(json_header
, "paths", json_paths
);
11206 json_object_object_add(json
, rdbuf
, json_header
);
11210 /* Display specified route of BGP table. */
11211 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11212 struct bgp_table
*rib
, const char *ip_str
,
11213 afi_t afi
, safi_t safi
,
11214 struct prefix_rd
*prd
, int prefix_check
,
11215 enum bgp_path_type pathtype
, bool use_json
)
11219 struct prefix match
;
11220 struct bgp_dest
*dest
;
11221 struct bgp_dest
*rm
;
11222 struct bgp_table
*table
;
11223 json_object
*json
= NULL
;
11224 json_object
*json_paths
= NULL
;
11226 /* Check IP address argument. */
11227 ret
= str2prefix(ip_str
, &match
);
11229 vty_out(vty
, "address is malformed\n");
11230 return CMD_WARNING
;
11233 match
.family
= afi2family(afi
);
11236 json
= json_object_new_object();
11238 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11239 for (dest
= bgp_table_top(rib
); dest
;
11240 dest
= bgp_route_next(dest
)) {
11241 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11243 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11245 table
= bgp_dest_get_bgp_table_info(dest
);
11249 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11252 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11254 && rm_p
->prefixlen
!= match
.prefixlen
) {
11255 bgp_dest_unlock_node(rm
);
11259 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11260 bgp
, afi
, safi
, json
, pathtype
,
11263 bgp_dest_unlock_node(rm
);
11265 } else if (safi
== SAFI_EVPN
) {
11266 struct bgp_dest
*longest_pfx
;
11267 bool is_exact_pfxlen_match
= false;
11269 for (dest
= bgp_table_top(rib
); dest
;
11270 dest
= bgp_route_next(dest
)) {
11271 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11273 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11275 table
= bgp_dest_get_bgp_table_info(dest
);
11279 longest_pfx
= NULL
;
11280 is_exact_pfxlen_match
= false;
11282 * Search through all the prefixes for a match. The
11283 * pfx's are enumerated in ascending order of pfxlens.
11284 * So, the last pfx match is the longest match. Set
11285 * is_exact_pfxlen_match when we get exact pfxlen match
11287 for (rm
= bgp_table_top(table
); rm
;
11288 rm
= bgp_route_next(rm
)) {
11289 const struct prefix
*rm_p
=
11290 bgp_dest_get_prefix(rm
);
11292 * Get prefixlen of the ip-prefix within type5
11295 if (evpn_type5_prefix_match(rm_p
, &match
)
11299 bgp_evpn_get_type5_prefixlen(
11301 if (type5_pfxlen
== match
.prefixlen
) {
11302 is_exact_pfxlen_match
= true;
11303 bgp_dest_unlock_node(rm
);
11312 if (prefix_check
&& !is_exact_pfxlen_match
)
11316 bgp_dest_lock_node(rm
);
11318 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11319 bgp
, afi
, safi
, json
, pathtype
,
11322 bgp_dest_unlock_node(rm
);
11324 } else if (safi
== SAFI_FLOWSPEC
) {
11326 json_paths
= json_object_new_array();
11328 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11329 &match
, prefix_check
,
11335 json_object_object_add(json
, "paths",
11338 json_object_free(json_paths
);
11341 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
11342 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11344 || dest_p
->prefixlen
== match
.prefixlen
) {
11345 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11346 safi
, json
, pathtype
,
11350 bgp_dest_unlock_node(dest
);
11355 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11356 json
, JSON_C_TO_STRING_PRETTY
|
11357 JSON_C_TO_STRING_NOSLASHESCAPE
));
11358 json_object_free(json
);
11361 vty_out(vty
, "%% Network not in table\n");
11362 return CMD_WARNING
;
11366 return CMD_SUCCESS
;
11369 /* Display specified route of Main RIB */
11370 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11371 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11372 int prefix_check
, enum bgp_path_type pathtype
,
11376 bgp
= bgp_get_default();
11379 vty_out(vty
, "No BGP process is configured\n");
11381 vty_out(vty
, "{}\n");
11382 return CMD_WARNING
;
11386 /* labeled-unicast routes live in the unicast table */
11387 if (safi
== SAFI_LABELED_UNICAST
)
11388 safi
= SAFI_UNICAST
;
11390 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11391 afi
, safi
, prd
, prefix_check
, pathtype
,
11395 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11396 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11397 safi_t safi
, bool uj
)
11399 struct lcommunity
*lcom
;
11404 uint8_t show_flags
= 0;
11408 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11410 b
= buffer_new(1024);
11411 for (i
= 0; i
< argc
; i
++) {
11413 buffer_putc(b
, ' ');
11415 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11417 buffer_putstr(b
, argv
[i
]->arg
);
11421 buffer_putc(b
, '\0');
11423 str
= buffer_getstr(b
);
11426 lcom
= lcommunity_str2com(str
);
11427 XFREE(MTYPE_TMP
, str
);
11429 vty_out(vty
, "%% Large-community malformed\n");
11430 return CMD_WARNING
;
11433 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11434 (exact
? bgp_show_type_lcommunity_exact
11435 : bgp_show_type_lcommunity
),
11438 lcommunity_free(&lcom
);
11442 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11443 const char *lcom
, bool exact
, afi_t afi
,
11444 safi_t safi
, bool uj
)
11446 struct community_list
*list
;
11447 uint8_t show_flags
= 0;
11450 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11453 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11454 LARGE_COMMUNITY_LIST_MASTER
);
11455 if (list
== NULL
) {
11456 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11458 return CMD_WARNING
;
11461 return bgp_show(vty
, bgp
, afi
, safi
,
11462 (exact
? bgp_show_type_lcommunity_list_exact
11463 : bgp_show_type_lcommunity_list
),
11467 DEFUN (show_ip_bgp_large_community_list
,
11468 show_ip_bgp_large_community_list_cmd
,
11469 "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]",
11473 BGP_INSTANCE_HELP_STR
11475 BGP_SAFI_WITH_LABEL_HELP_STR
11476 "Display routes matching the large-community-list\n"
11477 "large-community-list number\n"
11478 "large-community-list name\n"
11479 "Exact match of the large-communities\n"
11482 afi_t afi
= AFI_IP6
;
11483 safi_t safi
= SAFI_UNICAST
;
11485 bool exact_match
= 0;
11486 struct bgp
*bgp
= NULL
;
11487 bool uj
= use_json(argc
, argv
);
11492 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11495 return CMD_WARNING
;
11497 argv_find(argv
, argc
, "large-community-list", &idx
);
11499 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11501 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11504 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11505 exact_match
, afi
, safi
, uj
);
11507 DEFUN (show_ip_bgp_large_community
,
11508 show_ip_bgp_large_community_cmd
,
11509 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11513 BGP_INSTANCE_HELP_STR
11515 BGP_SAFI_WITH_LABEL_HELP_STR
11516 "Display routes matching the large-communities\n"
11517 "List of large-community numbers\n"
11518 "Exact match of the large-communities\n"
11521 afi_t afi
= AFI_IP6
;
11522 safi_t safi
= SAFI_UNICAST
;
11524 bool exact_match
= 0;
11525 struct bgp
*bgp
= NULL
;
11526 bool uj
= use_json(argc
, argv
);
11527 uint8_t show_flags
= 0;
11531 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11534 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11537 return CMD_WARNING
;
11539 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11540 if (argv_find(argv
, argc
, "exact-match", &idx
))
11542 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11543 exact_match
, afi
, safi
, uj
);
11545 return bgp_show(vty
, bgp
, afi
, safi
,
11546 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
11549 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11550 safi_t safi
, struct json_object
*json_array
);
11551 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11552 safi_t safi
, struct json_object
*json
);
11555 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11556 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11557 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11558 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11560 bool uj
= use_json(argc
, argv
);
11561 struct bgp
*bgp
= NULL
;
11562 safi_t safi
= SAFI_UNICAST
;
11563 afi_t afi
= AFI_IP6
;
11565 struct json_object
*json_all
= NULL
;
11566 struct json_object
*json_afi_safi
= NULL
;
11568 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11571 return CMD_WARNING
;
11574 json_all
= json_object_new_object();
11576 FOREACH_AFI_SAFI (afi
, safi
) {
11578 * So limit output to those afi/safi pairs that
11579 * actually have something interesting in them
11581 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11586 json_afi_safi
= json_object_new_array();
11587 json_object_object_add(
11589 get_afi_safi_str(afi
, safi
, true),
11592 json_afi_safi
= NULL
;
11595 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11600 json_object_to_json_string_ext(
11601 json_all
, JSON_C_TO_STRING_PRETTY
));
11602 json_object_free(json_all
);
11605 return CMD_SUCCESS
;
11608 /* BGP route print out function without JSON */
11609 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11610 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11611 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11615 BGP_INSTANCE_HELP_STR
11618 "BGP RIB advertisement statistics\n"
11621 afi_t afi
= AFI_IP6
;
11622 safi_t safi
= SAFI_UNICAST
;
11623 struct bgp
*bgp
= NULL
;
11625 bool uj
= use_json(argc
, argv
);
11626 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11628 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11631 return CMD_WARNING
;
11634 json_afi_safi
= json_object_new_array();
11636 json_afi_safi
= NULL
;
11638 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11641 json
= json_object_new_object();
11642 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11644 vty_out(vty
, "%s", json_object_to_json_string_ext(
11645 json
, JSON_C_TO_STRING_PRETTY
));
11646 json_object_free(json
);
11651 /* BGP route print out function without JSON */
11652 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11653 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11654 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11656 statistics [json]",
11657 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11658 BGP_SAFI_WITH_LABEL_HELP_STR
11659 "BGP RIB advertisement statistics\n" JSON_STR
)
11661 afi_t afi
= AFI_IP6
;
11662 safi_t safi
= SAFI_UNICAST
;
11663 struct bgp
*bgp
= NULL
;
11665 bool uj
= use_json(argc
, argv
);
11666 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11668 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11671 return CMD_WARNING
;
11674 json_afi_safi
= json_object_new_array();
11676 json_afi_safi
= NULL
;
11678 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11681 json
= json_object_new_object();
11682 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11685 json_object_to_json_string_ext(
11686 json
, JSON_C_TO_STRING_PRETTY
));
11687 json_object_free(json
);
11692 /* BGP route print out function without JSON */
11693 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11694 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11695 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11697 <[all$all] dampening <parameters>\
11701 |community-list <(1-500)|WORD> [exact-match]\
11702 |A.B.C.D/M longer-prefixes\
11703 |X:X::X:X/M longer-prefixes\
11705 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11706 BGP_SAFI_WITH_LABEL_HELP_STR
11707 "Display the entries for all address families\n"
11708 "Display detailed information about dampening\n"
11709 "Display detail of configured dampening parameters\n"
11710 "Display routes matching the route-map\n"
11711 "A route-map to match on\n"
11712 "Display routes conforming to the prefix-list\n"
11713 "Prefix-list name\n"
11714 "Display routes conforming to the filter-list\n"
11715 "Regular expression access list name\n"
11716 "Display routes matching the community-list\n"
11717 "community-list number\n"
11718 "community-list name\n"
11719 "Exact match of the communities\n"
11721 "Display route and more specific routes\n"
11723 "Display route and more specific routes\n")
11725 afi_t afi
= AFI_IP6
;
11726 safi_t safi
= SAFI_UNICAST
;
11727 int exact_match
= 0;
11728 struct bgp
*bgp
= NULL
;
11730 uint8_t show_flags
= 0;
11732 /* [<ipv4|ipv6> [all]] */
11734 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11735 if (argv_find(argv
, argc
, "ipv4", &idx
))
11736 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11738 if (argv_find(argv
, argc
, "ipv6", &idx
))
11739 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11742 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11745 return CMD_WARNING
;
11747 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11748 if (argv_find(argv
, argc
, "parameters", &idx
))
11749 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11753 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11754 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11755 safi
, bgp_show_type_prefix_list
);
11757 if (argv_find(argv
, argc
, "filter-list", &idx
))
11758 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11759 safi
, bgp_show_type_filter_list
);
11761 if (argv_find(argv
, argc
, "route-map", &idx
))
11762 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11763 safi
, bgp_show_type_route_map
);
11765 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11766 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11767 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11769 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11770 exact_match
, afi
, safi
);
11772 /* prefix-longer */
11773 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11774 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11775 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11777 bgp_show_type_prefix_longer
);
11779 return CMD_WARNING
;
11782 /* BGP route print out function with JSON */
11783 DEFPY (show_ip_bgp_json
,
11784 show_ip_bgp_json_cmd
,
11785 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11788 |dampening <flap-statistics|dampened-paths>\
11789 |community [AA:NN|local-AS|no-advertise|no-export\
11790 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11791 |accept-own|accept-own-nexthop|route-filter-v6\
11792 |route-filter-v4|route-filter-translated-v6\
11793 |route-filter-translated-v4] [exact-match]\
11794 ] [json$uj | wide$wide]",
11798 BGP_INSTANCE_HELP_STR
11800 BGP_SAFI_WITH_LABEL_HELP_STR
11801 "Display the entries for all address families\n"
11802 "Display only routes with non-natural netmasks\n"
11803 "Display detailed information about dampening\n"
11804 "Display flap statistics of routes\n"
11805 "Display paths suppressed due to dampening\n"
11806 "Display routes matching the communities\n"
11808 "Do not send outside local AS (well-known community)\n"
11809 "Do not advertise to any peer (well-known community)\n"
11810 "Do not export to next AS (well-known community)\n"
11811 "Graceful shutdown (well-known community)\n"
11812 "Do not export to any peer (well-known community)\n"
11813 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11814 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11815 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11816 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11817 "Should accept VPN route with local nexthop (well-known community)\n"
11818 "RT VPNv6 route filtering (well-known community)\n"
11819 "RT VPNv4 route filtering (well-known community)\n"
11820 "RT translated VPNv6 route filtering (well-known community)\n"
11821 "RT translated VPNv4 route filtering (well-known community)\n"
11822 "Exact match of the communities\n"
11824 "Increase table width for longer prefixes\n")
11826 afi_t afi
= AFI_IP6
;
11827 safi_t safi
= SAFI_UNICAST
;
11828 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11829 struct bgp
*bgp
= NULL
;
11831 int exact_match
= 0;
11832 char *community
= NULL
;
11834 uint8_t show_flags
= 0;
11839 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11842 /* [<ipv4|ipv6> [all]] */
11844 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11846 if (argv_find(argv
, argc
, "ipv4", &idx
))
11847 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11849 if (argv_find(argv
, argc
, "ipv6", &idx
))
11850 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11854 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11856 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11859 return CMD_WARNING
;
11861 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11862 sh_type
= bgp_show_type_cidr_only
;
11864 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11865 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11866 sh_type
= bgp_show_type_dampend_paths
;
11867 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11868 sh_type
= bgp_show_type_flap_statistics
;
11871 if (argv_find(argv
, argc
, "community", &idx
)) {
11872 char *maybecomm
= NULL
;
11874 if (idx
+ 1 < argc
) {
11875 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11876 maybecomm
= argv
[idx
+ 1]->arg
;
11878 maybecomm
= argv
[idx
+ 1]->text
;
11881 if (maybecomm
&& !strmatch(maybecomm
, "json")
11882 && !strmatch(maybecomm
, "exact-match"))
11883 community
= maybecomm
;
11885 if (argv_find(argv
, argc
, "exact-match", &idx
))
11889 sh_type
= bgp_show_type_community_all
;
11893 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11895 return bgp_show_community(vty
, bgp
, community
,
11896 exact_match
, afi
, safi
,
11899 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11902 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11906 vty_out(vty
, "{\n");
11908 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11909 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11910 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11913 FOREACH_SAFI (safi
) {
11914 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11921 vty_out(vty
, ",\n");
11922 vty_out(vty
, "\"%s\":{\n",
11923 get_afi_safi_str(afi
, safi
,
11927 "\nFor address family: %s\n",
11928 get_afi_safi_str(afi
, safi
,
11932 bgp_show_community(vty
, bgp
, community
,
11936 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11939 vty_out(vty
, "}\n");
11942 /* show <ip> bgp all: for each AFI and SAFI*/
11943 FOREACH_AFI_SAFI (afi
, safi
) {
11944 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11951 vty_out(vty
, ",\n");
11953 vty_out(vty
, "\"%s\":{\n",
11954 get_afi_safi_str(afi
, safi
,
11958 "\nFor address family: %s\n",
11959 get_afi_safi_str(afi
, safi
,
11963 bgp_show_community(vty
, bgp
, community
,
11967 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11970 vty_out(vty
, "}\n");
11974 vty_out(vty
, "}\n");
11976 return CMD_SUCCESS
;
11979 DEFUN (show_ip_bgp_route
,
11980 show_ip_bgp_route_cmd
,
11981 "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]",
11985 BGP_INSTANCE_HELP_STR
11987 BGP_SAFI_WITH_LABEL_HELP_STR
11988 "Network in the BGP routing table to display\n"
11990 "Network in the BGP routing table to display\n"
11992 "Display only the bestpath\n"
11993 "Display only multipaths\n"
11996 int prefix_check
= 0;
11998 afi_t afi
= AFI_IP6
;
11999 safi_t safi
= SAFI_UNICAST
;
12000 char *prefix
= NULL
;
12001 struct bgp
*bgp
= NULL
;
12002 enum bgp_path_type path_type
;
12003 bool uj
= use_json(argc
, argv
);
12007 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12010 return CMD_WARNING
;
12014 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12015 return CMD_WARNING
;
12018 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12019 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12020 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12022 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12023 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12026 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12027 && afi
!= AFI_IP6
) {
12029 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12030 return CMD_WARNING
;
12032 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12033 && afi
!= AFI_IP
) {
12035 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12036 return CMD_WARNING
;
12039 prefix
= argv
[idx
]->arg
;
12041 /* [<bestpath|multipath>] */
12042 if (argv_find(argv
, argc
, "bestpath", &idx
))
12043 path_type
= BGP_PATH_SHOW_BESTPATH
;
12044 else if (argv_find(argv
, argc
, "multipath", &idx
))
12045 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12047 path_type
= BGP_PATH_SHOW_ALL
;
12049 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12053 DEFUN (show_ip_bgp_regexp
,
12054 show_ip_bgp_regexp_cmd
,
12055 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12059 BGP_INSTANCE_HELP_STR
12061 BGP_SAFI_WITH_LABEL_HELP_STR
12062 "Display routes matching the AS path regular expression\n"
12063 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12066 afi_t afi
= AFI_IP6
;
12067 safi_t safi
= SAFI_UNICAST
;
12068 struct bgp
*bgp
= NULL
;
12069 bool uj
= use_json(argc
, argv
);
12070 char *regstr
= NULL
;
12073 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12076 return CMD_WARNING
;
12078 // get index of regex
12079 if (argv_find(argv
, argc
, "REGEX", &idx
))
12080 regstr
= argv
[idx
]->arg
;
12083 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12084 bgp_show_type_regexp
, uj
);
12087 DEFPY (show_ip_bgp_instance_all
,
12088 show_ip_bgp_instance_all_cmd
,
12089 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12093 BGP_INSTANCE_ALL_HELP_STR
12095 BGP_SAFI_WITH_LABEL_HELP_STR
12097 "Increase table width for longer prefixes\n")
12099 afi_t afi
= AFI_IP
;
12100 safi_t safi
= SAFI_UNICAST
;
12101 struct bgp
*bgp
= NULL
;
12103 uint8_t show_flags
= 0;
12107 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12111 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12113 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12116 return CMD_WARNING
;
12118 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12119 return CMD_SUCCESS
;
12122 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12123 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12128 uint8_t show_flags
= 0;
12131 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12133 if (!config_bgp_aspath_validate(regstr
)) {
12134 vty_out(vty
, "Invalid character in REGEX %s\n",
12136 return CMD_WARNING_CONFIG_FAILED
;
12139 regex
= bgp_regcomp(regstr
);
12141 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12142 return CMD_WARNING
;
12145 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
12146 bgp_regex_free(regex
);
12150 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12151 const char *prefix_list_str
, afi_t afi
,
12152 safi_t safi
, enum bgp_show_type type
)
12154 struct prefix_list
*plist
;
12155 uint8_t show_flags
= 0;
12157 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12158 if (plist
== NULL
) {
12159 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12161 return CMD_WARNING
;
12164 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
12167 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12168 const char *filter
, afi_t afi
, safi_t safi
,
12169 enum bgp_show_type type
)
12171 struct as_list
*as_list
;
12172 uint8_t show_flags
= 0;
12174 as_list
= as_list_lookup(filter
);
12175 if (as_list
== NULL
) {
12176 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12178 return CMD_WARNING
;
12181 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
12184 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12185 const char *rmap_str
, afi_t afi
, safi_t safi
,
12186 enum bgp_show_type type
)
12188 struct route_map
*rmap
;
12189 uint8_t show_flags
= 0;
12191 rmap
= route_map_lookup_by_name(rmap_str
);
12193 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12194 return CMD_WARNING
;
12197 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
12200 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12201 const char *comstr
, int exact
, afi_t afi
,
12202 safi_t safi
, uint8_t show_flags
)
12204 struct community
*com
;
12207 com
= community_str2com(comstr
);
12209 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12210 return CMD_WARNING
;
12213 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12214 (exact
? bgp_show_type_community_exact
12215 : bgp_show_type_community
),
12217 community_free(&com
);
12222 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12223 const char *com
, int exact
, afi_t afi
,
12226 struct community_list
*list
;
12227 uint8_t show_flags
= 0;
12229 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12230 if (list
== NULL
) {
12231 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12232 return CMD_WARNING
;
12235 return bgp_show(vty
, bgp
, afi
, safi
,
12236 (exact
? bgp_show_type_community_list_exact
12237 : bgp_show_type_community_list
),
12241 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12242 const char *prefix
, afi_t afi
, safi_t safi
,
12243 enum bgp_show_type type
)
12247 uint8_t show_flags
= 0;
12251 ret
= str2prefix(prefix
, p
);
12253 vty_out(vty
, "%% Malformed Prefix\n");
12254 return CMD_WARNING
;
12257 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
12263 BGP_STATS_MAXBITLEN
= 0,
12265 BGP_STATS_PREFIXES
,
12267 BGP_STATS_UNAGGREGATEABLE
,
12268 BGP_STATS_MAX_AGGREGATEABLE
,
12269 BGP_STATS_AGGREGATES
,
12271 BGP_STATS_ASPATH_COUNT
,
12272 BGP_STATS_ASPATH_MAXHOPS
,
12273 BGP_STATS_ASPATH_TOTHOPS
,
12274 BGP_STATS_ASPATH_MAXSIZE
,
12275 BGP_STATS_ASPATH_TOTSIZE
,
12276 BGP_STATS_ASN_HIGHEST
,
12280 #define TABLE_STATS_IDX_VTY 0
12281 #define TABLE_STATS_IDX_JSON 1
12283 static const char *table_stats_strs
[][2] = {
12284 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12285 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12286 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12287 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12288 "unaggregateablePrefixes"},
12289 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12290 "maximumAggregateablePrefixes"},
12291 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12292 "bgpAggregateAdvertisements"},
12293 [BGP_STATS_SPACE
] = {"Address space advertised",
12294 "addressSpaceAdvertised"},
12295 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12296 "advertisementsWithPaths"},
12297 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12299 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12301 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12302 "averageAsPathLengthHops"},
12303 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12304 "averageAsPathSizeBytes"},
12305 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12306 [BGP_STATS_MAX
] = {NULL
, NULL
}
12309 struct bgp_table_stats
{
12310 struct bgp_table
*table
;
12311 unsigned long long counts
[BGP_STATS_MAX
];
12312 double total_space
;
12315 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12316 struct bgp_table_stats
*ts
, unsigned int space
)
12318 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12319 struct bgp_path_info
*pi
;
12320 const struct prefix
*rn_p
;
12322 if (!bgp_dest_has_bgp_path_info_data(dest
))
12325 rn_p
= bgp_dest_get_prefix(dest
);
12326 ts
->counts
[BGP_STATS_PREFIXES
]++;
12327 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12329 /* check if the prefix is included by any other announcements */
12330 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12331 pdest
= bgp_dest_parent_nolock(pdest
);
12333 if (pdest
== NULL
|| pdest
== top
) {
12334 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12335 /* announced address space */
12337 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12338 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12339 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12342 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12343 ts
->counts
[BGP_STATS_RIB
]++;
12345 if (CHECK_FLAG(pi
->attr
->flag
,
12346 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12347 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12349 /* as-path stats */
12350 if (pi
->attr
->aspath
) {
12351 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12352 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12353 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12355 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12357 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12358 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12360 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12361 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12363 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12364 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12365 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12366 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12371 static int bgp_table_stats_walker(struct thread
*t
)
12373 struct bgp_dest
*dest
, *ndest
;
12374 struct bgp_dest
*top
;
12375 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12376 unsigned int space
= 0;
12378 if (!(top
= bgp_table_top(ts
->table
)))
12381 switch (ts
->table
->afi
) {
12383 space
= IPV4_MAX_BITLEN
;
12386 space
= IPV6_MAX_BITLEN
;
12392 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12394 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12395 if (ts
->table
->safi
== SAFI_MPLS_VPN
12396 || ts
->table
->safi
== SAFI_ENCAP
12397 || ts
->table
->safi
== SAFI_EVPN
) {
12398 struct bgp_table
*table
;
12400 table
= bgp_dest_get_bgp_table_info(dest
);
12404 top
= bgp_table_top(table
);
12405 for (ndest
= bgp_table_top(table
); ndest
;
12406 ndest
= bgp_route_next(ndest
))
12407 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12409 bgp_table_stats_rn(dest
, top
, ts
, space
);
12416 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12417 struct json_object
*json_array
)
12419 struct listnode
*node
, *nnode
;
12422 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12423 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12426 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12427 safi_t safi
, struct json_object
*json_array
)
12429 struct bgp_table_stats ts
;
12431 int ret
= CMD_SUCCESS
;
12433 struct json_object
*json
= NULL
;
12436 json
= json_object_new_object();
12438 if (!bgp
->rib
[afi
][safi
]) {
12439 char warning_msg
[50];
12441 snprintf(warning_msg
, sizeof(warning_msg
),
12442 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12446 vty_out(vty
, "%s\n", warning_msg
);
12448 json_object_string_add(json
, "warning", warning_msg
);
12451 goto end_table_stats
;
12455 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12456 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12458 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12460 /* labeled-unicast routes live in the unicast table */
12461 if (safi
== SAFI_LABELED_UNICAST
)
12462 safi
= SAFI_UNICAST
;
12464 memset(&ts
, 0, sizeof(ts
));
12465 ts
.table
= bgp
->rib
[afi
][safi
];
12466 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12468 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12469 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12470 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12474 case BGP_STATS_ASPATH_TOTHOPS
:
12475 case BGP_STATS_ASPATH_TOTSIZE
:
12478 temp_buf
, sizeof(temp_buf
), "%12.2f",
12480 ? (float)ts
.counts
[i
]
12482 [BGP_STATS_ASPATH_COUNT
]
12484 vty_out(vty
, "%-30s: %s",
12485 table_stats_strs
[i
]
12486 [TABLE_STATS_IDX_VTY
],
12489 json_object_double_add(
12491 table_stats_strs
[i
]
12492 [TABLE_STATS_IDX_JSON
],
12494 ? (double)ts
.counts
[i
]
12495 / (double)ts
.counts
12496 [BGP_STATS_ASPATH_COUNT
]
12500 case BGP_STATS_TOTPLEN
:
12503 temp_buf
, sizeof(temp_buf
), "%12.2f",
12505 ? (float)ts
.counts
[i
]
12507 [BGP_STATS_PREFIXES
]
12509 vty_out(vty
, "%-30s: %s",
12510 table_stats_strs
[i
]
12511 [TABLE_STATS_IDX_VTY
],
12514 json_object_double_add(
12516 table_stats_strs
[i
]
12517 [TABLE_STATS_IDX_JSON
],
12519 ? (double)ts
.counts
[i
]
12520 / (double)ts
.counts
12521 [BGP_STATS_PREFIXES
]
12525 case BGP_STATS_SPACE
:
12527 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12529 vty_out(vty
, "%-30s: %s\n",
12530 table_stats_strs
[i
]
12531 [TABLE_STATS_IDX_VTY
],
12534 json_object_double_add(
12536 table_stats_strs
[i
]
12537 [TABLE_STATS_IDX_JSON
],
12538 (double)ts
.total_space
);
12540 if (afi
== AFI_IP6
) {
12542 snprintf(temp_buf
, sizeof(temp_buf
),
12545 * pow(2.0, -128 + 32));
12546 vty_out(vty
, "%30s: %s\n",
12547 "/32 equivalent %s\n",
12550 json_object_double_add(
12551 json
, "/32equivalent",
12552 (double)(ts
.total_space
12557 snprintf(temp_buf
, sizeof(temp_buf
),
12560 * pow(2.0, -128 + 48));
12561 vty_out(vty
, "%30s: %s\n",
12562 "/48 equivalent %s\n",
12565 json_object_double_add(
12566 json
, "/48equivalent",
12567 (double)(ts
.total_space
12573 snprintf(temp_buf
, sizeof(temp_buf
),
12575 ts
.total_space
* 100.
12577 vty_out(vty
, "%30s: %s\n",
12578 "% announced ", temp_buf
);
12580 json_object_double_add(
12581 json
, "%announced",
12582 (double)(ts
.total_space
* 100.
12586 snprintf(temp_buf
, sizeof(temp_buf
),
12589 * pow(2.0, -32 + 8));
12590 vty_out(vty
, "%30s: %s\n",
12591 "/8 equivalent ", temp_buf
);
12593 json_object_double_add(
12594 json
, "/8equivalent",
12595 (double)(ts
.total_space
12596 * pow(2.0, -32 + 8)));
12599 snprintf(temp_buf
, sizeof(temp_buf
),
12602 * pow(2.0, -32 + 24));
12603 vty_out(vty
, "%30s: %s\n",
12604 "/24 equivalent ", temp_buf
);
12606 json_object_double_add(
12607 json
, "/24equivalent",
12608 (double)(ts
.total_space
12609 * pow(2.0, -32 + 24)));
12615 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12617 vty_out(vty
, "%-30s: %s",
12618 table_stats_strs
[i
]
12619 [TABLE_STATS_IDX_VTY
],
12622 json_object_int_add(
12624 table_stats_strs
[i
]
12625 [TABLE_STATS_IDX_JSON
],
12630 vty_out(vty
, "\n");
12634 json_object_array_add(json_array
, json
);
12638 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12639 safi_t safi
, struct json_object
*json_array
)
12642 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12643 return CMD_SUCCESS
;
12646 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12658 PCOUNT_BPATH_SELECTED
,
12659 PCOUNT_PFCNT
, /* the figure we display to users */
12663 static const char *const pcount_strs
[] = {
12664 [PCOUNT_ADJ_IN
] = "Adj-in",
12665 [PCOUNT_DAMPED
] = "Damped",
12666 [PCOUNT_REMOVED
] = "Removed",
12667 [PCOUNT_HISTORY
] = "History",
12668 [PCOUNT_STALE
] = "Stale",
12669 [PCOUNT_VALID
] = "Valid",
12670 [PCOUNT_ALL
] = "All RIB",
12671 [PCOUNT_COUNTED
] = "PfxCt counted",
12672 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12673 [PCOUNT_PFCNT
] = "Useable",
12674 [PCOUNT_MAX
] = NULL
,
12677 struct peer_pcounts
{
12678 unsigned int count
[PCOUNT_MAX
];
12679 const struct peer
*peer
;
12680 const struct bgp_table
*table
;
12684 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12686 const struct bgp_adj_in
*ain
;
12687 const struct bgp_path_info
*pi
;
12688 const struct peer
*peer
= pc
->peer
;
12690 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12691 if (ain
->peer
== peer
)
12692 pc
->count
[PCOUNT_ADJ_IN
]++;
12694 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12696 if (pi
->peer
!= peer
)
12699 pc
->count
[PCOUNT_ALL
]++;
12701 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12702 pc
->count
[PCOUNT_DAMPED
]++;
12703 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12704 pc
->count
[PCOUNT_HISTORY
]++;
12705 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12706 pc
->count
[PCOUNT_REMOVED
]++;
12707 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12708 pc
->count
[PCOUNT_STALE
]++;
12709 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12710 pc
->count
[PCOUNT_VALID
]++;
12711 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12712 pc
->count
[PCOUNT_PFCNT
]++;
12713 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12714 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12716 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12717 pc
->count
[PCOUNT_COUNTED
]++;
12718 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12720 EC_LIB_DEVELOPMENT
,
12721 "Attempting to count but flags say it is unusable");
12723 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12725 EC_LIB_DEVELOPMENT
,
12726 "Not counted but flags say we should");
12731 static int bgp_peer_count_walker(struct thread
*t
)
12733 struct bgp_dest
*rn
, *rm
;
12734 const struct bgp_table
*table
;
12735 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12737 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12738 || pc
->safi
== SAFI_EVPN
) {
12739 /* Special handling for 2-level routing tables. */
12740 for (rn
= bgp_table_top(pc
->table
); rn
;
12741 rn
= bgp_route_next(rn
)) {
12742 table
= bgp_dest_get_bgp_table_info(rn
);
12744 for (rm
= bgp_table_top(table
); rm
;
12745 rm
= bgp_route_next(rm
))
12746 bgp_peer_count_proc(rm
, pc
);
12749 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
12750 bgp_peer_count_proc(rn
, pc
);
12755 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12756 safi_t safi
, bool use_json
)
12758 struct peer_pcounts pcounts
= {.peer
= peer
};
12760 json_object
*json
= NULL
;
12761 json_object
*json_loop
= NULL
;
12764 json
= json_object_new_object();
12765 json_loop
= json_object_new_object();
12768 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
12769 || !peer
->bgp
->rib
[afi
][safi
]) {
12771 json_object_string_add(
12773 "No such neighbor or address family");
12774 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12775 json_object_free(json
);
12776 json_object_free(json_loop
);
12778 vty_out(vty
, "%% No such neighbor or address family\n");
12780 return CMD_WARNING
;
12783 memset(&pcounts
, 0, sizeof(pcounts
));
12784 pcounts
.peer
= peer
;
12785 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
12786 pcounts
.safi
= safi
;
12788 /* in-place call via thread subsystem so as to record execution time
12789 * stats for the thread-walk (i.e. ensure this can't be blamed on
12790 * on just vty_read()).
12792 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
12795 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
12796 json_object_string_add(json
, "multiProtocol",
12797 get_afi_safi_str(afi
, safi
, true));
12798 json_object_int_add(json
, "pfxCounter",
12799 peer
->pcount
[afi
][safi
]);
12801 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12802 json_object_int_add(json_loop
, pcount_strs
[i
],
12805 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12807 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12808 json_object_string_add(json
, "pfxctDriftFor",
12810 json_object_string_add(
12811 json
, "recommended",
12812 "Please report this bug, with the above command output");
12814 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12815 json
, JSON_C_TO_STRING_PRETTY
));
12816 json_object_free(json
);
12820 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12821 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12822 peer
->hostname
, peer
->host
,
12823 get_afi_safi_str(afi
, safi
, false));
12825 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12826 get_afi_safi_str(afi
, safi
, false));
12829 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12830 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12832 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12833 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12836 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12837 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12839 "Please report this bug, with the above command output\n");
12843 return CMD_SUCCESS
;
12846 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12847 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12848 "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]",
12852 BGP_INSTANCE_HELP_STR
12855 "Detailed information on TCP and BGP neighbor connections\n"
12856 "Neighbor to display information about\n"
12857 "Neighbor to display information about\n"
12858 "Neighbor on BGP configured interface\n"
12859 "Display detailed prefix count information\n"
12862 afi_t afi
= AFI_IP6
;
12863 safi_t safi
= SAFI_UNICAST
;
12866 struct bgp
*bgp
= NULL
;
12867 bool uj
= use_json(argc
, argv
);
12872 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12875 return CMD_WARNING
;
12877 argv_find(argv
, argc
, "neighbors", &idx
);
12878 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12880 return CMD_WARNING
;
12882 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12885 #ifdef KEEP_OLD_VPN_COMMANDS
12886 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12887 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12888 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12893 "Display information about all VPNv4 NLRIs\n"
12894 "Detailed information on TCP and BGP neighbor connections\n"
12895 "Neighbor to display information about\n"
12896 "Neighbor to display information about\n"
12897 "Neighbor on BGP configured interface\n"
12898 "Display detailed prefix count information\n"
12903 bool uj
= use_json(argc
, argv
);
12905 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12907 return CMD_WARNING
;
12909 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12912 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12913 show_ip_bgp_vpn_all_route_prefix_cmd
,
12914 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12919 "Display information about all VPNv4 NLRIs\n"
12920 "Network in the BGP routing table to display\n"
12921 "Network in the BGP routing table to display\n"
12925 char *network
= NULL
;
12926 struct bgp
*bgp
= bgp_get_default();
12928 vty_out(vty
, "Can't find default instance\n");
12929 return CMD_WARNING
;
12932 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12933 network
= argv
[idx
]->arg
;
12934 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12935 network
= argv
[idx
]->arg
;
12937 vty_out(vty
, "Unable to figure out Network\n");
12938 return CMD_WARNING
;
12941 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12942 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12944 #endif /* KEEP_OLD_VPN_COMMANDS */
12946 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12947 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12948 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
12953 "Network in the BGP routing table to display\n"
12954 "Network in the BGP routing table to display\n"
12955 "Network in the BGP routing table to display\n"
12956 "Network in the BGP routing table to display\n"
12960 char *network
= NULL
;
12961 int prefix_check
= 0;
12963 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
12964 argv_find(argv
, argc
, "X:X::X:X", &idx
))
12965 network
= argv
[idx
]->arg
;
12966 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
12967 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
12968 network
= argv
[idx
]->arg
;
12971 vty_out(vty
, "Unable to figure out Network\n");
12972 return CMD_WARNING
;
12974 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
12975 prefix_check
, BGP_PATH_SHOW_ALL
,
12976 use_json(argc
, argv
));
12979 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
12980 struct bgp_table
*table
, int *header1
,
12981 int *header2
, json_object
*json
,
12982 json_object
*json_scode
,
12983 json_object
*json_ocode
, bool wide
)
12985 uint64_t version
= table
? table
->version
: 0;
12986 char buf
[BUFSIZ
] = {0};
12990 json_object_int_add(json
, "bgpTableVersion", version
);
12991 json_object_string_add(json
, "bgpLocalRouterId",
12993 &bgp
->router_id
, buf
,
12995 json_object_int_add(json
, "defaultLocPrf",
12996 bgp
->default_local_pref
);
12997 json_object_int_add(json
, "localAS", bgp
->as
);
12998 json_object_object_add(json
, "bgpStatusCodes",
13000 json_object_object_add(json
, "bgpOriginCodes",
13004 "BGP table version is %" PRIu64
13005 ", local router ID is %pI4, vrf id ",
13006 version
, &bgp
->router_id
);
13007 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13008 vty_out(vty
, "%s", VRFID_NONE_STR
);
13010 vty_out(vty
, "%u", bgp
->vrf_id
);
13011 vty_out(vty
, "\n");
13012 vty_out(vty
, "Default local pref %u, ",
13013 bgp
->default_local_pref
);
13014 vty_out(vty
, "local AS %u\n", bgp
->as
);
13015 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13016 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13017 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13023 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13024 : BGP_SHOW_HEADER
));
13030 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13031 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13032 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13033 json_object
*json_scode
, json_object
*json_ocode
,
13034 uint8_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13035 unsigned long *output_count
, unsigned long *filtered_count
)
13037 struct bgp_adj_in
*ain
;
13038 struct bgp_adj_out
*adj
;
13039 struct bgp_dest
*dest
;
13043 struct update_subgroup
*subgrp
;
13044 struct peer_af
*paf
;
13045 bool route_filtered
;
13046 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13047 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13048 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13049 || (safi
== SAFI_EVPN
))
13057 json_object_string_add(json
, "alert", "no BGP");
13058 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13059 json_object_free(json
);
13061 vty_out(vty
, "%% No bgp\n");
13065 subgrp
= peer_subgroup(peer
, afi
, safi
);
13067 if (type
== bgp_show_adj_route_advertised
&& subgrp
13068 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13069 char buf
[BUFSIZ
] = {0};
13072 json_object_int_add(json
, "bgpTableVersion",
13074 json_object_string_add(json
, "bgpLocalRouterId",
13076 &bgp
->router_id
, buf
,
13078 json_object_int_add(json
, "defaultLocPrf",
13079 bgp
->default_local_pref
);
13080 json_object_int_add(json
, "localAS", bgp
->as
);
13081 json_object_object_add(json
, "bgpStatusCodes",
13083 json_object_object_add(json
, "bgpOriginCodes",
13085 json_object_string_add(
13086 json
, "bgpOriginatingDefaultNetwork",
13087 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13090 "BGP table version is %" PRIu64
13091 ", local router ID is %pI4, vrf id ",
13092 table
->version
, &bgp
->router_id
);
13093 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13094 vty_out(vty
, "%s", VRFID_NONE_STR
);
13096 vty_out(vty
, "%u", bgp
->vrf_id
);
13097 vty_out(vty
, "\n");
13098 vty_out(vty
, "Default local pref %u, ",
13099 bgp
->default_local_pref
);
13100 vty_out(vty
, "local AS %u\n", bgp
->as
);
13101 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13102 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13103 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13105 vty_out(vty
, "Originating default network %s\n\n",
13106 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13111 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13112 if (type
== bgp_show_adj_route_received
13113 || type
== bgp_show_adj_route_filtered
) {
13114 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13115 if (ain
->peer
!= peer
)
13118 show_adj_route_header(vty
, bgp
, table
, header1
,
13119 header2
, json
, json_scode
,
13122 if ((safi
== SAFI_MPLS_VPN
)
13123 || (safi
== SAFI_ENCAP
)
13124 || (safi
== SAFI_EVPN
)) {
13126 json_object_string_add(
13127 json_ar
, "rd", rd_str
);
13128 else if (show_rd
&& rd_str
) {
13130 "Route Distinguisher: %s\n",
13137 route_filtered
= false;
13139 /* Filter prefix using distribute list,
13140 * filter list or prefix list
13142 const struct prefix
*rn_p
=
13143 bgp_dest_get_prefix(dest
);
13144 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13147 route_filtered
= true;
13149 /* Filter prefix using route-map */
13150 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13151 safi
, rmap_name
, NULL
,
13154 if (type
== bgp_show_adj_route_filtered
&&
13155 !route_filtered
&& ret
!= RMAP_DENY
) {
13156 bgp_attr_undup(&attr
, ain
->attr
);
13160 if (type
== bgp_show_adj_route_received
13161 && (route_filtered
|| ret
== RMAP_DENY
))
13162 (*filtered_count
)++;
13164 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
13165 use_json
, json_ar
, wide
);
13166 bgp_attr_undup(&attr
, ain
->attr
);
13169 } else if (type
== bgp_show_adj_route_advertised
) {
13170 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13171 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13172 if (paf
->peer
!= peer
|| !adj
->attr
)
13175 show_adj_route_header(vty
, bgp
, table
,
13180 const struct prefix
*rn_p
=
13181 bgp_dest_get_prefix(dest
);
13184 ret
= bgp_output_modifier(
13185 peer
, rn_p
, &attr
, afi
, safi
,
13188 if (ret
!= RMAP_DENY
) {
13189 if ((safi
== SAFI_MPLS_VPN
)
13190 || (safi
== SAFI_ENCAP
)
13191 || (safi
== SAFI_EVPN
)) {
13193 json_object_string_add(
13200 "Route Distinguisher: %s\n",
13206 vty
, rn_p
, &attr
, safi
,
13211 (*filtered_count
)++;
13214 bgp_attr_undup(&attr
, adj
->attr
);
13216 } else if (type
== bgp_show_adj_route_bestpath
) {
13217 struct bgp_path_info
*pi
;
13219 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13220 json
, json_scode
, json_ocode
,
13223 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13225 if (pi
->peer
!= peer
)
13228 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13231 route_vty_out_tmp(vty
,
13232 bgp_dest_get_prefix(dest
),
13233 pi
->attr
, safi
, use_json
,
13241 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13242 safi_t safi
, enum bgp_show_adj_route_type type
,
13243 const char *rmap_name
, uint8_t show_flags
)
13246 struct bgp_table
*table
;
13247 json_object
*json
= NULL
;
13248 json_object
*json_scode
= NULL
;
13249 json_object
*json_ocode
= NULL
;
13250 json_object
*json_ar
= NULL
;
13251 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13253 /* Init BGP headers here so they're only displayed once
13254 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13260 * Initialize variables for each RD
13261 * All prefixes under an RD is aggregated within "json_routes"
13263 char rd_str
[BUFSIZ
] = {0};
13264 json_object
*json_routes
= NULL
;
13267 /* For 2-tier tables, prefix counts need to be
13268 * maintained across multiple runs of show_adj_route()
13270 unsigned long output_count_per_rd
;
13271 unsigned long filtered_count_per_rd
;
13272 unsigned long output_count
= 0;
13273 unsigned long filtered_count
= 0;
13276 json
= json_object_new_object();
13277 json_ar
= json_object_new_object();
13278 json_scode
= json_object_new_object();
13279 json_ocode
= json_object_new_object();
13281 json_object_string_add(json_scode
, "suppressed", "s");
13282 json_object_string_add(json_scode
, "damped", "d");
13283 json_object_string_add(json_scode
, "history", "h");
13284 json_object_string_add(json_scode
, "valid", "*");
13285 json_object_string_add(json_scode
, "best", ">");
13286 json_object_string_add(json_scode
, "multipath", "=");
13287 json_object_string_add(json_scode
, "internal", "i");
13288 json_object_string_add(json_scode
, "ribFailure", "r");
13289 json_object_string_add(json_scode
, "stale", "S");
13290 json_object_string_add(json_scode
, "removed", "R");
13292 json_object_string_add(json_ocode
, "igp", "i");
13293 json_object_string_add(json_ocode
, "egp", "e");
13294 json_object_string_add(json_ocode
, "incomplete", "?");
13297 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13299 json_object_string_add(
13301 "No such neighbor or address family");
13302 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13303 json_object_free(json
);
13305 vty_out(vty
, "%% No such neighbor or address family\n");
13307 return CMD_WARNING
;
13310 if ((type
== bgp_show_adj_route_received
13311 || type
== bgp_show_adj_route_filtered
)
13312 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13313 PEER_FLAG_SOFT_RECONFIG
)) {
13315 json_object_string_add(
13317 "Inbound soft reconfiguration not enabled");
13318 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13319 json_object_free(json
);
13322 "%% Inbound soft reconfiguration not enabled\n");
13324 return CMD_WARNING
;
13329 /* labeled-unicast routes live in the unicast table */
13330 if (safi
== SAFI_LABELED_UNICAST
)
13331 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13333 table
= bgp
->rib
[afi
][safi
];
13335 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13336 || (safi
== SAFI_EVPN
)) {
13338 struct bgp_dest
*dest
;
13340 for (dest
= bgp_table_top(table
); dest
;
13341 dest
= bgp_route_next(dest
)) {
13342 table
= bgp_dest_get_bgp_table_info(dest
);
13346 output_count_per_rd
= 0;
13347 filtered_count_per_rd
= 0;
13350 json_routes
= json_object_new_object();
13352 const struct prefix_rd
*prd
;
13353 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13356 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13358 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13359 rmap_name
, json
, json_routes
, json_scode
,
13360 json_ocode
, show_flags
, &header1
,
13361 &header2
, rd_str
, &output_count_per_rd
,
13362 &filtered_count_per_rd
);
13364 /* Don't include an empty RD in the output! */
13365 if (json_routes
&& (output_count_per_rd
> 0))
13366 json_object_object_add(json_ar
, rd_str
,
13369 output_count
+= output_count_per_rd
;
13370 filtered_count
+= filtered_count_per_rd
;
13373 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13374 json
, json_ar
, json_scode
, json_ocode
,
13375 show_flags
, &header1
, &header2
, rd_str
,
13376 &output_count
, &filtered_count
);
13379 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13380 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13381 json_object_int_add(json
, "filteredPrefixCounter",
13384 vty_out(vty
, "%s\n",
13385 json_object_to_json_string_ext(
13386 json
, JSON_C_TO_STRING_PRETTY
));
13388 if (!output_count
&& !filtered_count
) {
13389 json_object_free(json_scode
);
13390 json_object_free(json_ocode
);
13394 json_object_free(json
);
13396 } else if (output_count
> 0) {
13397 if (filtered_count
> 0)
13399 "\nTotal number of prefixes %ld (%ld filtered)\n",
13400 output_count
, filtered_count
);
13402 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13406 return CMD_SUCCESS
;
13409 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13410 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13411 "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]",
13415 BGP_INSTANCE_HELP_STR
13417 BGP_SAFI_WITH_LABEL_HELP_STR
13418 "Detailed information on TCP and BGP neighbor connections\n"
13419 "Neighbor to display information about\n"
13420 "Neighbor to display information about\n"
13421 "Neighbor on BGP configured interface\n"
13422 "Display the routes selected by best path\n"
13424 "Increase table width for longer prefixes\n")
13426 afi_t afi
= AFI_IP6
;
13427 safi_t safi
= SAFI_UNICAST
;
13428 char *rmap_name
= NULL
;
13429 char *peerstr
= NULL
;
13430 struct bgp
*bgp
= NULL
;
13432 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13434 uint8_t show_flags
= 0;
13437 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13440 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13442 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13446 return CMD_WARNING
;
13448 argv_find(argv
, argc
, "neighbors", &idx
);
13449 peerstr
= argv
[++idx
]->arg
;
13451 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13453 return CMD_WARNING
;
13455 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13459 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13460 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13461 "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]",
13465 BGP_INSTANCE_HELP_STR
13467 BGP_SAFI_WITH_LABEL_HELP_STR
13468 "Display the entries for all address families\n"
13469 "Detailed information on TCP and BGP neighbor connections\n"
13470 "Neighbor to display information about\n"
13471 "Neighbor to display information about\n"
13472 "Neighbor on BGP configured interface\n"
13473 "Display the routes advertised to a BGP neighbor\n"
13474 "Display the received routes from neighbor\n"
13475 "Display the filtered routes received from neighbor\n"
13476 "Route-map to modify the attributes\n"
13477 "Name of the route map\n"
13479 "Increase table width for longer prefixes\n")
13481 afi_t afi
= AFI_IP6
;
13482 safi_t safi
= SAFI_UNICAST
;
13483 char *rmap_name
= NULL
;
13484 char *peerstr
= NULL
;
13485 struct bgp
*bgp
= NULL
;
13487 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13490 uint8_t show_flags
= 0;
13494 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13498 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13499 if (argv_find(argv
, argc
, "ipv4", &idx
))
13500 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13502 if (argv_find(argv
, argc
, "ipv6", &idx
))
13503 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13507 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13509 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13512 return CMD_WARNING
;
13514 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13515 argv_find(argv
, argc
, "neighbors", &idx
);
13516 peerstr
= argv
[++idx
]->arg
;
13518 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13520 return CMD_WARNING
;
13522 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13523 type
= bgp_show_adj_route_advertised
;
13524 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13525 type
= bgp_show_adj_route_received
;
13526 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13527 type
= bgp_show_adj_route_filtered
;
13529 if (argv_find(argv
, argc
, "route-map", &idx
))
13530 rmap_name
= argv
[++idx
]->arg
;
13533 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13536 vty_out(vty
, "{\n");
13538 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13539 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13540 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13542 FOREACH_SAFI (safi
) {
13543 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13550 vty_out(vty
, ",\n");
13551 vty_out(vty
, "\"%s\":",
13552 get_afi_safi_str(afi
, safi
, true));
13554 vty_out(vty
, "\nFor address family: %s\n",
13555 get_afi_safi_str(afi
, safi
, false));
13557 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13561 FOREACH_AFI_SAFI (afi
, safi
) {
13562 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13569 vty_out(vty
, ",\n");
13570 vty_out(vty
, "\"%s\":",
13571 get_afi_safi_str(afi
, safi
, true));
13573 vty_out(vty
, "\nFor address family: %s\n",
13574 get_afi_safi_str(afi
, safi
, false));
13576 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13581 vty_out(vty
, "}\n");
13583 return CMD_SUCCESS
;
13586 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13587 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13588 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13594 "Address Family modifier\n"
13595 "Detailed information on TCP and BGP neighbor connections\n"
13596 "Neighbor to display information about\n"
13597 "Neighbor to display information about\n"
13598 "Neighbor on BGP configured interface\n"
13599 "Display information received from a BGP neighbor\n"
13600 "Display the prefixlist filter\n"
13603 afi_t afi
= AFI_IP6
;
13604 safi_t safi
= SAFI_UNICAST
;
13605 char *peerstr
= NULL
;
13608 union sockunion su
;
13614 /* show [ip] bgp */
13615 if (argv_find(argv
, argc
, "ip", &idx
))
13617 /* [<ipv4|ipv6> [unicast]] */
13618 if (argv_find(argv
, argc
, "ipv4", &idx
))
13620 if (argv_find(argv
, argc
, "ipv6", &idx
))
13622 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13623 argv_find(argv
, argc
, "neighbors", &idx
);
13624 peerstr
= argv
[++idx
]->arg
;
13626 bool uj
= use_json(argc
, argv
);
13628 ret
= str2sockunion(peerstr
, &su
);
13630 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13633 vty_out(vty
, "{}\n");
13636 "%% Malformed address or name: %s\n",
13638 return CMD_WARNING
;
13641 peer
= peer_lookup(NULL
, &su
);
13644 vty_out(vty
, "{}\n");
13646 vty_out(vty
, "No peer\n");
13647 return CMD_WARNING
;
13651 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13652 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13655 vty_out(vty
, "Address Family: %s\n",
13656 get_afi_safi_str(afi
, safi
, false));
13657 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13660 vty_out(vty
, "{}\n");
13662 vty_out(vty
, "No functional output\n");
13665 return CMD_SUCCESS
;
13668 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13669 afi_t afi
, safi_t safi
,
13670 enum bgp_show_type type
, bool use_json
)
13672 uint8_t show_flags
= 0;
13675 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13677 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13679 json_object
*json_no
= NULL
;
13680 json_no
= json_object_new_object();
13681 json_object_string_add(
13682 json_no
, "warning",
13683 "No such neighbor or address family");
13684 vty_out(vty
, "%s\n",
13685 json_object_to_json_string(json_no
));
13686 json_object_free(json_no
);
13688 vty_out(vty
, "%% No such neighbor or address family\n");
13689 return CMD_WARNING
;
13692 /* labeled-unicast routes live in the unicast table */
13693 if (safi
== SAFI_LABELED_UNICAST
)
13694 safi
= SAFI_UNICAST
;
13696 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
13699 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13700 show_ip_bgp_flowspec_routes_detailed_cmd
,
13701 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13705 BGP_INSTANCE_HELP_STR
13708 "Detailed information on flowspec entries\n"
13711 afi_t afi
= AFI_IP
;
13712 safi_t safi
= SAFI_UNICAST
;
13713 struct bgp
*bgp
= NULL
;
13715 bool uj
= use_json(argc
, argv
);
13716 uint8_t show_flags
= 0;
13720 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13723 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13726 return CMD_WARNING
;
13728 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13732 DEFUN (show_ip_bgp_neighbor_routes
,
13733 show_ip_bgp_neighbor_routes_cmd
,
13734 "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]",
13738 BGP_INSTANCE_HELP_STR
13740 BGP_SAFI_WITH_LABEL_HELP_STR
13741 "Detailed information on TCP and BGP neighbor connections\n"
13742 "Neighbor to display information about\n"
13743 "Neighbor to display information about\n"
13744 "Neighbor on BGP configured interface\n"
13745 "Display flap statistics of the routes learned from neighbor\n"
13746 "Display the dampened routes received from neighbor\n"
13747 "Display routes learned from neighbor\n"
13750 char *peerstr
= NULL
;
13751 struct bgp
*bgp
= NULL
;
13752 afi_t afi
= AFI_IP6
;
13753 safi_t safi
= SAFI_UNICAST
;
13755 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
13757 bool uj
= use_json(argc
, argv
);
13762 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13765 return CMD_WARNING
;
13767 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13768 argv_find(argv
, argc
, "neighbors", &idx
);
13769 peerstr
= argv
[++idx
]->arg
;
13771 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13773 return CMD_WARNING
;
13775 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
13776 sh_type
= bgp_show_type_flap_neighbor
;
13777 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
13778 sh_type
= bgp_show_type_damp_neighbor
;
13779 else if (argv_find(argv
, argc
, "routes", &idx
))
13780 sh_type
= bgp_show_type_neighbor
;
13782 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
13785 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
13787 struct bgp_distance
{
13788 /* Distance value for the IP source prefix. */
13791 /* Name of the access-list to be matched. */
13795 DEFUN (show_bgp_afi_vpn_rd_route
,
13796 show_bgp_afi_vpn_rd_route_cmd
,
13797 "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]",
13801 "Address Family modifier\n"
13802 "Display information for a route distinguisher\n"
13803 "Route Distinguisher\n"
13804 "Network in the BGP routing table to display\n"
13805 "Network in the BGP routing table to display\n"
13809 struct prefix_rd prd
;
13810 afi_t afi
= AFI_MAX
;
13813 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
13814 vty_out(vty
, "%% Malformed Address Family\n");
13815 return CMD_WARNING
;
13818 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
13820 vty_out(vty
, "%% Malformed Route Distinguisher\n");
13821 return CMD_WARNING
;
13824 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
13825 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
13828 static struct bgp_distance
*bgp_distance_new(void)
13830 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
13833 static void bgp_distance_free(struct bgp_distance
*bdistance
)
13835 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
13838 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
13839 const char *access_list_str
, afi_t afi
, safi_t safi
,
13840 char *errmsg
, size_t errmsg_len
)
13844 struct bgp_dest
*dest
;
13845 struct bgp_distance
*bdistance
;
13847 ret
= str2prefix(ip_str
, &p
);
13849 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13850 return CMD_WARNING_CONFIG_FAILED
;
13853 /* Get BGP distance node. */
13854 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
13855 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13857 bgp_dest_unlock_node(dest
);
13859 bdistance
= bgp_distance_new();
13860 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
13863 /* Set distance value. */
13864 bdistance
->distance
= distance
;
13866 /* Reset access-list configuration. */
13867 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13868 if (access_list_str
)
13869 bdistance
->access_list
=
13870 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
13872 return CMD_SUCCESS
;
13875 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
13876 const char *access_list_str
, afi_t afi
, safi_t safi
,
13877 char *errmsg
, size_t errmsg_len
)
13881 struct bgp_dest
*dest
;
13882 struct bgp_distance
*bdistance
;
13884 ret
= str2prefix(ip_str
, &p
);
13886 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13887 return CMD_WARNING_CONFIG_FAILED
;
13890 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13892 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
13893 return CMD_WARNING_CONFIG_FAILED
;
13896 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13898 if (bdistance
->distance
!= distance
) {
13899 snprintf(errmsg
, errmsg_len
,
13900 "Distance does not match configured\n");
13901 return CMD_WARNING_CONFIG_FAILED
;
13904 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13905 bgp_distance_free(bdistance
);
13907 bgp_dest_set_bgp_path_info(dest
, NULL
);
13908 bgp_dest_unlock_node(dest
);
13909 bgp_dest_unlock_node(dest
);
13911 return CMD_SUCCESS
;
13914 /* Apply BGP information to distance method. */
13915 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13916 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13918 struct bgp_dest
*dest
;
13919 struct prefix q
= {0};
13921 struct bgp_distance
*bdistance
;
13922 struct access_list
*alist
;
13923 struct bgp_static
*bgp_static
;
13928 peer
= pinfo
->peer
;
13930 if (pinfo
->attr
->distance
)
13931 return pinfo
->attr
->distance
;
13933 /* Check source address.
13934 * Note: for aggregate route, peer can have unspec af type.
13936 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
13937 && !sockunion2hostprefix(&peer
->su
, &q
))
13940 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13942 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13943 bgp_dest_unlock_node(dest
);
13945 if (bdistance
->access_list
) {
13946 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13948 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13949 return bdistance
->distance
;
13951 return bdistance
->distance
;
13954 /* Backdoor check. */
13955 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
13957 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
13958 bgp_dest_unlock_node(dest
);
13960 if (bgp_static
->backdoor
) {
13961 if (bgp
->distance_local
[afi
][safi
])
13962 return bgp
->distance_local
[afi
][safi
];
13964 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13968 if (peer
->sort
== BGP_PEER_EBGP
) {
13969 if (bgp
->distance_ebgp
[afi
][safi
])
13970 return bgp
->distance_ebgp
[afi
][safi
];
13971 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
13972 } else if (peer
->sort
== BGP_PEER_IBGP
) {
13973 if (bgp
->distance_ibgp
[afi
][safi
])
13974 return bgp
->distance_ibgp
[afi
][safi
];
13975 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13977 if (bgp
->distance_local
[afi
][safi
])
13978 return bgp
->distance_local
[afi
][safi
];
13979 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
13983 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13984 * we should tell ZEBRA update the routes for a specific
13985 * AFI/SAFI to reflect changes in RIB.
13987 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
13988 safi_t update_safi
)
13993 FOREACH_AFI_SAFI (afi
, safi
) {
13994 if (!bgp_fibupd_safi(safi
))
13997 if (afi
!= update_afi
&& safi
!= update_safi
)
14000 if (BGP_DEBUG(zebra
, ZEBRA
))
14002 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14003 __func__
, afi
, safi
);
14004 bgp_zebra_announce_table(bgp
, afi
, safi
);
14008 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
14009 "distance bgp (1-255) (1-255) (1-255)",
14010 "Define an administrative distance\n"
14012 "Distance for routes external to the AS\n"
14013 "Distance for routes internal to the AS\n"
14014 "Distance for local routes\n")
14016 int idx_number
= 2;
14017 int idx_number_2
= 3;
14018 int idx_number_3
= 4;
14021 char xpath
[XPATH_MAXLEN
];
14023 afi
= bgp_node_afi(vty
);
14024 safi
= bgp_node_safi(vty
);
14027 xpath
, sizeof(xpath
),
14028 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14029 yang_afi_safi_value2identity(afi
, safi
),
14030 bgp_afi_safi_get_container_str(afi
, safi
));
14031 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
14033 xpath
, sizeof(xpath
),
14034 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14035 yang_afi_safi_value2identity(afi
, safi
),
14036 bgp_afi_safi_get_container_str(afi
, safi
));
14037 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14038 argv
[idx_number_2
]->arg
);
14040 xpath
, sizeof(xpath
),
14041 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14042 yang_afi_safi_value2identity(afi
, safi
),
14043 bgp_afi_safi_get_container_str(afi
, safi
));
14045 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14046 argv
[idx_number_3
]->arg
);
14048 return nb_cli_apply_changes(vty
, NULL
);
14051 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
14052 "no distance bgp [(1-255) (1-255) (1-255)]",
14054 "Define an administrative distance\n"
14056 "Distance for routes external to the AS\n"
14057 "Distance for routes internal to the AS\n"
14058 "Distance for local routes\n")
14062 char xpath
[XPATH_MAXLEN
];
14064 afi
= bgp_node_afi(vty
);
14065 safi
= bgp_node_safi(vty
);
14068 xpath
, sizeof(xpath
),
14069 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14070 yang_afi_safi_value2identity(afi
, safi
),
14071 bgp_afi_safi_get_container_str(afi
, safi
));
14072 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14074 xpath
, sizeof(xpath
),
14075 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14076 yang_afi_safi_value2identity(afi
, safi
),
14077 bgp_afi_safi_get_container_str(afi
, safi
));
14078 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14080 xpath
, sizeof(xpath
),
14081 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14082 yang_afi_safi_value2identity(afi
, safi
),
14083 bgp_afi_safi_get_container_str(afi
, safi
));
14085 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14087 return nb_cli_apply_changes(vty
, NULL
);
14090 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
14091 struct lyd_node
*dnode
,
14092 bool show_defaults
)
14094 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
14096 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14097 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14098 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14100 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14104 DEFPY_YANG(bgp_distance_source
,
14105 bgp_distance_source_cmd
,
14106 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14108 "Define an administrative distance\n"
14110 "IPv4 source prefix\n"
14111 "IPv6 source prefix\n"
14112 "Access list name\n")
14116 char xpath
[XPATH_MAXLEN
];
14118 afi
= bgp_node_afi(vty
);
14119 safi
= bgp_node_safi(vty
);
14122 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14123 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14126 nb_cli_enqueue_change(vty
,
14127 "./access-list-policy-export",
14128 NB_OP_CREATE
, acl
);
14130 nb_cli_enqueue_change(vty
,
14131 "./access-list-policy-export",
14132 NB_OP_DESTROY
, NULL
);
14134 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14138 xpath
, sizeof(xpath
),
14139 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14140 yang_afi_safi_value2identity(afi
, safi
),
14141 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14143 return nb_cli_apply_changes(vty
, xpath
);
14146 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14147 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14149 vty_out(vty
, " distance %d %s %s\n",
14150 yang_dnode_get_uint8(dnode
, "./distance"),
14151 yang_dnode_get_string(dnode
, "./prefix"),
14152 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14153 ? yang_dnode_get_string(dnode
,
14154 "./access-list-policy-export")
14159 bgp_dampening
, bgp_dampening_cmd
,
14160 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14162 "BGP Specific commands\n"
14163 "Enable route-flap dampening\n"
14164 "Half-life time for the penalty\n"
14165 "Value to start reusing a route\n"
14166 "Value to start suppressing a route\n"
14167 "Maximum duration to suppress a stable route\n")
14171 char xpath
[XPATH_MAXLEN
];
14173 afi
= bgp_node_afi(vty
);
14174 safi
= bgp_node_safi(vty
);
14177 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14179 nb_cli_enqueue_change(vty
, "./reach-decay",
14180 NB_OP_MODIFY
, halflife_str
);
14181 nb_cli_enqueue_change(vty
, "./reuse-above",
14182 NB_OP_MODIFY
, reuse_str
);
14183 nb_cli_enqueue_change(vty
, "./suppress-above",
14184 NB_OP_MODIFY
, suppress_str
);
14185 nb_cli_enqueue_change(vty
, "./unreach-decay",
14186 NB_OP_MODIFY
, max_suppress_str
);
14188 nb_cli_enqueue_change(vty
, "./reach-decay",
14189 NB_OP_MODIFY
, halflife_str
);
14192 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14196 xpath
, sizeof(xpath
),
14197 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14198 yang_afi_safi_value2identity(afi
, safi
),
14199 bgp_afi_safi_get_container_str(afi
, safi
));
14201 return nb_cli_apply_changes(vty
, xpath
);
14204 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14205 struct lyd_node
*dnode
,
14206 bool show_defaults
)
14208 if (!yang_dnode_get_bool(dnode
, "./enable"))
14211 int half
= DEFAULT_HALF_LIFE
* 60;
14212 int reuse
= DEFAULT_REUSE
;
14213 int suppress
= DEFAULT_SUPPRESS
;
14216 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14217 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14218 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14219 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14221 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14222 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14223 vty_out(vty
, " bgp dampening\n");
14224 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14225 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14226 vty_out(vty
, " bgp dampening %u\n", half
);
14228 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14232 /* Display specified route of BGP table. */
14233 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14234 const char *ip_str
, afi_t afi
, safi_t safi
,
14235 struct prefix_rd
*prd
, int prefix_check
)
14238 struct prefix match
;
14239 struct bgp_dest
*dest
;
14240 struct bgp_dest
*rm
;
14241 struct bgp_path_info
*pi
;
14242 struct bgp_path_info
*pi_temp
;
14244 struct bgp_table
*table
;
14246 /* BGP structure lookup. */
14248 bgp
= bgp_lookup_by_name(view_name
);
14250 vty_out(vty
, "%% Can't find BGP instance %s\n",
14252 return CMD_WARNING
;
14255 bgp
= bgp_get_default();
14257 vty_out(vty
, "%% No BGP process is configured\n");
14258 return CMD_WARNING
;
14262 /* Check IP address argument. */
14263 ret
= str2prefix(ip_str
, &match
);
14265 vty_out(vty
, "%% address is malformed\n");
14266 return CMD_WARNING
;
14269 match
.family
= afi2family(afi
);
14271 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14272 || (safi
== SAFI_EVPN
)) {
14273 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14274 dest
= bgp_route_next(dest
)) {
14275 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14277 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14279 table
= bgp_dest_get_bgp_table_info(dest
);
14282 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
14285 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14288 || rm_p
->prefixlen
== match
.prefixlen
) {
14289 pi
= bgp_dest_get_bgp_path_info(rm
);
14291 if (pi
->extra
&& pi
->extra
->damp_info
) {
14292 pi_temp
= pi
->next
;
14293 bgp_damp_info_free(
14294 &pi
->extra
->damp_info
,
14295 &bgp
->damp
[afi
][safi
],
14303 bgp_dest_unlock_node(rm
);
14306 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
14308 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14311 || dest_p
->prefixlen
== match
.prefixlen
) {
14312 pi
= bgp_dest_get_bgp_path_info(dest
);
14314 if (pi
->extra
&& pi
->extra
->damp_info
) {
14315 pi_temp
= pi
->next
;
14316 struct bgp_damp_info
*bdi
=
14317 pi
->extra
->damp_info
;
14318 if (bdi
->lastrecord
14319 == BGP_RECORD_UPDATE
) {
14320 bgp_aggregate_increment(
14331 bgp_damp_info_free(
14332 &pi
->extra
->damp_info
,
14333 &bgp
->damp
[afi
][safi
],
14341 bgp_dest_unlock_node(dest
);
14345 return CMD_SUCCESS
;
14348 DEFUN (clear_ip_bgp_dampening
,
14349 clear_ip_bgp_dampening_cmd
,
14350 "clear ip bgp dampening",
14354 "Clear route flap dampening information\n")
14356 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14357 bgp_damp_info_clean(bgp
, &bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14359 return CMD_SUCCESS
;
14362 DEFUN (clear_ip_bgp_dampening_prefix
,
14363 clear_ip_bgp_dampening_prefix_cmd
,
14364 "clear ip bgp dampening A.B.C.D/M",
14368 "Clear route flap dampening information\n"
14371 int idx_ipv4_prefixlen
= 4;
14372 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14373 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14376 DEFUN (clear_ip_bgp_dampening_address
,
14377 clear_ip_bgp_dampening_address_cmd
,
14378 "clear ip bgp dampening A.B.C.D",
14382 "Clear route flap dampening information\n"
14383 "Network to clear damping information\n")
14386 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14387 SAFI_UNICAST
, NULL
, 0);
14390 DEFUN (clear_ip_bgp_dampening_address_mask
,
14391 clear_ip_bgp_dampening_address_mask_cmd
,
14392 "clear ip bgp dampening A.B.C.D A.B.C.D",
14396 "Clear route flap dampening information\n"
14397 "Network to clear damping information\n"
14401 int idx_ipv4_2
= 5;
14403 char prefix_str
[BUFSIZ
];
14405 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14406 prefix_str
, sizeof(prefix_str
));
14408 vty_out(vty
, "%% Inconsistent address and mask\n");
14409 return CMD_WARNING
;
14412 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14416 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14418 struct vty
*vty
= arg
;
14419 struct peer
*peer
= bucket
->data
;
14420 char buf
[SU_ADDRSTRLEN
];
14422 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14423 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14426 DEFUN (show_bgp_listeners
,
14427 show_bgp_listeners_cmd
,
14428 "show bgp listeners",
14431 "Display Listen Sockets and who created them\n")
14433 bgp_dump_listener_info(vty
);
14435 return CMD_SUCCESS
;
14438 DEFUN (show_bgp_peerhash
,
14439 show_bgp_peerhash_cmd
,
14440 "show bgp peerhash",
14443 "Display information about the BGP peerhash\n")
14445 struct list
*instances
= bm
->bgp
;
14446 struct listnode
*node
;
14449 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14450 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14451 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14455 return CMD_SUCCESS
;
14458 /* also used for encap safi */
14459 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14460 afi_t afi
, safi_t safi
)
14462 struct bgp_dest
*pdest
;
14463 struct bgp_dest
*dest
;
14464 struct bgp_table
*table
;
14465 const struct prefix
*p
;
14466 const struct prefix_rd
*prd
;
14467 struct bgp_static
*bgp_static
;
14468 mpls_label_t label
;
14469 char rdbuf
[RD_ADDRSTRLEN
];
14471 /* Network configuration. */
14472 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14473 pdest
= bgp_route_next(pdest
)) {
14474 table
= bgp_dest_get_bgp_table_info(pdest
);
14478 for (dest
= bgp_table_top(table
); dest
;
14479 dest
= bgp_route_next(dest
)) {
14480 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14481 if (bgp_static
== NULL
)
14484 p
= bgp_dest_get_prefix(dest
);
14485 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14488 /* "network" configuration display. */
14489 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14490 label
= decode_label(&bgp_static
->label
);
14492 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14493 if (safi
== SAFI_MPLS_VPN
)
14494 vty_out(vty
, " label %u", label
);
14496 if (bgp_static
->rmap
.name
)
14497 vty_out(vty
, " route-map %s",
14498 bgp_static
->rmap
.name
);
14500 if (bgp_static
->backdoor
)
14501 vty_out(vty
, " backdoor");
14503 vty_out(vty
, "\n");
14508 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14509 afi_t afi
, safi_t safi
)
14511 struct bgp_dest
*pdest
;
14512 struct bgp_dest
*dest
;
14513 struct bgp_table
*table
;
14514 const struct prefix
*p
;
14515 const struct prefix_rd
*prd
;
14516 struct bgp_static
*bgp_static
;
14517 char buf
[PREFIX_STRLEN
* 2];
14518 char buf2
[SU_ADDRSTRLEN
];
14519 char rdbuf
[RD_ADDRSTRLEN
];
14520 char esi_buf
[ESI_BYTES
];
14522 /* Network configuration. */
14523 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14524 pdest
= bgp_route_next(pdest
)) {
14525 table
= bgp_dest_get_bgp_table_info(pdest
);
14529 for (dest
= bgp_table_top(table
); dest
;
14530 dest
= bgp_route_next(dest
)) {
14531 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14532 if (bgp_static
== NULL
)
14535 char *macrouter
= NULL
;
14537 if (bgp_static
->router_mac
)
14538 macrouter
= prefix_mac2str(
14539 bgp_static
->router_mac
, NULL
, 0);
14540 if (bgp_static
->eth_s_id
)
14541 esi_to_str(bgp_static
->eth_s_id
,
14542 esi_buf
, sizeof(esi_buf
));
14543 p
= bgp_dest_get_prefix(dest
);
14544 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14546 /* "network" configuration display. */
14547 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14548 if (p
->u
.prefix_evpn
.route_type
== 5) {
14549 char local_buf
[PREFIX_STRLEN
];
14550 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14551 struct prefix_evpn
*)p
)
14555 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14556 local_buf
, PREFIX_STRLEN
);
14557 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14558 p
->u
.prefix_evpn
.prefix_addr
14559 .ip_prefix_length
);
14561 prefix2str(p
, buf
, sizeof(buf
));
14564 if (bgp_static
->gatewayIp
.family
== AF_INET
14565 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14566 inet_ntop(bgp_static
->gatewayIp
.family
,
14567 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14570 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14572 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14573 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14576 XFREE(MTYPE_TMP
, macrouter
);
14581 /* Configuration of static route announcement and aggregate
14583 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14586 struct bgp_dest
*dest
;
14587 const struct prefix
*p
;
14588 struct bgp_static
*bgp_static
;
14589 struct bgp_aggregate
*bgp_aggregate
;
14591 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14592 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14596 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14597 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14601 /* Network configuration. */
14602 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14603 dest
= bgp_route_next(dest
)) {
14604 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14605 if (bgp_static
== NULL
)
14608 p
= bgp_dest_get_prefix(dest
);
14610 vty_out(vty
, " network %pFX", p
);
14612 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14613 vty_out(vty
, " label-index %u",
14614 bgp_static
->label_index
);
14616 if (bgp_static
->rmap
.name
)
14617 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14619 if (bgp_static
->backdoor
)
14620 vty_out(vty
, " backdoor");
14622 vty_out(vty
, "\n");
14625 /* Aggregate-address configuration. */
14626 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14627 dest
= bgp_route_next(dest
)) {
14628 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14629 if (bgp_aggregate
== NULL
)
14632 p
= bgp_dest_get_prefix(dest
);
14634 vty_out(vty
, " aggregate-address %pFX", p
);
14636 if (bgp_aggregate
->as_set
)
14637 vty_out(vty
, " as-set");
14639 if (bgp_aggregate
->summary_only
)
14640 vty_out(vty
, " summary-only");
14642 if (bgp_aggregate
->rmap
.name
)
14643 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14645 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14646 vty_out(vty
, " origin %s",
14647 bgp_origin2str(bgp_aggregate
->origin
));
14649 if (bgp_aggregate
->match_med
)
14650 vty_out(vty
, " matching-MED-only");
14652 if (bgp_aggregate
->suppress_map_name
)
14653 vty_out(vty
, " suppress-map %s",
14654 bgp_aggregate
->suppress_map_name
);
14656 vty_out(vty
, "\n");
14660 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14663 struct bgp_dest
*dest
;
14664 struct bgp_distance
*bdistance
;
14666 /* Distance configuration. */
14667 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
14668 && bgp
->distance_local
[afi
][safi
]
14669 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
14670 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
14671 || bgp
->distance_local
[afi
][safi
]
14672 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
14673 vty_out(vty
, " distance bgp %d %d %d\n",
14674 bgp
->distance_ebgp
[afi
][safi
],
14675 bgp
->distance_ibgp
[afi
][safi
],
14676 bgp
->distance_local
[afi
][safi
]);
14679 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14680 dest
= bgp_route_next(dest
)) {
14681 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14682 if (bdistance
!= NULL
)
14683 vty_out(vty
, " distance %d %pBD %s\n",
14684 bdistance
->distance
, dest
,
14685 bdistance
->access_list
? bdistance
->access_list
14690 /* Allocate routing table structure and install commands. */
14691 void bgp_route_init(void)
14696 /* Init BGP distance table. */
14697 FOREACH_AFI_SAFI (afi
, safi
)
14698 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14700 /* IPv4 BGP commands. */
14701 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14702 install_element(BGP_NODE
, &bgp_network_cmd
);
14703 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14705 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14707 /* IPv4 unicast configuration. */
14708 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14709 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14710 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14712 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14714 /* IPv4 multicast configuration. */
14715 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14716 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14717 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14718 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14720 /* IPv4 labeled-unicast configuration. */
14721 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14722 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14724 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14725 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14726 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14727 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14728 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14729 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14730 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14731 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14733 install_element(VIEW_NODE
,
14734 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14735 install_element(VIEW_NODE
,
14736 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
14737 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
14738 install_element(VIEW_NODE
,
14739 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
14740 #ifdef KEEP_OLD_VPN_COMMANDS
14741 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
14742 #endif /* KEEP_OLD_VPN_COMMANDS */
14743 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
14744 install_element(VIEW_NODE
,
14745 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
14747 /* BGP dampening clear commands */
14748 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
14749 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
14751 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
14752 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
14755 install_element(ENABLE_NODE
,
14756 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
14757 #ifdef KEEP_OLD_VPN_COMMANDS
14758 install_element(ENABLE_NODE
,
14759 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
14760 #endif /* KEEP_OLD_VPN_COMMANDS */
14762 /* New config IPv6 BGP commands. */
14763 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
14764 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
14765 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
14767 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
14769 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
14771 /* IPv6 labeled unicast address family. */
14772 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
14773 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
14775 install_element(BGP_NODE
, &bgp_distance_cmd
);
14776 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
14777 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
14778 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
14779 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
14780 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
14781 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
14782 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
14783 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
14784 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
14785 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
14786 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
14787 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
14788 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
14789 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
14791 /* BGP dampening */
14792 install_element(BGP_NODE
, &bgp_dampening_cmd
);
14793 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
14794 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
14795 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
14796 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
14797 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
14798 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
14800 /* Large Communities */
14801 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
14802 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
14804 /* show bgp ipv4 flowspec detailed */
14805 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
14807 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
14808 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
14811 void bgp_route_finish(void)
14816 FOREACH_AFI_SAFI (afi
, safi
) {
14817 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
14818 bgp_distance_table
[afi
][safi
] = NULL
;