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"
74 #include "bgpd/bgp_rpki.h"
77 #include "bgpd/rfapi/rfapi_backend.h"
78 #include "bgpd/rfapi/vnc_import_bgp.h"
79 #include "bgpd/rfapi/vnc_export_bgp.h"
81 #include "bgpd/bgp_encap_types.h"
82 #include "bgpd/bgp_encap_tlv.h"
83 #include "bgpd/bgp_evpn.h"
84 #include "bgpd/bgp_evpn_mh.h"
85 #include "bgpd/bgp_evpn_vty.h"
86 #include "bgpd/bgp_flowspec.h"
87 #include "bgpd/bgp_flowspec_util.h"
88 #include "bgpd/bgp_pbr.h"
89 #include "northbound.h"
90 #include "northbound_cli.h"
91 #include "bgpd/bgp_nb.h"
93 #ifndef VTYSH_EXTRACT_PL
94 #include "bgpd/bgp_route_clippy.c"
97 DEFINE_HOOK(bgp_snmp_update_stats
,
98 (struct bgp_node
*rn
, struct bgp_path_info
*pi
, bool added
),
101 DEFINE_HOOK(bgp_rpki_prefix_status
,
102 (struct peer
*peer
, struct attr
*attr
,
103 const struct prefix
*prefix
),
104 (peer
, attr
, prefix
));
106 /* Extern from bgp_dump.c */
107 extern const char *bgp_origin_str
[];
108 extern const char *bgp_origin_long_str
[];
111 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
112 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
113 static const struct message bgp_pmsi_tnltype_str
[] = {
114 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
115 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
116 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
117 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
118 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
119 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
120 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
121 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
125 #define VRFID_NONE_STR "-"
127 DEFINE_HOOK(bgp_process
,
128 (struct bgp
* bgp
, afi_t afi
, safi_t safi
, struct bgp_dest
*bn
,
129 struct peer
*peer
, bool withdraw
),
130 (bgp
, afi
, safi
, bn
, peer
, withdraw
));
132 /** Test if path is suppressed. */
133 static bool bgp_path_suppressed(struct bgp_path_info
*pi
)
135 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
138 return listcount(pi
->extra
->aggr_suppressors
) > 0;
141 struct bgp_dest
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
142 safi_t safi
, const struct prefix
*p
,
143 struct prefix_rd
*prd
)
145 struct bgp_dest
*dest
;
146 struct bgp_dest
*pdest
= NULL
;
150 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
151 || (safi
== SAFI_EVPN
)) {
152 pdest
= bgp_node_get(table
, (struct prefix
*)prd
);
154 if (!bgp_dest_has_bgp_path_info_data(pdest
))
155 bgp_dest_set_bgp_table_info(
156 pdest
, bgp_table_init(table
->bgp
, afi
, safi
));
158 bgp_dest_unlock_node(pdest
);
159 table
= bgp_dest_get_bgp_table_info(pdest
);
162 dest
= bgp_node_get(table
, p
);
164 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
165 || (safi
== SAFI_EVPN
))
171 struct bgp_dest
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
172 safi_t safi
, const struct prefix
*p
,
173 struct prefix_rd
*prd
)
175 struct bgp_dest
*dest
;
176 struct bgp_dest
*pdest
= NULL
;
181 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
182 || (safi
== SAFI_EVPN
)) {
183 pdest
= bgp_node_lookup(table
, (struct prefix
*)prd
);
187 if (!bgp_dest_has_bgp_path_info_data(pdest
)) {
188 bgp_dest_unlock_node(pdest
);
192 table
= bgp_dest_get_bgp_table_info(pdest
);
195 dest
= bgp_node_lookup(table
, p
);
200 /* Allocate bgp_path_info_extra */
201 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
203 struct bgp_path_info_extra
*new;
204 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
205 sizeof(struct bgp_path_info_extra
));
206 new->label
[0] = MPLS_INVALID_LABEL
;
208 new->bgp_fs_pbr
= NULL
;
209 new->bgp_fs_iprule
= NULL
;
213 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
215 struct bgp_path_info_extra
*e
;
217 if (!extra
|| !*extra
)
224 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
227 /* FIXME: since multiple e may have the same e->parent
228 * and e->parent->net is holding a refcount for each
229 * of them, we need to do some fudging here.
231 * WARNING: if bpi->net->lock drops to 0, bpi may be
232 * freed as well (because bpi->net was holding the
233 * last reference to bpi) => write after free!
237 bpi
= bgp_path_info_lock(bpi
);
238 refcount
= bgp_dest_get_lock_count(bpi
->net
) - 1;
239 bgp_dest_unlock_node((struct bgp_dest
*)bpi
->net
);
242 bgp_path_info_unlock(bpi
);
244 bgp_path_info_unlock(e
->parent
);
249 bgp_unlock(e
->bgp_orig
);
251 if (e
->aggr_suppressors
)
252 list_delete(&e
->aggr_suppressors
);
255 bgp_evpn_path_mh_info_free(e
->mh_info
);
257 if ((*extra
)->bgp_fs_iprule
)
258 list_delete(&((*extra
)->bgp_fs_iprule
));
259 if ((*extra
)->bgp_fs_pbr
)
260 list_delete(&((*extra
)->bgp_fs_pbr
));
261 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
264 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
265 * allocated if required.
267 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
270 pi
->extra
= bgp_path_info_extra_new();
274 /* Free bgp route information. */
275 static void bgp_path_info_free(struct bgp_path_info
*path
)
277 bgp_attr_unintern(&path
->attr
);
279 bgp_unlink_nexthop(path
);
280 bgp_path_info_extra_free(&path
->extra
);
281 bgp_path_info_mpath_free(&path
->mpath
);
283 bgp_addpath_free_info_data(&path
->tx_addpath
,
284 &path
->net
->tx_addpath
);
286 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
288 XFREE(MTYPE_BGP_ROUTE
, path
);
291 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
297 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
299 assert(path
&& path
->lock
> 0);
302 if (path
->lock
== 0) {
304 zlog_debug ("%s: unlocked and freeing", __func__
);
305 zlog_backtrace (LOG_DEBUG
);
307 bgp_path_info_free(path
);
314 zlog_debug ("%s: unlocked to 1", __func__
);
315 zlog_backtrace (LOG_DEBUG
);
322 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
323 static int bgp_dest_set_defer_flag(struct bgp_dest
*dest
, bool delete)
326 struct bgp_path_info
*old_pi
, *nextpi
;
327 bool set_flag
= false;
328 struct bgp
*bgp
= NULL
;
329 struct bgp_table
*table
= NULL
;
333 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
334 * then the route selection is deferred
336 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
339 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
340 if (BGP_DEBUG(update
, UPDATE_OUT
))
342 "Route %pBD is in workqueue and being processed, not deferred.",
348 table
= bgp_dest_table(dest
);
355 for (old_pi
= bgp_dest_get_bgp_path_info(dest
);
356 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
357 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
360 /* Route selection is deferred if there is a stale path which
361 * which indicates peer is in restart mode
363 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
364 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
367 /* If the peer is graceful restart capable and peer is
368 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
371 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
372 && BGP_PEER_RESTARTING_MODE(peer
)
374 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
382 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
385 if (set_flag
&& table
) {
386 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
387 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
388 bgp
->gr_info
[afi
][safi
].gr_deferred
++;
389 SET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
390 if (BGP_DEBUG(update
, UPDATE_OUT
))
391 zlog_debug("DEFER route %pBD, dest %p", dest
,
399 void bgp_path_info_add(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
401 struct bgp_path_info
*top
;
403 top
= bgp_dest_get_bgp_path_info(dest
);
409 bgp_dest_set_bgp_path_info(dest
, pi
);
411 bgp_path_info_lock(pi
);
412 bgp_dest_lock_node(dest
);
413 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
414 bgp_dest_set_defer_flag(dest
, false);
415 hook_call(bgp_snmp_update_stats
, dest
, pi
, true);
418 /* Do the actual removal of info from RIB, for use by bgp_process
419 completion callback *only* */
420 void bgp_path_info_reap(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
423 pi
->next
->prev
= pi
->prev
;
425 pi
->prev
->next
= pi
->next
;
427 bgp_dest_set_bgp_path_info(dest
, pi
->next
);
429 bgp_path_info_mpath_dequeue(pi
);
430 bgp_path_info_unlock(pi
);
431 hook_call(bgp_snmp_update_stats
, dest
, pi
, false);
432 bgp_dest_unlock_node(dest
);
435 void bgp_path_info_delete(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
437 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_REMOVED
);
438 /* set of previous already took care of pcount */
439 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
442 /* undo the effects of a previous call to bgp_path_info_delete; typically
443 called when a route is deleted and then quickly re-added before the
444 deletion has been processed */
445 void bgp_path_info_restore(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
447 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_REMOVED
);
448 /* unset of previous already took care of pcount */
449 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
452 /* Adjust pcount as required */
453 static void bgp_pcount_adjust(struct bgp_dest
*dest
, struct bgp_path_info
*pi
)
455 struct bgp_table
*table
;
457 assert(dest
&& bgp_dest_table(dest
));
458 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
460 table
= bgp_dest_table(dest
);
462 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
465 if (!BGP_PATH_COUNTABLE(pi
)
466 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
468 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
470 /* slight hack, but more robust against errors. */
471 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
472 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
474 flog_err(EC_LIB_DEVELOPMENT
,
475 "Asked to decrement 0 prefix count for peer");
476 } else if (BGP_PATH_COUNTABLE(pi
)
477 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
478 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
479 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
483 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
484 struct bgp_path_info
*pi2
)
486 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
489 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
490 * This is here primarily to keep prefix-count in check.
492 void bgp_path_info_set_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
495 SET_FLAG(pi
->flags
, flag
);
497 /* early bath if we know it's not a flag that changes countability state
499 if (!CHECK_FLAG(flag
,
500 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
503 bgp_pcount_adjust(dest
, pi
);
506 void bgp_path_info_unset_flag(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
509 UNSET_FLAG(pi
->flags
, flag
);
511 /* early bath if we know it's not a flag that changes countability state
513 if (!CHECK_FLAG(flag
,
514 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
517 bgp_pcount_adjust(dest
, pi
);
520 /* Get MED value. If MED value is missing and "bgp bestpath
521 missing-as-worst" is specified, treat it as the worst value. */
522 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
524 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
527 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
534 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
,
537 if (pi
->addpath_rx_id
)
538 snprintf(buf
, buf_len
, "path %s (addpath rxid %d)",
539 pi
->peer
->host
, pi
->addpath_rx_id
);
541 snprintf(buf
, buf_len
, "path %s", pi
->peer
->host
);
544 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
546 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
547 struct bgp_path_info
*exist
, int *paths_eq
,
548 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
549 char *pfx_buf
, afi_t afi
, safi_t safi
,
550 enum bgp_path_selection_reason
*reason
)
552 struct attr
*newattr
, *existattr
;
553 bgp_peer_sort_t new_sort
;
554 bgp_peer_sort_t exist_sort
;
560 uint32_t exist_weight
;
561 uint32_t newm
, existm
;
562 struct in_addr new_id
;
563 struct in_addr exist_id
;
566 int internal_as_route
;
569 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
570 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
572 uint32_t exist_mm_seq
;
579 bool new_origin
, exist_origin
;
585 *reason
= bgp_path_selection_none
;
587 zlog_debug("%s: new is NULL", pfx_buf
);
592 bgp_path_info_path_with_addpath_rx_str(new, new_buf
,
596 *reason
= bgp_path_selection_first
;
598 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
604 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
,
606 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
607 pfx_buf
, new_buf
, new->flags
, exist_buf
,
612 existattr
= exist
->attr
;
614 /* For EVPN routes, we cannot just go by local vs remote, we have to
615 * look at the MAC mobility sequence number, if present.
617 if (safi
== SAFI_EVPN
) {
618 /* This is an error condition described in RFC 7432 Section
620 * states that in this scenario "the PE MUST alert the operator"
622 * does not state what other action to take. In order to provide
624 * consistency in this scenario we are going to prefer the path
628 if (newattr
->sticky
!= existattr
->sticky
) {
631 bgp_dest_get_prefix(new->net
), pfx_buf
,
632 sizeof(*pfx_buf
) * PREFIX2STR_BUFFER
);
633 bgp_path_info_path_with_addpath_rx_str(
634 new, new_buf
, sizeof(new_buf
));
635 bgp_path_info_path_with_addpath_rx_str(
636 exist
, exist_buf
, sizeof(exist_buf
));
639 if (newattr
->sticky
&& !existattr
->sticky
) {
640 *reason
= bgp_path_selection_evpn_sticky_mac
;
643 "%s: %s wins over %s due to sticky MAC flag",
644 pfx_buf
, new_buf
, exist_buf
);
648 if (!newattr
->sticky
&& existattr
->sticky
) {
649 *reason
= bgp_path_selection_evpn_sticky_mac
;
652 "%s: %s loses to %s due to sticky MAC flag",
653 pfx_buf
, new_buf
, exist_buf
);
658 new_esi
= bgp_evpn_attr_get_esi(newattr
);
659 exist_esi
= bgp_evpn_attr_get_esi(existattr
);
660 if (bgp_evpn_is_esi_valid(new_esi
) &&
661 !memcmp(new_esi
, exist_esi
, sizeof(esi_t
))) {
667 /* If both paths have the same non-zero ES and
668 * one path is local it wins.
669 * PS: Note the local path wins even if the remote
670 * has the higher MM seq. The local path's
671 * MM seq will be fixed up to match the highest
672 * rem seq, subsequently.
675 char esi_buf
[ESI_STR_LEN
];
677 if (bgp_evpn_is_path_local(bgp
, new)) {
678 *reason
= bgp_path_selection_evpn_local_path
;
681 "%s: %s wins over %s as ES %s is same and local",
682 pfx_buf
, new_buf
, exist_buf
,
683 esi_to_str(new_esi
, esi_buf
,
687 if (bgp_evpn_is_path_local(bgp
, exist
)) {
688 *reason
= bgp_path_selection_evpn_local_path
;
691 "%s: %s loses to %s as ES %s is same and local",
692 pfx_buf
, new_buf
, exist_buf
,
693 esi_to_str(new_esi
, esi_buf
,
699 new_mm_seq
= mac_mobility_seqnum(newattr
);
700 exist_mm_seq
= mac_mobility_seqnum(existattr
);
702 if (new_mm_seq
> exist_mm_seq
) {
703 *reason
= bgp_path_selection_evpn_seq
;
706 "%s: %s wins over %s due to MM seq %u > %u",
707 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
712 if (new_mm_seq
< exist_mm_seq
) {
713 *reason
= bgp_path_selection_evpn_seq
;
716 "%s: %s loses to %s due to MM seq %u < %u",
717 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
722 /* if the sequence numbers and ESI are the same and one path
723 * is non-proxy it wins (over proxy)
725 new_proxy
= bgp_evpn_attr_is_proxy(newattr
);
726 old_proxy
= bgp_evpn_attr_is_proxy(existattr
);
727 if (same_esi
&& bgp_evpn_attr_is_local_es(newattr
) &&
728 old_proxy
!= new_proxy
) {
730 *reason
= bgp_path_selection_evpn_non_proxy
;
733 "%s: %s wins over %s, same seq/es and non-proxy",
734 pfx_buf
, new_buf
, exist_buf
);
738 *reason
= bgp_path_selection_evpn_non_proxy
;
741 "%s: %s loses to %s, same seq/es and non-proxy",
742 pfx_buf
, new_buf
, exist_buf
);
747 * if sequence numbers are the same path with the lowest IP
750 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
752 *reason
= bgp_path_selection_evpn_lower_ip
;
755 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
756 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
757 &new->attr
->nexthop
);
761 *reason
= bgp_path_selection_evpn_lower_ip
;
764 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
765 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
766 &new->attr
->nexthop
);
771 /* 1. Weight check. */
772 new_weight
= newattr
->weight
;
773 exist_weight
= existattr
->weight
;
775 if (new_weight
> exist_weight
) {
776 *reason
= bgp_path_selection_weight
;
778 zlog_debug("%s: %s wins over %s due to weight %d > %d",
779 pfx_buf
, new_buf
, exist_buf
, new_weight
,
784 if (new_weight
< exist_weight
) {
785 *reason
= bgp_path_selection_weight
;
787 zlog_debug("%s: %s loses to %s due to weight %d < %d",
788 pfx_buf
, new_buf
, exist_buf
, new_weight
,
793 /* 2. Local preference check. */
794 new_pref
= exist_pref
= bgp
->default_local_pref
;
796 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
797 new_pref
= newattr
->local_pref
;
798 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
799 exist_pref
= existattr
->local_pref
;
801 if (new_pref
> exist_pref
) {
802 *reason
= bgp_path_selection_local_pref
;
805 "%s: %s wins over %s due to localpref %d > %d",
806 pfx_buf
, new_buf
, exist_buf
, new_pref
,
811 if (new_pref
< exist_pref
) {
812 *reason
= bgp_path_selection_local_pref
;
815 "%s: %s loses to %s due to localpref %d < %d",
816 pfx_buf
, new_buf
, exist_buf
, new_pref
,
821 /* 3. Local route check. We prefer:
823 * - BGP_ROUTE_AGGREGATE
824 * - BGP_ROUTE_REDISTRIBUTE
826 new_origin
= !(new->sub_type
== BGP_ROUTE_NORMAL
||
827 new->sub_type
== BGP_ROUTE_IMPORTED
);
828 exist_origin
= !(exist
->sub_type
== BGP_ROUTE_NORMAL
||
829 exist
->sub_type
== BGP_ROUTE_IMPORTED
);
831 if (new_origin
&& !exist_origin
) {
832 *reason
= bgp_path_selection_local_route
;
835 "%s: %s wins over %s due to preferred BGP_ROUTE type",
836 pfx_buf
, new_buf
, exist_buf
);
840 if (!new_origin
&& exist_origin
) {
841 *reason
= bgp_path_selection_local_route
;
844 "%s: %s loses to %s due to preferred BGP_ROUTE type",
845 pfx_buf
, new_buf
, exist_buf
);
849 /* 4. AS path length check. */
850 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
851 int exist_hops
= aspath_count_hops(existattr
->aspath
);
852 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
854 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
857 aspath_hops
= aspath_count_hops(newattr
->aspath
);
858 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
860 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
861 *reason
= bgp_path_selection_confed_as_path
;
864 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
865 pfx_buf
, new_buf
, exist_buf
,
867 (exist_hops
+ exist_confeds
));
871 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
872 *reason
= bgp_path_selection_confed_as_path
;
875 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
876 pfx_buf
, new_buf
, exist_buf
,
878 (exist_hops
+ exist_confeds
));
882 int newhops
= aspath_count_hops(newattr
->aspath
);
884 if (newhops
< exist_hops
) {
885 *reason
= bgp_path_selection_as_path
;
888 "%s: %s wins over %s due to aspath hopcount %d < %d",
889 pfx_buf
, new_buf
, exist_buf
,
890 newhops
, exist_hops
);
894 if (newhops
> exist_hops
) {
895 *reason
= bgp_path_selection_as_path
;
898 "%s: %s loses to %s due to aspath hopcount %d > %d",
899 pfx_buf
, new_buf
, exist_buf
,
900 newhops
, exist_hops
);
906 /* 5. Origin check. */
907 if (newattr
->origin
< existattr
->origin
) {
908 *reason
= bgp_path_selection_origin
;
910 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
911 pfx_buf
, new_buf
, exist_buf
,
912 bgp_origin_long_str
[newattr
->origin
],
913 bgp_origin_long_str
[existattr
->origin
]);
917 if (newattr
->origin
> existattr
->origin
) {
918 *reason
= bgp_path_selection_origin
;
920 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
921 pfx_buf
, new_buf
, exist_buf
,
922 bgp_origin_long_str
[newattr
->origin
],
923 bgp_origin_long_str
[existattr
->origin
]);
928 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
929 && aspath_count_hops(existattr
->aspath
) == 0);
930 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
931 && aspath_count_confeds(existattr
->aspath
) > 0
932 && aspath_count_hops(newattr
->aspath
) == 0
933 && aspath_count_hops(existattr
->aspath
) == 0);
935 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
936 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
937 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
938 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
939 || internal_as_route
) {
940 new_med
= bgp_med_value(new->attr
, bgp
);
941 exist_med
= bgp_med_value(exist
->attr
, bgp
);
943 if (new_med
< exist_med
) {
944 *reason
= bgp_path_selection_med
;
947 "%s: %s wins over %s due to MED %d < %d",
948 pfx_buf
, new_buf
, exist_buf
, new_med
,
953 if (new_med
> exist_med
) {
954 *reason
= bgp_path_selection_med
;
957 "%s: %s loses to %s due to MED %d > %d",
958 pfx_buf
, new_buf
, exist_buf
, new_med
,
964 /* 7. Peer type check. */
965 new_sort
= new->peer
->sort
;
966 exist_sort
= exist
->peer
->sort
;
968 if (new_sort
== BGP_PEER_EBGP
969 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
970 *reason
= bgp_path_selection_peer
;
973 "%s: %s wins over %s due to eBGP peer > iBGP peer",
974 pfx_buf
, new_buf
, exist_buf
);
978 if (exist_sort
== BGP_PEER_EBGP
979 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
980 *reason
= bgp_path_selection_peer
;
983 "%s: %s loses to %s due to iBGP peer < eBGP peer",
984 pfx_buf
, new_buf
, exist_buf
);
988 /* 8. IGP metric check. */
992 newm
= new->extra
->igpmetric
;
994 existm
= exist
->extra
->igpmetric
;
999 "%s: %s wins over %s due to IGP metric %u < %u",
1000 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1004 if (newm
> existm
) {
1007 "%s: %s loses to %s due to IGP metric %u > %u",
1008 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
1012 /* 9. Same IGP metric. Compare the cluster list length as
1013 representative of IGP hops metric. Rewrite the metric value
1014 pair (newm, existm) with the cluster list length. Prefer the
1015 path with smaller cluster list length. */
1016 if (newm
== existm
) {
1017 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
1018 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
1019 && (mpath_cfg
== NULL
1021 mpath_cfg
->ibgp_flags
,
1022 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
1023 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1024 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1026 if (newm
< existm
) {
1029 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
1030 pfx_buf
, new_buf
, exist_buf
,
1035 if (newm
> existm
) {
1038 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
1039 pfx_buf
, new_buf
, exist_buf
,
1046 /* 10. confed-external vs. confed-internal */
1047 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1048 if (new_sort
== BGP_PEER_CONFED
1049 && exist_sort
== BGP_PEER_IBGP
) {
1050 *reason
= bgp_path_selection_confed
;
1053 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1054 pfx_buf
, new_buf
, exist_buf
);
1058 if (exist_sort
== BGP_PEER_CONFED
1059 && new_sort
== BGP_PEER_IBGP
) {
1060 *reason
= bgp_path_selection_confed
;
1063 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1064 pfx_buf
, new_buf
, exist_buf
);
1069 /* 11. Maximum path check. */
1070 if (newm
== existm
) {
1071 /* If one path has a label but the other does not, do not treat
1072 * them as equals for multipath
1074 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
1076 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
1079 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1080 pfx_buf
, new_buf
, exist_buf
);
1081 } else if (CHECK_FLAG(bgp
->flags
,
1082 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
1085 * For the two paths, all comparison steps till IGP
1087 * have succeeded - including AS_PATH hop count. Since
1089 * bestpath as-path multipath-relax' knob is on, we
1091 * an exact match of AS_PATH. Thus, mark the paths are
1093 * That will trigger both these paths to get into the
1101 "%s: %s and %s are equal via multipath-relax",
1102 pfx_buf
, new_buf
, exist_buf
);
1103 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1104 if (aspath_cmp(new->attr
->aspath
,
1105 exist
->attr
->aspath
)) {
1110 "%s: %s and %s are equal via matching aspaths",
1111 pfx_buf
, new_buf
, exist_buf
);
1113 } else if (new->peer
->as
== exist
->peer
->as
) {
1118 "%s: %s and %s are equal via same remote-as",
1119 pfx_buf
, new_buf
, exist_buf
);
1123 * TODO: If unequal cost ibgp multipath is enabled we can
1124 * mark the paths as equal here instead of returning
1129 "%s: %s wins over %s after IGP metric comparison",
1130 pfx_buf
, new_buf
, exist_buf
);
1133 "%s: %s loses to %s after IGP metric comparison",
1134 pfx_buf
, new_buf
, exist_buf
);
1136 *reason
= bgp_path_selection_igp_metric
;
1140 /* 12. If both paths are external, prefer the path that was received
1141 first (the oldest one). This step minimizes route-flap, since a
1142 newer path won't displace an older one, even if it was the
1143 preferred route based on the additional decision criteria below. */
1144 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1145 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1146 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1147 *reason
= bgp_path_selection_older
;
1150 "%s: %s wins over %s due to oldest external",
1151 pfx_buf
, new_buf
, exist_buf
);
1155 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1156 *reason
= bgp_path_selection_older
;
1159 "%s: %s loses to %s due to oldest external",
1160 pfx_buf
, new_buf
, exist_buf
);
1165 /* 13. Router-ID comparision. */
1166 /* If one of the paths is "stale", the corresponding peer router-id will
1167 * be 0 and would always win over the other path. If originator id is
1168 * used for the comparision, it will decide which path is better.
1170 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1171 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1173 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1174 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1175 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1177 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1179 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1180 *reason
= bgp_path_selection_router_id
;
1183 "%s: %s wins over %s due to Router-ID comparison",
1184 pfx_buf
, new_buf
, exist_buf
);
1188 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1189 *reason
= bgp_path_selection_router_id
;
1192 "%s: %s loses to %s due to Router-ID comparison",
1193 pfx_buf
, new_buf
, exist_buf
);
1197 /* 14. Cluster length comparision. */
1198 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1199 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1201 if (new_cluster
< exist_cluster
) {
1202 *reason
= bgp_path_selection_cluster_length
;
1205 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1206 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1211 if (new_cluster
> exist_cluster
) {
1212 *reason
= bgp_path_selection_cluster_length
;
1215 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1216 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1221 /* 15. Neighbor address comparision. */
1222 /* Do this only if neither path is "stale" as stale paths do not have
1223 * valid peer information (as the connection may or may not be up).
1225 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1226 *reason
= bgp_path_selection_stale
;
1229 "%s: %s wins over %s due to latter path being STALE",
1230 pfx_buf
, new_buf
, exist_buf
);
1234 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1235 *reason
= bgp_path_selection_stale
;
1238 "%s: %s loses to %s due to former path being STALE",
1239 pfx_buf
, new_buf
, exist_buf
);
1243 /* locally configured routes to advertise do not have su_remote */
1244 if (new->peer
->su_remote
== NULL
) {
1245 *reason
= bgp_path_selection_local_configured
;
1248 if (exist
->peer
->su_remote
== NULL
) {
1249 *reason
= bgp_path_selection_local_configured
;
1253 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1256 *reason
= bgp_path_selection_neighbor_ip
;
1259 "%s: %s loses to %s due to Neighor IP comparison",
1260 pfx_buf
, new_buf
, exist_buf
);
1265 *reason
= bgp_path_selection_neighbor_ip
;
1268 "%s: %s wins over %s due to Neighor IP comparison",
1269 pfx_buf
, new_buf
, exist_buf
);
1273 *reason
= bgp_path_selection_default
;
1275 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1276 pfx_buf
, new_buf
, exist_buf
);
1282 int bgp_evpn_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
1283 struct bgp_path_info
*exist
, int *paths_eq
)
1285 enum bgp_path_selection_reason reason
;
1286 char pfx_buf
[PREFIX2STR_BUFFER
];
1288 return bgp_path_info_cmp(bgp
, new, exist
, paths_eq
, NULL
, 0, pfx_buf
,
1289 AFI_L2VPN
, SAFI_EVPN
, &reason
);
1292 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1293 * is preferred, or 0 if they are the same (usually will only occur if
1294 * multipath is enabled
1295 * This version is compatible with */
1296 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1297 struct bgp_path_info
*exist
, char *pfx_buf
,
1298 afi_t afi
, safi_t safi
,
1299 enum bgp_path_selection_reason
*reason
)
1303 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1317 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1318 const struct prefix
*p
,
1319 struct attr
*attr
, afi_t afi
,
1322 struct bgp_filter
*filter
;
1323 enum filter_type ret
= FILTER_PERMIT
;
1325 filter
= &peer
->filter
[afi
][safi
];
1327 #define FILTER_EXIST_WARN(F, f, filter) \
1328 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1329 zlog_debug("%s: Could not find configured input %s-list %s!", \
1330 peer->host, #f, F##_IN_NAME(filter));
1332 if (DISTRIBUTE_IN_NAME(filter
)) {
1333 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1335 if (access_list_apply(DISTRIBUTE_IN(filter
), p
)
1342 if (PREFIX_LIST_IN_NAME(filter
)) {
1343 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1345 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
)
1352 if (FILTER_LIST_IN_NAME(filter
)) {
1353 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1355 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1356 == AS_FILTER_DENY
) {
1363 if (frrtrace_enabled(frr_bgp
, input_filter
)) {
1364 char pfxprint
[PREFIX2STR_BUFFER
];
1366 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1367 frrtrace(5, frr_bgp
, input_filter
, peer
, pfxprint
, afi
, safi
,
1368 ret
== FILTER_PERMIT
? "permit" : "deny");
1372 #undef FILTER_EXIST_WARN
1375 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1376 const struct prefix
*p
,
1377 struct attr
*attr
, afi_t afi
,
1380 struct bgp_filter
*filter
;
1381 enum filter_type ret
= FILTER_PERMIT
;
1383 filter
= &peer
->filter
[afi
][safi
];
1385 #define FILTER_EXIST_WARN(F, f, filter) \
1386 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1387 zlog_debug("%s: Could not find configured output %s-list %s!", \
1388 peer->host, #f, F##_OUT_NAME(filter));
1390 if (DISTRIBUTE_OUT_NAME(filter
)) {
1391 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1393 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
)
1400 if (PREFIX_LIST_OUT_NAME(filter
)) {
1401 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1403 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1410 if (FILTER_LIST_OUT_NAME(filter
)) {
1411 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1413 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1414 == AS_FILTER_DENY
) {
1420 if (frrtrace_enabled(frr_bgp
, output_filter
)) {
1421 char pfxprint
[PREFIX2STR_BUFFER
];
1423 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
1424 frrtrace(5, frr_bgp
, output_filter
, peer
, pfxprint
, afi
, safi
,
1425 ret
== FILTER_PERMIT
? "permit" : "deny");
1430 #undef FILTER_EXIST_WARN
1433 /* If community attribute includes no_export then return 1. */
1434 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1436 if (attr
->community
) {
1437 /* NO_ADVERTISE check. */
1438 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1441 /* NO_EXPORT check. */
1442 if (peer
->sort
== BGP_PEER_EBGP
1443 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1446 /* NO_EXPORT_SUBCONFED check. */
1447 if (peer
->sort
== BGP_PEER_EBGP
1448 || peer
->sort
== BGP_PEER_CONFED
)
1449 if (community_include(attr
->community
,
1450 COMMUNITY_NO_EXPORT_SUBCONFED
))
1456 /* Route reflection loop check. */
1457 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1459 struct in_addr cluster_id
;
1460 struct cluster_list
*cluster
= bgp_attr_get_cluster(attr
);
1463 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1464 cluster_id
= peer
->bgp
->cluster_id
;
1466 cluster_id
= peer
->bgp
->router_id
;
1468 if (cluster_loop_check(cluster
, cluster_id
))
1474 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1475 struct attr
*attr
, afi_t afi
, safi_t safi
,
1476 const char *rmap_name
, mpls_label_t
*label
,
1477 uint32_t num_labels
, struct bgp_dest
*dest
)
1479 struct bgp_filter
*filter
;
1480 struct bgp_path_info rmap_path
= { 0 };
1481 struct bgp_path_info_extra extra
= { 0 };
1482 route_map_result_t ret
;
1483 struct route_map
*rmap
= NULL
;
1485 filter
= &peer
->filter
[afi
][safi
];
1487 /* Apply default weight value. */
1488 if (peer
->weight
[afi
][safi
])
1489 attr
->weight
= peer
->weight
[afi
][safi
];
1492 rmap
= route_map_lookup_by_name(rmap_name
);
1497 if (ROUTE_MAP_IN_NAME(filter
)) {
1498 rmap
= ROUTE_MAP_IN(filter
);
1505 /* Route map apply. */
1507 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1508 /* Duplicate current value to new strucutre for modification. */
1509 rmap_path
.peer
= peer
;
1510 rmap_path
.attr
= attr
;
1511 rmap_path
.extra
= &extra
;
1512 rmap_path
.net
= dest
;
1514 extra
.num_labels
= num_labels
;
1515 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1516 memcpy(extra
.label
, label
,
1517 num_labels
* sizeof(mpls_label_t
));
1519 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1521 /* Apply BGP route map to the attribute. */
1522 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1524 peer
->rmap_type
= 0;
1526 if (ret
== RMAP_DENYMATCH
)
1532 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1533 struct attr
*attr
, afi_t afi
, safi_t safi
,
1534 const char *rmap_name
)
1536 struct bgp_path_info rmap_path
;
1537 route_map_result_t ret
;
1538 struct route_map
*rmap
= NULL
;
1542 * So if we get to this point and have no rmap_name
1543 * we want to just show the output as it currently
1549 /* Apply default weight value. */
1550 if (peer
->weight
[afi
][safi
])
1551 attr
->weight
= peer
->weight
[afi
][safi
];
1553 rmap
= route_map_lookup_by_name(rmap_name
);
1556 * If we have a route map name and we do not find
1557 * the routemap that means we have an implicit
1563 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1564 /* Route map apply. */
1565 /* Duplicate current value to new strucutre for modification. */
1566 rmap_path
.peer
= peer
;
1567 rmap_path
.attr
= attr
;
1569 rmap_type
= peer
->rmap_type
;
1570 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1572 /* Apply BGP route map to the attribute. */
1573 ret
= route_map_apply(rmap
, p
, &rmap_path
);
1575 peer
->rmap_type
= rmap_type
;
1577 if (ret
== RMAP_DENYMATCH
)
1579 * caller has multiple error paths with bgp_attr_flush()
1586 /* If this is an EBGP peer with remove-private-AS */
1587 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1588 struct peer
*peer
, struct attr
*attr
)
1590 if (peer
->sort
== BGP_PEER_EBGP
1591 && (peer_af_flag_check(peer
, afi
, safi
,
1592 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1593 || peer_af_flag_check(peer
, afi
, safi
,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1595 || peer_af_flag_check(peer
, afi
, safi
,
1596 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1597 || peer_af_flag_check(peer
, afi
, safi
,
1598 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1599 // Take action on the entire aspath
1600 if (peer_af_flag_check(peer
, afi
, safi
,
1601 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1602 || peer_af_flag_check(peer
, afi
, safi
,
1603 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1604 if (peer_af_flag_check(
1606 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1607 attr
->aspath
= aspath_replace_private_asns(
1608 attr
->aspath
, bgp
->as
, peer
->as
);
1610 // The entire aspath consists of private ASNs so create
1612 else if (aspath_private_as_check(attr
->aspath
))
1613 attr
->aspath
= aspath_empty_get();
1615 // There are some public and some private ASNs, remove
1618 attr
->aspath
= aspath_remove_private_asns(
1619 attr
->aspath
, peer
->as
);
1622 // 'all' was not specified so the entire aspath must be private
1624 // for us to do anything
1625 else if (aspath_private_as_check(attr
->aspath
)) {
1626 if (peer_af_flag_check(
1628 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1629 attr
->aspath
= aspath_replace_private_asns(
1630 attr
->aspath
, bgp
->as
, peer
->as
);
1632 attr
->aspath
= aspath_empty_get();
1637 /* If this is an EBGP peer with as-override */
1638 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1639 struct peer
*peer
, struct attr
*attr
)
1641 if (peer
->sort
== BGP_PEER_EBGP
1642 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1643 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1644 attr
->aspath
= aspath_replace_specific_asn(
1645 attr
->aspath
, peer
->as
, bgp
->as
);
1649 void bgp_attr_add_gshut_community(struct attr
*attr
)
1651 struct community
*old
;
1652 struct community
*new;
1653 struct community
*merge
;
1654 struct community
*gshut
;
1656 old
= attr
->community
;
1657 gshut
= community_str2com("graceful-shutdown");
1662 merge
= community_merge(community_dup(old
), gshut
);
1664 if (old
->refcnt
== 0)
1665 community_free(&old
);
1667 new = community_uniq_sort(merge
);
1668 community_free(&merge
);
1670 new = community_dup(gshut
);
1673 community_free(&gshut
);
1674 attr
->community
= new;
1675 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1677 /* When we add the graceful-shutdown community we must also
1678 * lower the local-preference */
1679 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1680 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1684 /* Notify BGP Conditional advertisement scanner process. */
1685 void bgp_notify_conditional_adv_scanner(struct update_subgroup
*subgrp
)
1687 struct peer
*temp_peer
;
1688 struct peer
*peer
= SUBGRP_PEER(subgrp
);
1689 struct listnode
*temp_node
, *temp_nnode
= NULL
;
1690 afi_t afi
= SUBGRP_AFI(subgrp
);
1691 safi_t safi
= SUBGRP_SAFI(subgrp
);
1692 struct bgp
*bgp
= SUBGRP_INST(subgrp
);
1693 struct bgp_filter
*filter
= &peer
->filter
[afi
][safi
];
1695 if (!ADVERTISE_MAP_NAME(filter
))
1698 for (ALL_LIST_ELEMENTS(bgp
->peer
, temp_node
, temp_nnode
, temp_peer
)) {
1699 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
1702 if (peer
!= temp_peer
)
1705 temp_peer
->advmap_table_change
= true;
1711 void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1713 if (family
== AF_INET
) {
1714 attr
->nexthop
.s_addr
= INADDR_ANY
;
1715 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1717 if (family
== AF_INET6
)
1718 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1719 if (family
== AF_EVPN
)
1720 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1723 bool subgroup_announce_check(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
1724 struct update_subgroup
*subgrp
,
1725 const struct prefix
*p
, struct attr
*attr
,
1726 bool skip_rmap_check
)
1728 struct bgp_filter
*filter
;
1731 struct peer
*onlypeer
;
1733 struct attr
*piattr
;
1734 route_map_result_t ret
;
1739 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1740 bool nh_reset
= false;
1743 if (DISABLE_BGP_ANNOUNCE
)
1746 afi
= SUBGRP_AFI(subgrp
);
1747 safi
= SUBGRP_SAFI(subgrp
);
1748 peer
= SUBGRP_PEER(subgrp
);
1750 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1751 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1754 filter
= &peer
->filter
[afi
][safi
];
1755 bgp
= SUBGRP_INST(subgrp
);
1756 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1759 #ifdef ENABLE_BGP_VNC
1760 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1761 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1762 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1765 * direct and direct_ext type routes originate internally even
1766 * though they can have peer pointers that reference other
1769 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1775 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1776 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1777 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1778 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1780 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1785 /* With addpath we may be asked to TX all kinds of paths so make sure
1787 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1788 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1789 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1793 /* If this is not the bestpath then check to see if there is an enabled
1795 * feature that requires us to advertise it */
1796 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1797 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1802 /* Aggregate-address suppress check. */
1803 if (bgp_path_suppressed(pi
) && !UNSUPPRESS_MAP_NAME(filter
))
1807 * If we are doing VRF 2 VRF leaking via the import
1808 * statement, we want to prevent the route going
1809 * off box as that the RT and RD created are localy
1810 * significant and globaly useless.
1812 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1813 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1816 /* If it's labeled safi, make sure the route has a valid label. */
1817 if (safi
== SAFI_LABELED_UNICAST
) {
1818 mpls_label_t label
= bgp_adv_label(dest
, pi
, peer
, afi
, safi
);
1819 if (!bgp_is_valid_label(&label
)) {
1820 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1821 zlog_debug("u%" PRIu64
":s%" PRIu64
1822 " %pFX is filtered - no label (%p)",
1823 subgrp
->update_group
->id
, subgrp
->id
,
1829 /* Do not send back route to sender. */
1830 if (onlypeer
&& from
== onlypeer
) {
1834 /* Do not send the default route in the BGP table if the neighbor is
1835 * configured for default-originate */
1836 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1837 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1838 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1840 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1844 /* Transparency check. */
1845 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1846 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1851 /* If community is not disabled check the no-export and local. */
1852 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1853 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1854 zlog_debug("%s: community filter check fail for %pFX",
1859 /* If the attribute has originator-id and it is same as remote
1861 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1862 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1863 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1865 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1870 /* ORF prefix-list filter check */
1871 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1872 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1873 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1874 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1875 if (peer
->orf_plist
[afi
][safi
]) {
1876 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1878 if (bgp_debug_update(NULL
, p
,
1879 subgrp
->update_group
, 0))
1881 "%s [Update:SEND] %pFX is filtered via ORF",
1887 /* Output filter check. */
1888 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1889 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1890 zlog_debug("%s [Update:SEND] %pFX is filtered",
1895 /* AS path loop check. */
1896 if (onlypeer
&& onlypeer
->as_path_loop_detection
1897 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1898 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1900 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
1901 onlypeer
->host
, onlypeer
->as
);
1905 /* If we're a CONFED we need to loop check the CONFED ID too */
1906 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1907 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1908 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1910 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
1911 peer
->host
, bgp
->confed_id
);
1916 /* Route-Reflect check. */
1917 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1922 /* IBGP reflection check. */
1923 if (reflect
&& !samepeer_safe
) {
1924 /* A route from a Client peer. */
1925 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1926 PEER_FLAG_REFLECTOR_CLIENT
)) {
1927 /* Reflect to all the Non-Client peers and also to the
1928 Client peers other than the originator. Originator
1930 is already done. So there is noting to do. */
1931 /* no bgp client-to-client reflection check. */
1932 if (CHECK_FLAG(bgp
->flags
,
1933 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1934 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1935 PEER_FLAG_REFLECTOR_CLIENT
))
1938 /* A route from a Non-client peer. Reflect to all other
1940 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1941 PEER_FLAG_REFLECTOR_CLIENT
))
1946 /* For modify attribute, copy it to temporary structure. */
1949 /* If local-preference is not set. */
1950 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1951 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1952 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1953 attr
->local_pref
= bgp
->default_local_pref
;
1956 /* If originator-id is not set and the route is to be reflected,
1957 set the originator id */
1959 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1960 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1961 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1964 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1966 if (peer
->sort
== BGP_PEER_EBGP
1967 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1968 if (from
!= bgp
->peer_self
&& !transparent
1969 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1970 PEER_FLAG_MED_UNCHANGED
))
1972 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1975 /* Since the nexthop attribute can vary per peer, it is not explicitly
1977 * in announce check, only certain flags and length (or number of
1979 * -- for IPv6/MP_REACH) are set here in order to guide the update
1981 * code in setting the nexthop(s) on a per peer basis in
1983 * Typically, the source nexthop in the attribute is preserved but in
1985 * scenarios where we know it will always be overwritten, we reset the
1986 * nexthop to "0" in an attempt to achieve better Update packing. An
1987 * example of this is when a prefix from each of 2 IBGP peers needs to
1989 * announced to an EBGP peer (and they have the same attributes barring
1993 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1995 #define NEXTHOP_IS_V6 \
1996 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1997 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1998 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1999 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2001 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2003 * the peer (group) is configured to receive link-local nexthop
2005 * and it is available in the prefix OR we're not reflecting the route,
2006 * link-local nexthop address is valid and
2007 * the peer (group) to whom we're going to announce is on a shared
2009 * and this is either a self-originated route or the peer is EBGP.
2010 * By checking if nexthop LL address is valid we are sure that
2011 * we do not announce LL address as `::`.
2013 if (NEXTHOP_IS_V6
) {
2014 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
2015 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2016 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
2017 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
2019 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
2020 && peer
->shared_network
2021 && (from
== bgp
->peer_self
2022 || peer
->sort
== BGP_PEER_EBGP
))) {
2023 attr
->mp_nexthop_len
=
2024 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
2027 /* Clear off link-local nexthop in source, whenever it is not
2029 * ensure more prefixes share the same attribute for
2032 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2033 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
2034 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
2037 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
2038 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
2040 /* Route map & unsuppress-map apply. */
2041 if (!skip_rmap_check
2042 && (ROUTE_MAP_OUT_NAME(filter
) || bgp_path_suppressed(pi
))) {
2043 struct bgp_path_info rmap_path
= {0};
2044 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
2045 struct attr dummy_attr
= {0};
2047 /* Fill temp path_info */
2048 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
, dest
,
2051 /* don't confuse inbound and outbound setting */
2052 RESET_FLAG(attr
->rmap_change_flags
);
2055 * The route reflector is not allowed to modify the attributes
2056 * of the reflected IBGP routes unless explicitly allowed.
2058 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
2059 && !CHECK_FLAG(bgp
->flags
,
2060 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
2062 rmap_path
.attr
= &dummy_attr
;
2065 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
2067 if (bgp_path_suppressed(pi
))
2068 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
2071 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
2074 peer
->rmap_type
= 0;
2076 if (ret
== RMAP_DENYMATCH
) {
2077 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2079 "%s [Update:SEND] %pFX is filtered by route-map",
2082 bgp_attr_flush(attr
);
2087 /* RFC 8212 to prevent route leaks.
2088 * This specification intends to improve this situation by requiring the
2089 * explicit configuration of both BGP Import and Export Policies for any
2090 * External BGP (EBGP) session such as customers, peers, or
2091 * confederation boundaries for all enabled address families. Through
2092 * codification of the aforementioned requirement, operators will
2093 * benefit from consistent behavior across different BGP
2096 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
2097 if (!bgp_outbound_policy_exists(peer
, filter
))
2100 /* draft-ietf-idr-deprecate-as-set-confed-set
2101 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2102 * Eventually, This document (if approved) updates RFC 4271
2103 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2104 * and obsoletes RFC 6472.
2106 if (peer
->bgp
->reject_as_sets
)
2107 if (aspath_check_as_sets(attr
->aspath
))
2110 /* Codification of AS 0 Processing */
2111 if (aspath_check_as_zero(attr
->aspath
))
2114 if (bgp_in_graceful_shutdown(bgp
)) {
2115 if (peer
->sort
== BGP_PEER_IBGP
2116 || peer
->sort
== BGP_PEER_CONFED
) {
2117 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2118 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
2120 bgp_attr_add_gshut_community(attr
);
2124 /* After route-map has been applied, we check to see if the nexthop to
2125 * be carried in the attribute (that is used for the announcement) can
2126 * be cleared off or not. We do this in all cases where we would be
2127 * setting the nexthop to "ourselves". For IPv6, we only need to
2129 * the global nexthop here; the link-local nexthop would have been
2131 * already, and if not, it is required by the update formation code.
2132 * Also see earlier comments in this function.
2135 * If route-map has performed some operation on the nexthop or the peer
2136 * configuration says to pass it unchanged, we cannot reset the nexthop
2137 * here, so only attempt to do it if these aren't true. Note that the
2138 * route-map handler itself might have cleared the nexthop, if for
2140 * it is configured as 'peer-address'.
2142 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
2143 piattr
->rmap_change_flags
)
2145 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2146 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
2147 /* We can reset the nexthop, if setting (or forcing) it to
2149 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2150 PEER_FLAG_NEXTHOP_SELF
)
2151 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2152 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2154 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2155 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
2156 subgroup_announce_reset_nhop(
2157 (peer_cap_enhe(peer
, afi
, safi
)
2163 } else if (peer
->sort
== BGP_PEER_EBGP
) {
2164 /* Can also reset the nexthop if announcing to EBGP, but
2166 * no peer in the subgroup is on a shared subnet.
2167 * Note: 3rd party nexthop currently implemented for
2170 if ((p
->family
== AF_INET
) &&
2171 (!bgp_subgrp_multiaccess_check_v4(
2174 subgroup_announce_reset_nhop(
2175 (peer_cap_enhe(peer
, afi
, safi
)
2182 if ((p
->family
== AF_INET6
) &&
2183 (!bgp_subgrp_multiaccess_check_v6(
2184 piattr
->mp_nexthop_global
,
2186 subgroup_announce_reset_nhop(
2187 (peer_cap_enhe(peer
, afi
, safi
)
2196 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2198 * This flag is used for leaked vpn-vrf routes
2200 int family
= p
->family
;
2202 if (peer_cap_enhe(peer
, afi
, safi
))
2205 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2207 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2208 __func__
, family2str(family
));
2209 subgroup_announce_reset_nhop(family
, attr
);
2214 /* If IPv6/MP and nexthop does not have any override and happens
2216 * be a link-local address, reset it so that we don't pass along
2218 * source's link-local IPv6 address to recipients who may not be
2220 * the same interface.
2222 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2223 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
)) {
2224 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2230 * When the next hop is set to ourselves, if all multipaths have
2231 * link-bandwidth announce the cumulative bandwidth as that makes
2232 * the most sense. However, don't modify if the link-bandwidth has
2233 * been explicitly set by user policy.
2236 bgp_path_info_mpath_chkwtd(bgp
, pi
) &&
2237 (cum_bw
= bgp_path_info_mpath_cumbw(pi
)) != 0 &&
2238 !CHECK_FLAG(attr
->rmap_change_flags
, BATTR_RMAP_LINK_BW_SET
))
2239 attr
->ecommunity
= ecommunity_replace_linkbw(
2240 bgp
->as
, attr
->ecommunity
, cum_bw
);
2245 static int bgp_route_select_timer_expire(struct thread
*thread
)
2247 struct afi_safi_info
*info
;
2252 info
= THREAD_ARG(thread
);
2257 if (BGP_DEBUG(update
, UPDATE_OUT
))
2258 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2261 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2263 XFREE(MTYPE_TMP
, info
);
2265 /* Best path selection */
2266 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2269 void bgp_best_selection(struct bgp
*bgp
, struct bgp_dest
*dest
,
2270 struct bgp_maxpaths_cfg
*mpath_cfg
,
2271 struct bgp_path_info_pair
*result
, afi_t afi
,
2274 struct bgp_path_info
*new_select
;
2275 struct bgp_path_info
*old_select
;
2276 struct bgp_path_info
*pi
;
2277 struct bgp_path_info
*pi1
;
2278 struct bgp_path_info
*pi2
;
2279 struct bgp_path_info
*nextpi
= NULL
;
2280 int paths_eq
, do_mpath
, debug
;
2281 struct list mp_list
;
2282 char pfx_buf
[PREFIX2STR_BUFFER
];
2283 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2285 bgp_mp_list_init(&mp_list
);
2287 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2289 debug
= bgp_debug_bestpath(dest
);
2292 prefix2str(bgp_dest_get_prefix(dest
), pfx_buf
, sizeof(pfx_buf
));
2294 dest
->reason
= bgp_path_selection_none
;
2295 /* bgp deterministic-med */
2297 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2299 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2300 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2302 bgp_path_info_unset_flag(dest
, pi1
,
2303 BGP_PATH_DMED_SELECTED
);
2305 for (pi1
= bgp_dest_get_bgp_path_info(dest
); pi1
;
2307 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2309 if (BGP_PATH_HOLDDOWN(pi1
))
2311 if (pi1
->peer
!= bgp
->peer_self
)
2312 if (pi1
->peer
->status
!= Established
)
2317 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2318 if (CHECK_FLAG(pi2
->flags
,
2319 BGP_PATH_DMED_CHECK
))
2321 if (BGP_PATH_HOLDDOWN(pi2
))
2323 if (pi2
->peer
!= bgp
->peer_self
2326 PEER_STATUS_NSF_WAIT
))
2327 if (pi2
->peer
->status
2331 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2333 && !aspath_cmp_left_confed(
2338 if (bgp_path_info_cmp(
2339 bgp
, pi2
, new_select
,
2340 &paths_eq
, mpath_cfg
, debug
,
2343 bgp_path_info_unset_flag(
2345 BGP_PATH_DMED_SELECTED
);
2349 bgp_path_info_set_flag(
2350 dest
, pi2
, BGP_PATH_DMED_CHECK
);
2353 bgp_path_info_set_flag(dest
, new_select
,
2354 BGP_PATH_DMED_CHECK
);
2355 bgp_path_info_set_flag(dest
, new_select
,
2356 BGP_PATH_DMED_SELECTED
);
2359 bgp_path_info_path_with_addpath_rx_str(
2360 new_select
, path_buf
, sizeof(path_buf
));
2362 "%pBD: %s is the bestpath from AS %u",
2364 aspath_get_first_as(
2365 new_select
->attr
->aspath
));
2370 /* Check old selected route and new selected route. */
2373 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2374 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2375 enum bgp_path_selection_reason reason
;
2377 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2380 if (BGP_PATH_HOLDDOWN(pi
)) {
2381 /* reap REMOVED routes, if needs be
2382 * selected route must stay for a while longer though
2384 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2385 && (pi
!= old_select
))
2386 bgp_path_info_reap(dest
, pi
);
2389 zlog_debug("%s: pi %p in holddown", __func__
,
2395 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2396 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2397 if (pi
->peer
->status
!= Established
) {
2401 "%s: pi %p non self peer %s not estab state",
2402 __func__
, pi
, pi
->peer
->host
);
2407 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2408 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2409 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2411 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2415 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_DMED_CHECK
);
2417 reason
= dest
->reason
;
2418 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2419 debug
, pfx_buf
, afi
, safi
,
2421 if (new_select
== NULL
&&
2422 reason
!= bgp_path_selection_none
)
2423 dest
->reason
= reason
;
2428 /* Now that we know which path is the bestpath see if any of the other
2430 * qualify as multipaths
2434 bgp_path_info_path_with_addpath_rx_str(
2435 new_select
, path_buf
, sizeof(path_buf
));
2437 snprintf(path_buf
, sizeof(path_buf
), "NONE");
2439 "%pBD: After path selection, newbest is %s oldbest was %s",
2441 old_select
? old_select
->peer
->host
: "NONE");
2444 if (do_mpath
&& new_select
) {
2445 for (pi
= bgp_dest_get_bgp_path_info(dest
);
2446 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2449 bgp_path_info_path_with_addpath_rx_str(
2450 pi
, path_buf
, sizeof(path_buf
));
2452 if (pi
== new_select
) {
2455 "%pBD: %s is the bestpath, add to the multipath list",
2457 bgp_mp_list_add(&mp_list
, pi
);
2461 if (BGP_PATH_HOLDDOWN(pi
))
2464 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2465 && !CHECK_FLAG(pi
->peer
->sflags
,
2466 PEER_STATUS_NSF_WAIT
))
2467 if (pi
->peer
->status
!= Established
)
2470 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2473 "%pBD: %s has the same nexthop as the bestpath, skip it",
2478 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2479 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2485 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2487 bgp_mp_list_add(&mp_list
, pi
);
2492 bgp_path_info_mpath_update(dest
, new_select
, old_select
, &mp_list
,
2494 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2495 bgp_mp_list_clear(&mp_list
);
2497 bgp_addpath_update_ids(bgp
, dest
, afi
, safi
);
2499 result
->old
= old_select
;
2500 result
->new = new_select
;
2506 * A new route/change in bestpath of an existing route. Evaluate the path
2507 * for advertisement to the subgroup.
2509 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2510 struct bgp_path_info
*selected
,
2511 struct bgp_dest
*dest
,
2512 uint32_t addpath_tx_id
)
2514 const struct prefix
*p
;
2515 struct peer
*onlypeer
;
2522 p
= bgp_dest_get_prefix(dest
);
2523 afi
= SUBGRP_AFI(subgrp
);
2524 safi
= SUBGRP_SAFI(subgrp
);
2525 bgp
= SUBGRP_INST(subgrp
);
2526 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2529 if (BGP_DEBUG(update
, UPDATE_OUT
))
2530 zlog_debug("%s: p=%pFX, selected=%p", __func__
, p
, selected
);
2532 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2533 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2534 PEER_STATUS_ORF_WAIT_REFRESH
))
2537 memset(&attr
, 0, sizeof(struct attr
));
2538 /* It's initialized in bgp_announce_check() */
2540 /* Announcement to the subgroup. If the route is filtered withdraw it.
2541 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2542 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2545 advertise
= bgp_check_advertise(bgp
, dest
);
2548 if (subgroup_announce_check(dest
, selected
, subgrp
, p
, &attr
,
2550 /* Route is selected, if the route is already installed
2551 * in FIB, then it is advertised
2554 bgp_adj_out_set_subgroup(dest
, subgrp
, &attr
,
2557 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1,
2561 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2563 bgp_adj_out_unset_subgroup(dest
, subgrp
, 1, addpath_tx_id
);
2568 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2569 * This is called at the end of route processing.
2571 void bgp_zebra_clear_route_change_flags(struct bgp_dest
*dest
)
2573 struct bgp_path_info
*pi
;
2575 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2576 if (BGP_PATH_HOLDDOWN(pi
))
2578 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2579 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2584 * Has the route changed from the RIB's perspective? This is invoked only
2585 * if the route selection returns the same best route as earlier - to
2586 * determine if we need to update zebra or not.
2588 bool bgp_zebra_has_route_changed(struct bgp_path_info
*selected
)
2590 struct bgp_path_info
*mpinfo
;
2592 /* If this is multipath, check all selected paths for any nexthop
2593 * change or attribute change. Some attribute changes (e.g., community)
2594 * aren't of relevance to the RIB, but we'll update zebra to ensure
2595 * we handle the case of BGP nexthop change. This is the behavior
2596 * when the best path has an attribute change anyway.
2598 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2599 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
)
2600 || CHECK_FLAG(selected
->flags
, BGP_PATH_LINK_BW_CHG
))
2604 * If this is multipath, check all selected paths for any nexthop change
2606 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2607 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2608 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2609 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2613 /* Nothing has changed from the RIB's perspective. */
2617 struct bgp_process_queue
{
2619 STAILQ_HEAD(, bgp_dest
) pqueue
;
2620 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2622 unsigned int queued
;
2625 static void bgp_process_evpn_route_injection(struct bgp
*bgp
, afi_t afi
,
2626 safi_t safi
, struct bgp_dest
*dest
,
2627 struct bgp_path_info
*new_select
,
2628 struct bgp_path_info
*old_select
)
2630 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2632 if ((afi
!= AFI_IP
&& afi
!= AFI_IP6
) || (safi
!= SAFI_UNICAST
))
2635 if (advertise_type5_routes(bgp
, afi
) && new_select
2636 && is_route_injectable_into_evpn(new_select
)) {
2638 /* apply the route-map */
2639 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2640 route_map_result_t ret
;
2641 struct bgp_path_info rmap_path
;
2642 struct bgp_path_info_extra rmap_path_extra
;
2643 struct attr dummy_attr
;
2645 dummy_attr
= *new_select
->attr
;
2647 /* Fill temp path_info */
2648 prep_for_rmap_apply(&rmap_path
, &rmap_path_extra
, dest
,
2649 new_select
, new_select
->peer
,
2652 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2654 ret
= route_map_apply(bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2657 if (ret
== RMAP_DENYMATCH
) {
2658 bgp_attr_flush(&dummy_attr
);
2659 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
,
2662 bgp_evpn_advertise_type5_route(
2663 bgp
, p
, &dummy_attr
, afi
, safi
);
2665 bgp_evpn_advertise_type5_route(bgp
, p
, new_select
->attr
,
2668 } else if (advertise_type5_routes(bgp
, afi
) && old_select
2669 && is_route_injectable_into_evpn(old_select
))
2670 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2674 * old_select = The old best path
2675 * new_select = the new best path
2677 * if (!old_select && new_select)
2678 * We are sending new information on.
2680 * if (old_select && new_select) {
2681 * if (new_select != old_select)
2682 * We have a new best path send a change
2684 * We've received a update with new attributes that needs
2688 * if (old_select && !new_select)
2689 * We have no eligible route that we can announce or the rn
2692 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_dest
*dest
,
2693 afi_t afi
, safi_t safi
)
2695 struct bgp_path_info
*new_select
;
2696 struct bgp_path_info
*old_select
;
2697 struct bgp_path_info_pair old_and_new
;
2700 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2702 debug
= bgp_debug_bestpath(dest
);
2705 "%s: bgp delete in progress, ignoring event, p=%pBD",
2709 /* Is it end of initial update? (after startup) */
2711 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2712 sizeof(bgp
->update_delay_zebra_resume_time
));
2714 bgp
->main_zebra_update_hold
= 0;
2715 FOREACH_AFI_SAFI (afi
, safi
) {
2716 if (bgp_fibupd_safi(safi
))
2717 bgp_zebra_announce_table(bgp
, afi
, safi
);
2719 bgp
->main_peers_update_hold
= 0;
2721 bgp_start_routeadv(bgp
);
2725 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2727 debug
= bgp_debug_bestpath(dest
);
2729 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__
, dest
,
2730 afi2str(afi
), safi2str(safi
));
2732 /* The best path calculation for the route is deferred if
2733 * BGP_NODE_SELECT_DEFER is set
2735 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
2736 if (BGP_DEBUG(update
, UPDATE_OUT
))
2737 zlog_debug("SELECT_DEFER flag set for route %p", dest
);
2741 /* Best path selection. */
2742 bgp_best_selection(bgp
, dest
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2744 old_select
= old_and_new
.old
;
2745 new_select
= old_and_new
.new;
2747 /* Do we need to allocate or free labels?
2748 * Right now, since we only deal with per-prefix labels, it is not
2749 * necessary to do this upon changes to best path. Exceptions:
2750 * - label index has changed -> recalculate resulting label
2751 * - path_info sub_type changed -> switch to/from implicit-null
2752 * - no valid label (due to removed static label binding) -> get new one
2754 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2757 || bgp_label_index_differs(new_select
, old_select
)
2758 || new_select
->sub_type
!= old_select
->sub_type
2759 || !bgp_is_valid_label(&dest
->local_label
)) {
2760 /* Enforced penultimate hop popping:
2761 * implicit-null for local routes, aggregate
2762 * and redistributed routes
2764 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2765 || new_select
->sub_type
2766 == BGP_ROUTE_AGGREGATE
2767 || new_select
->sub_type
2768 == BGP_ROUTE_REDISTRIBUTE
) {
2771 BGP_NODE_REGISTERED_FOR_LABEL
)
2774 BGP_NODE_LABEL_REQUESTED
))
2775 bgp_unregister_for_label(dest
);
2776 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2777 &dest
->local_label
);
2778 bgp_set_valid_label(&dest
->local_label
);
2780 bgp_register_for_label(dest
,
2783 } else if (CHECK_FLAG(dest
->flags
,
2784 BGP_NODE_REGISTERED_FOR_LABEL
)
2785 || CHECK_FLAG(dest
->flags
,
2786 BGP_NODE_LABEL_REQUESTED
)) {
2787 bgp_unregister_for_label(dest
);
2789 } else if (CHECK_FLAG(dest
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)
2790 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_REQUESTED
)) {
2791 bgp_unregister_for_label(dest
);
2796 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
2797 __func__
, dest
, afi2str(afi
), safi2str(safi
),
2798 old_select
, new_select
);
2800 /* If best route remains the same and this is not due to user-initiated
2801 * clear, see exactly what needs to be done.
2803 if (old_select
&& old_select
== new_select
2804 && !CHECK_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
)
2805 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2806 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2807 if (bgp_zebra_has_route_changed(old_select
)) {
2808 #ifdef ENABLE_BGP_VNC
2809 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2810 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2812 if (bgp_fibupd_safi(safi
)
2813 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2815 if (new_select
->type
== ZEBRA_ROUTE_BGP
2816 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2817 || new_select
->sub_type
2818 == BGP_ROUTE_IMPORTED
))
2820 bgp_zebra_announce(dest
, p
, old_select
,
2825 /* If there is a change of interest to peers, reannounce the
2827 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2828 || CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2829 || CHECK_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2830 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2832 /* unicast routes must also be annouced to
2833 * labeled-unicast update-groups */
2834 if (safi
== SAFI_UNICAST
)
2835 group_announce_route(bgp
, afi
,
2836 SAFI_LABELED_UNICAST
, dest
,
2839 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2840 UNSET_FLAG(dest
->flags
, BGP_NODE_LABEL_CHANGED
);
2843 /* advertise/withdraw type-5 routes */
2844 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
)
2845 || CHECK_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
))
2846 bgp_process_evpn_route_injection(
2847 bgp
, afi
, safi
, dest
, old_select
, old_select
);
2849 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2850 UNSET_FLAG(old_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2851 bgp_zebra_clear_route_change_flags(dest
);
2852 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2856 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2858 UNSET_FLAG(dest
->flags
, BGP_NODE_USER_CLEAR
);
2860 /* bestpath has changed; bump version */
2861 if (old_select
|| new_select
) {
2862 bgp_bump_version(dest
);
2864 if (!bgp
->t_rmap_def_originate_eval
) {
2868 update_group_refresh_default_originate_route_map
,
2869 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2870 &bgp
->t_rmap_def_originate_eval
);
2875 bgp_path_info_unset_flag(dest
, old_select
, BGP_PATH_SELECTED
);
2878 zlog_debug("%s: setting SELECTED flag", __func__
);
2879 bgp_path_info_set_flag(dest
, new_select
, BGP_PATH_SELECTED
);
2880 bgp_path_info_unset_flag(dest
, new_select
,
2881 BGP_PATH_ATTR_CHANGED
);
2882 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2883 UNSET_FLAG(new_select
->flags
, BGP_PATH_LINK_BW_CHG
);
2886 #ifdef ENABLE_BGP_VNC
2887 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2888 if (old_select
!= new_select
) {
2890 vnc_import_bgp_exterior_del_route(bgp
, p
,
2892 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2895 vnc_import_bgp_exterior_add_route(bgp
, p
,
2897 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2903 group_announce_route(bgp
, afi
, safi
, dest
, new_select
);
2905 /* unicast routes must also be annouced to labeled-unicast update-groups
2907 if (safi
== SAFI_UNICAST
)
2908 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, dest
,
2912 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2913 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2914 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2915 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2916 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2917 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2919 /* if this is an evpn imported type-5 prefix,
2920 * we need to withdraw the route first to clear
2921 * the nh neigh and the RMAC entry.
2924 is_route_parent_evpn(old_select
))
2925 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2927 bgp_zebra_announce(dest
, p
, new_select
, bgp
, afi
, safi
);
2929 /* Withdraw the route from the kernel. */
2930 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2931 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2932 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2933 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2935 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2939 bgp_process_evpn_route_injection(bgp
, afi
, safi
, dest
, new_select
,
2942 /* Clear any route change flags. */
2943 bgp_zebra_clear_route_change_flags(dest
);
2945 /* Reap old select bgp_path_info, if it has been removed */
2946 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2947 bgp_path_info_reap(dest
, old_select
);
2949 UNSET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2953 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2954 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2956 struct bgp_dest
*dest
;
2958 struct afi_safi_info
*thread_info
;
2960 if (bgp
->gr_info
[afi
][safi
].t_route_select
) {
2961 struct thread
*t
= bgp
->gr_info
[afi
][safi
].t_route_select
;
2963 thread_info
= THREAD_ARG(t
);
2964 XFREE(MTYPE_TMP
, thread_info
);
2965 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2968 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2969 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2970 get_afi_safi_str(afi
, safi
, false),
2971 bgp
->gr_info
[afi
][safi
].gr_deferred
);
2974 /* Process the route list */
2975 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]);
2976 dest
&& bgp
->gr_info
[afi
][safi
].gr_deferred
!= 0;
2977 dest
= bgp_route_next(dest
)) {
2978 if (!CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
))
2981 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
2982 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
2983 bgp_process_main_one(bgp
, dest
, afi
, safi
);
2985 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
) {
2986 bgp_dest_unlock_node(dest
);
2991 /* Send EOR message when all routes are processed */
2992 if (!bgp
->gr_info
[afi
][safi
].gr_deferred
) {
2993 bgp_send_delayed_eor(bgp
);
2994 /* Send route processing complete message to RIB */
2995 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2996 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
3000 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
3002 thread_info
->afi
= afi
;
3003 thread_info
->safi
= safi
;
3004 thread_info
->bgp
= bgp
;
3006 /* If there are more routes to be processed, start the
3009 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
3010 BGP_ROUTE_SELECT_DELAY
,
3011 &bgp
->gr_info
[afi
][safi
].t_route_select
);
3015 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
3017 struct bgp_process_queue
*pqnode
= data
;
3018 struct bgp
*bgp
= pqnode
->bgp
;
3019 struct bgp_table
*table
;
3020 struct bgp_dest
*dest
;
3023 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
3024 bgp_process_main_one(bgp
, NULL
, 0, 0);
3025 /* should always have dedicated wq call */
3026 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
3030 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
3031 dest
= STAILQ_FIRST(&pqnode
->pqueue
);
3032 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
3033 STAILQ_NEXT(dest
, pq
) = NULL
; /* complete unlink */
3034 table
= bgp_dest_table(dest
);
3035 /* note, new DESTs may be added as part of processing */
3036 bgp_process_main_one(bgp
, dest
, table
->afi
, table
->safi
);
3038 bgp_dest_unlock_node(dest
);
3039 bgp_table_unlock(table
);
3045 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
3047 struct bgp_process_queue
*pqnode
= data
;
3049 bgp_unlock(pqnode
->bgp
);
3051 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
3054 void bgp_process_queue_init(struct bgp
*bgp
)
3056 if (!bgp
->process_queue
) {
3059 snprintf(name
, BUFSIZ
, "process_queue %s", bgp
->name_pretty
);
3060 bgp
->process_queue
= work_queue_new(bm
->master
, name
);
3063 bgp
->process_queue
->spec
.workfunc
= &bgp_process_wq
;
3064 bgp
->process_queue
->spec
.del_item_data
= &bgp_processq_del
;
3065 bgp
->process_queue
->spec
.max_retries
= 0;
3066 bgp
->process_queue
->spec
.hold
= 50;
3067 /* Use a higher yield value of 50ms for main queue processing */
3068 bgp
->process_queue
->spec
.yield
= 50 * 1000L;
3071 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
3073 struct bgp_process_queue
*pqnode
;
3075 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
3076 sizeof(struct bgp_process_queue
));
3078 /* unlocked in bgp_processq_del */
3079 pqnode
->bgp
= bgp_lock(bgp
);
3080 STAILQ_INIT(&pqnode
->pqueue
);
3085 void bgp_process(struct bgp
*bgp
, struct bgp_dest
*dest
, afi_t afi
, safi_t safi
)
3087 #define ARBITRARY_PROCESS_QLEN 10000
3088 struct work_queue
*wq
= bgp
->process_queue
;
3089 struct bgp_process_queue
*pqnode
;
3090 int pqnode_reuse
= 0;
3092 /* already scheduled for processing? */
3093 if (CHECK_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
3096 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3099 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3100 if (BGP_DEBUG(update
, UPDATE_OUT
))
3101 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
3109 /* Add route nodes to an existing work queue item until reaching the
3110 limit only if is from the same BGP view and it's not an EOIU marker
3112 if (work_queue_item_count(wq
)) {
3113 struct work_queue_item
*item
= work_queue_last_item(wq
);
3114 pqnode
= item
->data
;
3116 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
3117 || pqnode
->bgp
!= bgp
3118 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
3119 pqnode
= bgp_processq_alloc(bgp
);
3123 pqnode
= bgp_processq_alloc(bgp
);
3124 /* all unlocked in bgp_process_wq */
3125 bgp_table_lock(bgp_dest_table(dest
));
3127 SET_FLAG(dest
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
3128 bgp_dest_lock_node(dest
);
3130 /* can't be enqueued twice */
3131 assert(STAILQ_NEXT(dest
, pq
) == NULL
);
3132 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, dest
, pq
);
3136 work_queue_add(wq
, pqnode
);
3141 void bgp_add_eoiu_mark(struct bgp
*bgp
)
3143 struct bgp_process_queue
*pqnode
;
3145 if (bgp
->process_queue
== NULL
)
3148 pqnode
= bgp_processq_alloc(bgp
);
3150 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
3151 work_queue_add(bgp
->process_queue
, pqnode
);
3154 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
3158 peer
= THREAD_ARG(thread
);
3159 peer
->t_pmax_restart
= NULL
;
3161 if (bgp_debug_neighbor_events(peer
))
3163 "%s Maximum-prefix restart timer expired, restore peering",
3166 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
3167 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
3172 static uint32_t bgp_filtered_routes_count(struct peer
*peer
, afi_t afi
,
3176 bool filtered
= false;
3177 struct bgp_dest
*dest
;
3178 struct bgp_adj_in
*ain
;
3179 struct attr attr
= {};
3180 struct bgp_table
*table
= peer
->bgp
->rib
[afi
][safi
];
3182 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
3183 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
3184 const struct prefix
*rn_p
= bgp_dest_get_prefix(dest
);
3188 if (bgp_input_filter(peer
, rn_p
, &attr
, afi
, safi
)
3192 if (bgp_input_modifier(
3193 peer
, rn_p
, &attr
, afi
, safi
,
3194 ROUTE_MAP_IN_NAME(&peer
->filter
[afi
][safi
]),
3202 bgp_attr_undup(&attr
, ain
->attr
);
3209 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
3213 iana_safi_t pkt_safi
;
3214 uint32_t pcount
= (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3215 PEER_FLAG_MAX_PREFIX_FORCE
))
3216 ? bgp_filtered_routes_count(peer
, afi
, safi
)
3217 + peer
->pcount
[afi
][safi
]
3218 : peer
->pcount
[afi
][safi
];
3220 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
3223 if (pcount
> peer
->pmax
[afi
][safi
]) {
3224 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3225 PEER_STATUS_PREFIX_LIMIT
)
3230 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
3231 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3232 peer
->pmax
[afi
][safi
]);
3233 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
3235 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
3236 PEER_FLAG_MAX_PREFIX_WARNING
))
3239 /* Convert AFI, SAFI to values for packet. */
3240 pkt_afi
= afi_int2iana(afi
);
3241 pkt_safi
= safi_int2iana(safi
);
3245 ndata
[0] = (pkt_afi
>> 8);
3247 ndata
[2] = pkt_safi
;
3248 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
3249 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
3250 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
3251 ndata
[6] = (peer
->pmax
[afi
][safi
]);
3253 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
3254 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
3255 BGP_NOTIFY_CEASE_MAX_PREFIX
,
3259 /* Dynamic peers will just close their connection. */
3260 if (peer_dynamic_neighbor(peer
))
3263 /* restart timer start */
3264 if (peer
->pmax_restart
[afi
][safi
]) {
3265 peer
->v_pmax_restart
=
3266 peer
->pmax_restart
[afi
][safi
] * 60;
3268 if (bgp_debug_neighbor_events(peer
))
3270 "%s Maximum-prefix restart timer started for %d secs",
3271 peer
->host
, peer
->v_pmax_restart
);
3273 BGP_TIMER_ON(peer
->t_pmax_restart
,
3274 bgp_maximum_prefix_restart_timer
,
3275 peer
->v_pmax_restart
);
3280 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3281 PEER_STATUS_PREFIX_LIMIT
);
3284 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3285 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3286 PEER_STATUS_PREFIX_THRESHOLD
)
3291 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
3292 get_afi_safi_str(afi
, safi
, false), peer
->host
, pcount
,
3293 peer
->pmax
[afi
][safi
]);
3294 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3295 PEER_STATUS_PREFIX_THRESHOLD
);
3297 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3298 PEER_STATUS_PREFIX_THRESHOLD
);
3302 /* Unconditionally remove the route from the RIB, without taking
3303 * damping into consideration (eg, because the session went down)
3305 void bgp_rib_remove(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3306 struct peer
*peer
, afi_t afi
, safi_t safi
)
3309 struct bgp
*bgp
= NULL
;
3310 bool delete_route
= false;
3312 bgp_aggregate_decrement(peer
->bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
3315 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3316 bgp_path_info_delete(dest
, pi
); /* keep historical info */
3318 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3321 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3322 delete_route
= true;
3323 else if (bgp_dest_set_defer_flag(dest
, true) < 0)
3324 delete_route
= true;
3326 if (CHECK_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
)) {
3327 UNSET_FLAG(dest
->flags
, BGP_NODE_SELECT_DEFER
);
3328 bgp
= pi
->peer
->bgp
;
3329 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
3334 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, dest
, peer
, true);
3335 bgp_process(peer
->bgp
, dest
, afi
, safi
);
3338 static void bgp_rib_withdraw(struct bgp_dest
*dest
, struct bgp_path_info
*pi
,
3339 struct peer
*peer
, afi_t afi
, safi_t safi
,
3340 struct prefix_rd
*prd
)
3342 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3344 /* apply dampening, if result is suppressed, we'll be retaining
3345 * the bgp_path_info in the RIB for historical reference.
3347 if (peer
->sort
== BGP_PEER_EBGP
) {
3348 if (get_active_bdc_from_pi(pi
, afi
, safi
)) {
3349 if (bgp_damp_withdraw(pi
, dest
, afi
, safi
, 0)
3350 == BGP_DAMP_SUPPRESSED
) {
3351 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3358 #ifdef ENABLE_BGP_VNC
3359 if (safi
== SAFI_MPLS_VPN
) {
3360 struct bgp_dest
*pdest
= NULL
;
3361 struct bgp_table
*table
= NULL
;
3363 pdest
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3364 (struct prefix
*)prd
);
3365 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3366 table
= bgp_dest_get_bgp_table_info(pdest
);
3368 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3369 peer
->bgp
, prd
, table
, p
, pi
);
3371 bgp_dest_unlock_node(pdest
);
3373 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3374 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3376 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3377 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3382 /* If this is an EVPN route, process for un-import. */
3383 if (safi
== SAFI_EVPN
)
3384 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3386 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
3389 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3390 struct peer
*peer
, struct attr
*attr
,
3391 struct bgp_dest
*dest
)
3393 struct bgp_path_info
*new;
3395 /* Make new BGP info. */
3396 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3398 new->instance
= instance
;
3399 new->sub_type
= sub_type
;
3402 new->uptime
= bgp_clock();
3407 static void overlay_index_update(struct attr
*attr
,
3408 union gw_addr
*gw_ip
)
3412 if (gw_ip
== NULL
) {
3413 struct bgp_route_evpn eo
;
3415 memset(&eo
, 0, sizeof(eo
));
3416 bgp_attr_set_evpn_overlay(attr
, &eo
);
3418 struct bgp_route_evpn eo
= {.gw_ip
= *gw_ip
};
3420 bgp_attr_set_evpn_overlay(attr
, &eo
);
3424 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3425 union gw_addr
*gw_ip
)
3427 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(path
->attr
);
3428 union gw_addr path_gw_ip
, *path_gw_ip_remote
;
3434 if (afi
!= AFI_L2VPN
)
3437 path_gw_ip
= eo
->gw_ip
;
3439 if (gw_ip
== NULL
) {
3440 memset(&temp
, 0, sizeof(temp
));
3441 path_gw_ip_remote
= &temp
.ip
;
3443 path_gw_ip_remote
= gw_ip
;
3445 return !!memcmp(&path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
));
3448 /* Check if received nexthop is valid or not. */
3449 bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3450 uint8_t type
, uint8_t stype
, struct attr
*attr
,
3451 struct bgp_dest
*dest
)
3454 bool is_bgp_static_route
=
3455 (type
== ZEBRA_ROUTE_BGP
&& stype
== BGP_ROUTE_STATIC
) ? true
3459 * Only validated for unicast and multicast currently.
3460 * Also valid for EVPN where the nexthop is an IP address.
3461 * If we are a bgp static route being checked then there is
3462 * no need to check to see if the nexthop is martian as
3463 * that it should be ok.
3465 if (is_bgp_static_route
||
3466 (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
))
3469 /* If NEXT_HOP is present, validate it. */
3470 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3471 if (attr
->nexthop
.s_addr
== INADDR_ANY
3472 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3473 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, dest
))
3477 /* If MP_NEXTHOP is present, validate it. */
3478 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3479 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3480 * it is not an IPv6 link-local address.
3482 * If we receive an UPDATE with nexthop length set to 32 bytes
3483 * we shouldn't discard an UPDATE if it's set to (::).
3484 * The link-local (2st) is validated along the code path later.
3486 if (attr
->mp_nexthop_len
) {
3487 switch (attr
->mp_nexthop_len
) {
3488 case BGP_ATTR_NHLEN_IPV4
:
3489 case BGP_ATTR_NHLEN_VPNV4
:
3490 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3492 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3493 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3497 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3498 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3499 ret
= (IN6_IS_ADDR_UNSPECIFIED(
3500 &attr
->mp_nexthop_global
)
3501 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3502 || IN6_IS_ADDR_MULTICAST(
3503 &attr
->mp_nexthop_global
)
3504 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3507 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3508 ret
= (IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3509 || IN6_IS_ADDR_MULTICAST(
3510 &attr
->mp_nexthop_global
)
3511 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3524 static void bgp_attr_add_no_export_community(struct attr
*attr
)
3526 struct community
*old
;
3527 struct community
*new;
3528 struct community
*merge
;
3529 struct community
*no_export
;
3531 old
= attr
->community
;
3532 no_export
= community_str2com("no-export");
3537 merge
= community_merge(community_dup(old
), no_export
);
3540 community_free(&old
);
3542 new = community_uniq_sort(merge
);
3543 community_free(&merge
);
3545 new = community_dup(no_export
);
3548 community_free(&no_export
);
3550 attr
->community
= new;
3551 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
3554 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3555 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3556 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3557 uint32_t num_labels
, int soft_reconfig
,
3558 struct bgp_route_evpn
*evpn
)
3561 int aspath_loop_count
= 0;
3562 struct bgp_dest
*dest
;
3564 struct attr new_attr
;
3565 struct attr
*attr_new
;
3566 struct bgp_path_info
*pi
;
3567 struct bgp_path_info
*new;
3568 struct bgp_path_info_extra
*extra
;
3570 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3572 int do_loop_check
= 1;
3573 int has_valid_label
= 0;
3575 uint8_t pi_type
= 0;
3576 uint8_t pi_sub_type
= 0;
3578 if (frrtrace_enabled(frr_bgp
, process_update
)) {
3579 char pfxprint
[PREFIX2STR_BUFFER
];
3581 prefix2str(p
, pfxprint
, sizeof(pfxprint
));
3582 frrtrace(6, frr_bgp
, process_update
, peer
, pfxprint
, addpath_id
,
3586 #ifdef ENABLE_BGP_VNC
3587 int vnc_implicit_withdraw
= 0;
3591 memset(&new_attr
, 0, sizeof(struct attr
));
3592 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3593 new_attr
.label
= MPLS_INVALID_LABEL
;
3596 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3597 /* TODO: Check to see if we can get rid of "is_valid_label" */
3598 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3599 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3601 has_valid_label
= bgp_is_valid_label(label
);
3603 if (has_valid_label
)
3604 assert(label
!= NULL
);
3606 /* When peer's soft reconfiguration enabled. Record input packet in
3609 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3610 && peer
!= bgp
->peer_self
)
3611 bgp_adj_in_set(dest
, peer
, attr
, addpath_id
);
3613 /* Check previously received route. */
3614 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
3615 if (pi
->peer
== peer
&& pi
->type
== type
3616 && pi
->sub_type
== sub_type
3617 && pi
->addpath_rx_id
== addpath_id
)
3620 /* AS path local-as loop check. */
3621 if (peer
->change_local_as
) {
3622 if (peer
->allowas_in
[afi
][safi
])
3623 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3624 else if (!CHECK_FLAG(peer
->flags
,
3625 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3626 aspath_loop_count
= 1;
3628 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3629 > aspath_loop_count
) {
3630 peer
->stat_pfx_aspath_loop
++;
3631 reason
= "as-path contains our own AS A;";
3636 /* If the peer is configured for "allowas-in origin" and the last ASN in
3638 * as-path is our ASN then we do not need to call aspath_loop_check
3640 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3641 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3644 /* AS path loop check. */
3645 if (do_loop_check
) {
3646 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3647 > peer
->allowas_in
[afi
][safi
]
3648 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3649 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3650 > peer
->allowas_in
[afi
][safi
])) {
3651 peer
->stat_pfx_aspath_loop
++;
3652 reason
= "as-path contains our own AS;";
3657 /* Route reflector originator ID check. */
3658 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3659 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3660 peer
->stat_pfx_originator_loop
++;
3661 reason
= "originator is us;";
3665 /* Route reflector cluster ID check. */
3666 if (bgp_cluster_filter(peer
, attr
)) {
3667 peer
->stat_pfx_cluster_loop
++;
3668 reason
= "reflected from the same cluster;";
3672 /* Apply incoming filter. */
3673 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3674 peer
->stat_pfx_filter
++;
3679 /* RFC 8212 to prevent route leaks.
3680 * This specification intends to improve this situation by requiring the
3681 * explicit configuration of both BGP Import and Export Policies for any
3682 * External BGP (EBGP) session such as customers, peers, or
3683 * confederation boundaries for all enabled address families. Through
3684 * codification of the aforementioned requirement, operators will
3685 * benefit from consistent behavior across different BGP
3688 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_EBGP_REQUIRES_POLICY
))
3689 if (!bgp_inbound_policy_exists(peer
,
3690 &peer
->filter
[afi
][safi
])) {
3691 reason
= "inbound policy missing";
3695 /* draft-ietf-idr-deprecate-as-set-confed-set
3696 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3697 * Eventually, This document (if approved) updates RFC 4271
3698 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3699 * and obsoletes RFC 6472.
3701 if (peer
->bgp
->reject_as_sets
)
3702 if (aspath_check_as_sets(attr
->aspath
)) {
3704 "as-path contains AS_SET or AS_CONFED_SET type;";
3710 /* Apply incoming route-map.
3711 * NB: new_attr may now contain newly allocated values from route-map
3713 * commands, so we need bgp_attr_flush in the error paths, until we
3715 * the attr (which takes over the memory references) */
3716 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
, label
,
3719 peer
->stat_pfx_filter
++;
3720 reason
= "route-map;";
3721 bgp_attr_flush(&new_attr
);
3725 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3726 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3727 /* remove from RIB previous entry */
3728 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3731 if (peer
->sort
== BGP_PEER_EBGP
) {
3734 * A BGP speaker receiving an announcement tagged with the
3735 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3736 * NO_EXPORT community as defined in RFC1997, or a
3737 * similar community, to prevent propagation of the
3738 * prefix outside the local AS. The community to prevent
3739 * propagation SHOULD be chosen according to the operator's
3742 if (new_attr
.community
3743 && community_include(new_attr
.community
,
3744 COMMUNITY_BLACKHOLE
))
3745 bgp_attr_add_no_export_community(&new_attr
);
3747 /* If we receive the graceful-shutdown community from an eBGP
3748 * peer we must lower local-preference */
3749 if (new_attr
.community
3750 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3751 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3752 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3754 /* If graceful-shutdown is configured then add the GSHUT
3755 * community to all paths received from eBGP peers */
3756 } else if (bgp_in_graceful_shutdown(peer
->bgp
))
3757 bgp_attr_add_gshut_community(&new_attr
);
3762 pi_sub_type
= pi
->sub_type
;
3765 /* next hop check. */
3766 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3767 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
, pi_sub_type
,
3769 peer
->stat_pfx_nh_invalid
++;
3770 reason
= "martian or self next-hop;";
3771 bgp_attr_flush(&new_attr
);
3775 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3776 peer
->stat_pfx_nh_invalid
++;
3777 reason
= "self mac;";
3781 /* Update Overlay Index */
3782 if (afi
== AFI_L2VPN
) {
3783 overlay_index_update(&new_attr
,
3784 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3787 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3789 * Suppress fib is enabled
3790 * BGP_OPT_NO_FIB is not enabled
3791 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3792 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3794 if (bgp_fibupd_safi(safi
) && BGP_SUPPRESS_FIB_ENABLED(bgp
)
3795 && (sub_type
== BGP_ROUTE_NORMAL
)
3796 && (!bgp_option_check(BGP_OPT_NO_FIB
))
3797 && (!CHECK_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALLED
)))
3798 SET_FLAG(dest
->flags
, BGP_NODE_FIB_INSTALL_PENDING
);
3800 attr_new
= bgp_attr_intern(&new_attr
);
3802 /* If maximum prefix count is configured and current prefix
3805 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3808 /* If the update is implicit withdraw. */
3810 pi
->uptime
= bgp_clock();
3811 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3813 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
3815 /* Same attribute comes in. */
3816 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3818 && (!has_valid_label
3819 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3820 num_labels
* sizeof(mpls_label_t
))
3822 && (overlay_index_equal(
3824 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3825 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3826 && peer
->sort
== BGP_PEER_EBGP
3827 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3828 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3829 bgp_debug_rdpfxpath2str(
3830 afi
, safi
, prd
, p
, label
,
3831 num_labels
, addpath_id
? 1 : 0,
3832 addpath_id
, pfx_buf
,
3834 zlog_debug("%s rcvd %s", peer
->host
,
3838 if (bgp_damp_update(pi
, dest
, afi
, safi
)
3839 != BGP_DAMP_SUPPRESSED
) {
3840 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3842 bgp_process(bgp
, dest
, afi
, safi
);
3844 } else /* Duplicate - odd */
3846 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3847 if (!peer
->rcvd_attr_printed
) {
3849 "%s rcvd UPDATE w/ attr: %s",
3851 peer
->rcvd_attr_str
);
3852 peer
->rcvd_attr_printed
= 1;
3855 bgp_debug_rdpfxpath2str(
3856 afi
, safi
, prd
, p
, label
,
3857 num_labels
, addpath_id
? 1 : 0,
3858 addpath_id
, pfx_buf
,
3861 "%s rcvd %s...duplicate ignored",
3862 peer
->host
, pfx_buf
);
3865 /* graceful restart STALE flag unset. */
3866 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3867 bgp_path_info_unset_flag(
3868 dest
, pi
, BGP_PATH_STALE
);
3869 bgp_dest_set_defer_flag(dest
, false);
3870 bgp_process(bgp
, dest
, afi
, safi
);
3874 bgp_dest_unlock_node(dest
);
3875 bgp_attr_unintern(&attr_new
);
3880 /* Withdraw/Announce before we fully processed the withdraw */
3881 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3882 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3883 bgp_debug_rdpfxpath2str(
3884 afi
, safi
, prd
, p
, label
, num_labels
,
3885 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3888 "%s rcvd %s, flapped quicker than processing",
3889 peer
->host
, pfx_buf
);
3892 bgp_path_info_restore(dest
, pi
);
3895 /* Received Logging. */
3896 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3897 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3898 num_labels
, addpath_id
? 1 : 0,
3899 addpath_id
, pfx_buf
,
3901 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3904 /* graceful restart STALE flag unset. */
3905 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3906 bgp_path_info_unset_flag(dest
, pi
, BGP_PATH_STALE
);
3907 bgp_dest_set_defer_flag(dest
, false);
3910 /* The attribute is changed. */
3911 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
3913 /* implicit withdraw, decrement aggregate and pcount here.
3914 * only if update is accepted, they'll increment below.
3916 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3918 /* Update bgp route dampening information. */
3919 if (get_active_bdc_from_pi(pi
, afi
, safi
)
3920 && peer
->sort
== BGP_PEER_EBGP
) {
3921 /* This is implicit withdraw so we should update
3922 * dampening information.
3924 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3925 bgp_damp_withdraw(pi
, dest
, afi
, safi
, 1);
3927 #ifdef ENABLE_BGP_VNC
3928 if (safi
== SAFI_MPLS_VPN
) {
3929 struct bgp_dest
*pdest
= NULL
;
3930 struct bgp_table
*table
= NULL
;
3932 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
3933 (struct prefix
*)prd
);
3934 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
3935 table
= bgp_dest_get_bgp_table_info(pdest
);
3937 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3938 bgp
, prd
, table
, p
, pi
);
3940 bgp_dest_unlock_node(pdest
);
3942 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3943 && (safi
== SAFI_UNICAST
)) {
3944 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3946 * Implicit withdraw case.
3948 ++vnc_implicit_withdraw
;
3949 vnc_import_bgp_del_route(bgp
, p
, pi
);
3950 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3955 /* Special handling for EVPN update of an existing route. If the
3956 * extended community attribute has changed, we need to
3958 * the route using its existing extended community. It will be
3959 * subsequently processed for import with the new extended
3962 if (((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
))
3965 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3967 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3970 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3971 attr_new
->ecommunity
);
3973 if (bgp_debug_update(peer
, p
, NULL
, 1))
3975 "Change in EXT-COMM, existing %s new %s",
3977 pi
->attr
->ecommunity
),
3979 attr_new
->ecommunity
));
3980 if (safi
== SAFI_EVPN
)
3981 bgp_evpn_unimport_route(
3982 bgp
, afi
, safi
, p
, pi
);
3983 else /* SAFI_MPLS_VPN */
3984 vpn_leak_to_vrf_withdraw(bgp
,
3990 /* Update to new attribute. */
3991 bgp_attr_unintern(&pi
->attr
);
3992 pi
->attr
= attr_new
;
3994 /* Update MPLS label */
3995 if (has_valid_label
) {
3996 extra
= bgp_path_info_extra_get(pi
);
3997 if (extra
->label
!= label
) {
3998 memcpy(&extra
->label
, label
,
3999 num_labels
* sizeof(mpls_label_t
));
4000 extra
->num_labels
= num_labels
;
4002 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4003 bgp_set_valid_label(&extra
->label
[0]);
4006 /* Update SRv6 SID */
4007 if (attr
->srv6_l3vpn
) {
4008 extra
= bgp_path_info_extra_get(pi
);
4009 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
4010 sid_copy(&extra
->sid
[0],
4011 &attr
->srv6_l3vpn
->sid
);
4012 extra
->num_sids
= 1;
4014 } else if (attr
->srv6_vpn
) {
4015 extra
= bgp_path_info_extra_get(pi
);
4016 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
4017 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4018 extra
->num_sids
= 1;
4022 #ifdef ENABLE_BGP_VNC
4023 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4024 && (safi
== SAFI_UNICAST
)) {
4025 if (vnc_implicit_withdraw
) {
4027 * Add back the route with its new attributes
4029 * The route is still selected, until the route
4031 * queued by bgp_process actually runs. We have
4033 * update to the VNC side immediately to avoid
4035 * configuration changes (e.g., route-map
4037 * trigger re-importation of the entire RIB.
4039 vnc_import_bgp_add_route(bgp
, p
, pi
);
4040 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
4045 /* Update bgp route dampening information. */
4046 if (get_active_bdc_from_pi(pi
, afi
, safi
)
4047 && peer
->sort
== BGP_PEER_EBGP
) {
4048 /* Now we do normal update dampening. */
4049 ret
= bgp_damp_update(pi
, dest
, afi
, safi
);
4050 if (ret
== BGP_DAMP_SUPPRESSED
) {
4051 bgp_dest_unlock_node(dest
);
4056 /* Nexthop reachability check - for unicast and
4057 * labeled-unicast.. */
4058 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4059 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4060 || (safi
== SAFI_EVPN
&&
4061 bgp_evpn_is_prefix_nht_supported(p
))) {
4062 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4063 && peer
->ttl
== BGP_DEFAULT_TTL
4064 && !CHECK_FLAG(peer
->flags
,
4065 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4066 && !CHECK_FLAG(bgp
->flags
,
4067 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4072 struct bgp
*bgp_nexthop
= bgp
;
4074 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4075 bgp_nexthop
= pi
->extra
->bgp_orig
;
4077 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
4079 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
4080 safi
, pi
, NULL
, connected
)
4081 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4082 bgp_path_info_set_flag(dest
, pi
,
4085 if (BGP_DEBUG(nht
, NHT
)) {
4086 zlog_debug("%s(%pI4): NH unresolved",
4088 (in_addr_t
*)&attr_new
->nexthop
);
4090 bgp_path_info_unset_flag(dest
, pi
,
4094 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_VALID
);
4096 #ifdef ENABLE_BGP_VNC
4097 if (safi
== SAFI_MPLS_VPN
) {
4098 struct bgp_dest
*pdest
= NULL
;
4099 struct bgp_table
*table
= NULL
;
4101 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
],
4102 (struct prefix
*)prd
);
4103 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4104 table
= bgp_dest_get_bgp_table_info(pdest
);
4106 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4107 bgp
, prd
, table
, p
, pi
);
4109 bgp_dest_unlock_node(pdest
);
4113 /* If this is an EVPN route and some attribute has changed,
4115 * route for import. If the extended community has changed, we
4117 * have done the un-import earlier and the import would result
4119 * route getting injected into appropriate L2 VNIs. If it is
4121 * some other attribute change, the import will result in
4123 * the attributes for the route in the VNI(s).
4125 if (safi
== SAFI_EVPN
&& !same_attr
&&
4126 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
4127 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
4129 /* Process change. */
4130 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4132 bgp_process(bgp
, dest
, afi
, safi
);
4133 bgp_dest_unlock_node(dest
);
4135 if (SAFI_UNICAST
== safi
4136 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4137 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4139 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
4141 if ((SAFI_MPLS_VPN
== safi
)
4142 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4144 vpn_leak_to_vrf_update(bgp
, pi
);
4147 #ifdef ENABLE_BGP_VNC
4148 if (SAFI_MPLS_VPN
== safi
) {
4149 mpls_label_t label_decoded
= decode_label(label
);
4151 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4152 type
, sub_type
, &label_decoded
);
4154 if (SAFI_ENCAP
== safi
) {
4155 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
4156 type
, sub_type
, NULL
);
4161 } // End of implicit withdraw
4163 /* Received Logging. */
4164 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4165 if (!peer
->rcvd_attr_printed
) {
4166 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4167 peer
->rcvd_attr_str
);
4168 peer
->rcvd_attr_printed
= 1;
4171 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4172 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4174 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
4177 /* Make new BGP info. */
4178 new = info_make(type
, sub_type
, 0, peer
, attr_new
, dest
);
4180 /* Update MPLS label */
4181 if (has_valid_label
) {
4182 extra
= bgp_path_info_extra_get(new);
4183 if (extra
->label
!= label
) {
4184 memcpy(&extra
->label
, label
,
4185 num_labels
* sizeof(mpls_label_t
));
4186 extra
->num_labels
= num_labels
;
4188 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
4189 bgp_set_valid_label(&extra
->label
[0]);
4192 /* Update SRv6 SID */
4193 if (safi
== SAFI_MPLS_VPN
) {
4194 extra
= bgp_path_info_extra_get(new);
4195 if (attr
->srv6_l3vpn
) {
4196 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
4197 extra
->num_sids
= 1;
4198 } else if (attr
->srv6_vpn
) {
4199 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
4200 extra
->num_sids
= 1;
4204 /* Update Overlay Index */
4205 if (afi
== AFI_L2VPN
) {
4206 overlay_index_update(new->attr
,
4207 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
4209 /* Nexthop reachability check. */
4210 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
4211 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
4212 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
4213 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
4214 && peer
->ttl
== BGP_DEFAULT_TTL
4215 && !CHECK_FLAG(peer
->flags
,
4216 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
4217 && !CHECK_FLAG(bgp
->flags
,
4218 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
4223 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
4225 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, safi
, new, NULL
,
4227 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
4228 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4230 if (BGP_DEBUG(nht
, NHT
)) {
4231 char buf1
[INET6_ADDRSTRLEN
];
4233 (const void *)&attr_new
->nexthop
,
4234 buf1
, INET6_ADDRSTRLEN
);
4235 zlog_debug("%s(%s): NH unresolved", __func__
,
4238 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
4241 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
4244 new->addpath_rx_id
= addpath_id
;
4246 /* Increment prefix */
4247 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4249 /* Register new BGP information. */
4250 bgp_path_info_add(dest
, new);
4252 /* route_node_get lock */
4253 bgp_dest_unlock_node(dest
);
4255 #ifdef ENABLE_BGP_VNC
4256 if (safi
== SAFI_MPLS_VPN
) {
4257 struct bgp_dest
*pdest
= NULL
;
4258 struct bgp_table
*table
= NULL
;
4260 pdest
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
4261 if (bgp_dest_has_bgp_path_info_data(pdest
)) {
4262 table
= bgp_dest_get_bgp_table_info(pdest
);
4264 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4265 bgp
, prd
, table
, p
, new);
4267 bgp_dest_unlock_node(pdest
);
4271 /* If this is an EVPN route, process for import. */
4272 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
4273 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
4275 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, false);
4277 /* Process change. */
4278 bgp_process(bgp
, dest
, afi
, safi
);
4280 if (SAFI_UNICAST
== safi
4281 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4282 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4283 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4285 if ((SAFI_MPLS_VPN
== safi
)
4286 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4288 vpn_leak_to_vrf_update(bgp
, new);
4290 #ifdef ENABLE_BGP_VNC
4291 if (SAFI_MPLS_VPN
== safi
) {
4292 mpls_label_t label_decoded
= decode_label(label
);
4294 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4295 sub_type
, &label_decoded
);
4297 if (SAFI_ENCAP
== safi
) {
4298 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
4305 /* This BGP update is filtered. Log the reason then update BGP
4308 hook_call(bgp_process
, bgp
, afi
, safi
, dest
, peer
, true);
4310 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4311 if (!peer
->rcvd_attr_printed
) {
4312 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
4313 peer
->rcvd_attr_str
);
4314 peer
->rcvd_attr_printed
= 1;
4317 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4318 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4320 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4321 peer
->host
, pfx_buf
, reason
);
4325 /* If this is an EVPN route, un-import it as it is now filtered.
4327 if (safi
== SAFI_EVPN
)
4328 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
4330 if (SAFI_UNICAST
== safi
4331 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4332 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4334 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4336 if ((SAFI_MPLS_VPN
== safi
)
4337 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4339 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4342 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4345 bgp_dest_unlock_node(dest
);
4347 #ifdef ENABLE_BGP_VNC
4349 * Filtered update is treated as an implicit withdrawal (see
4351 * a few lines above)
4353 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4354 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4362 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4363 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4364 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4365 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4368 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4369 struct bgp_dest
*dest
;
4370 struct bgp_path_info
*pi
;
4372 #ifdef ENABLE_BGP_VNC
4373 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4374 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4382 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4384 /* If peer is soft reconfiguration enabled. Record input packet for
4385 * further calculation.
4387 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4388 * routes that are filtered. This tanks out Quagga RS pretty badly due
4390 * the iteration over all RS clients.
4391 * Since we need to remove the entry from adj_in anyway, do that first
4393 * if there was no entry, we don't need to do anything more.
4395 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4396 && peer
!= bgp
->peer_self
)
4397 if (!bgp_adj_in_unset(dest
, peer
, addpath_id
)) {
4398 peer
->stat_pfx_dup_withdraw
++;
4400 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4401 bgp_debug_rdpfxpath2str(
4402 afi
, safi
, prd
, p
, label
, num_labels
,
4403 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4406 "%s withdrawing route %s not in adj-in",
4407 peer
->host
, pfx_buf
);
4409 bgp_dest_unlock_node(dest
);
4413 /* Lookup withdrawn route. */
4414 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
4415 if (pi
->peer
== peer
&& pi
->type
== type
4416 && pi
->sub_type
== sub_type
4417 && pi
->addpath_rx_id
== addpath_id
)
4421 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4422 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4423 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4425 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4429 /* Withdraw specified route from routing table. */
4430 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4431 bgp_rib_withdraw(dest
, pi
, peer
, afi
, safi
, prd
);
4432 if (SAFI_UNICAST
== safi
4433 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4434 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4435 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4437 if ((SAFI_MPLS_VPN
== safi
)
4438 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4440 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4442 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4443 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4444 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4446 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4449 /* Unlock bgp_node_get() lock. */
4450 bgp_dest_unlock_node(dest
);
4455 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4458 struct update_subgroup
*subgrp
;
4459 subgrp
= peer_subgroup(peer
, afi
, safi
);
4460 subgroup_default_originate(subgrp
, withdraw
);
4465 * bgp_stop_announce_route_timer
4467 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4469 if (!paf
->t_announce_route
)
4472 thread_cancel(&paf
->t_announce_route
);
4476 * bgp_announce_route_timer_expired
4478 * Callback that is invoked when the route announcement timer for a
4481 static int bgp_announce_route_timer_expired(struct thread
*t
)
4483 struct peer_af
*paf
;
4486 paf
= THREAD_ARG(t
);
4489 if (peer
->status
!= Established
)
4492 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4495 peer_af_announce_route(paf
, 1);
4497 /* Notify BGP conditional advertisement scanner percess */
4498 peer
->advmap_config_change
[paf
->afi
][paf
->safi
] = true;
4504 * bgp_announce_route
4506 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4508 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4510 struct peer_af
*paf
;
4511 struct update_subgroup
*subgrp
;
4513 paf
= peer_af_find(peer
, afi
, safi
);
4516 subgrp
= PAF_SUBGRP(paf
);
4519 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4520 * or a refresh has already been triggered.
4522 if (!subgrp
|| paf
->t_announce_route
)
4526 * Start a timer to stagger/delay the announce. This serves
4527 * two purposes - announcement can potentially be combined for
4528 * multiple peers and the announcement doesn't happen in the
4531 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4532 (subgrp
->peer_count
== 1)
4533 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4534 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4535 &paf
->t_announce_route
);
4539 * Announce routes from all AF tables to a peer.
4541 * This should ONLY be called when there is a need to refresh the
4542 * routes to the peer based on a policy change for this peer alone
4543 * or a route refresh request received from the peer.
4544 * The operation will result in splitting the peer from its existing
4545 * subgroups and putting it in new subgroups.
4547 void bgp_announce_route_all(struct peer
*peer
)
4552 FOREACH_AFI_SAFI (afi
, safi
)
4553 bgp_announce_route(peer
, afi
, safi
);
4556 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4557 struct bgp_table
*table
,
4558 struct prefix_rd
*prd
)
4561 struct bgp_dest
*dest
;
4562 struct bgp_adj_in
*ain
;
4565 table
= peer
->bgp
->rib
[afi
][safi
];
4567 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
4568 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
4569 if (ain
->peer
!= peer
)
4572 struct bgp_path_info
*pi
;
4573 uint32_t num_labels
= 0;
4574 mpls_label_t
*label_pnt
= NULL
;
4575 struct bgp_route_evpn evpn
;
4577 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4579 if (pi
->peer
== peer
)
4582 if (pi
&& pi
->extra
)
4583 num_labels
= pi
->extra
->num_labels
;
4585 label_pnt
= &pi
->extra
->label
[0];
4588 bgp_attr_get_evpn_overlay(pi
->attr
),
4591 memset(&evpn
, 0, sizeof(evpn
));
4593 ret
= bgp_update(peer
, bgp_dest_get_prefix(dest
),
4594 ain
->addpath_rx_id
, ain
->attr
, afi
,
4595 safi
, ZEBRA_ROUTE_BGP
,
4596 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4597 num_labels
, 1, &evpn
);
4600 bgp_dest_unlock_node(dest
);
4606 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4608 struct bgp_dest
*dest
;
4609 struct bgp_table
*table
;
4611 if (peer
->status
!= Established
)
4614 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4615 && (safi
!= SAFI_EVPN
))
4616 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4618 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4619 dest
= bgp_route_next(dest
)) {
4620 table
= bgp_dest_get_bgp_table_info(dest
);
4625 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
4626 struct prefix_rd prd
;
4628 prd
.family
= AF_UNSPEC
;
4630 memcpy(&prd
.val
, p
->u
.val
, 8);
4632 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4637 struct bgp_clear_node_queue
{
4638 struct bgp_dest
*dest
;
4641 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4643 struct bgp_clear_node_queue
*cnq
= data
;
4644 struct bgp_dest
*dest
= cnq
->dest
;
4645 struct peer
*peer
= wq
->spec
.data
;
4646 struct bgp_path_info
*pi
;
4648 afi_t afi
= bgp_dest_table(dest
)->afi
;
4649 safi_t safi
= bgp_dest_table(dest
)->safi
;
4651 assert(dest
&& peer
);
4654 /* It is possible that we have multiple paths for a prefix from a peer
4655 * if that peer is using AddPath.
4657 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
4658 if (pi
->peer
!= peer
)
4661 /* graceful restart STALE flag set. */
4662 if (((CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4663 && peer
->nsf
[afi
][safi
])
4664 || CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
4665 PEER_STATUS_ENHANCED_REFRESH
))
4666 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4667 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4668 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_STALE
);
4670 /* If this is an EVPN route, process for
4672 if (safi
== SAFI_EVPN
)
4673 bgp_evpn_unimport_route(
4675 bgp_dest_get_prefix(dest
), pi
);
4676 /* Handle withdraw for VRF route-leaking and L3VPN */
4677 if (SAFI_UNICAST
== safi
4678 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4679 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4680 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4683 if (SAFI_MPLS_VPN
== safi
&&
4684 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4685 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4688 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4694 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4696 struct bgp_clear_node_queue
*cnq
= data
;
4697 struct bgp_dest
*dest
= cnq
->dest
;
4698 struct bgp_table
*table
= bgp_dest_table(dest
);
4700 bgp_dest_unlock_node(dest
);
4701 bgp_table_unlock(table
);
4702 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4705 static void bgp_clear_node_complete(struct work_queue
*wq
)
4707 struct peer
*peer
= wq
->spec
.data
;
4709 /* Tickle FSM to start moving again */
4710 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4712 peer_unlock(peer
); /* bgp_clear_route */
4715 static void bgp_clear_node_queue_init(struct peer
*peer
)
4717 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4719 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4720 #undef CLEAR_QUEUE_NAME_LEN
4722 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4723 peer
->clear_node_queue
->spec
.hold
= 10;
4724 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4725 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4726 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4727 peer
->clear_node_queue
->spec
.max_retries
= 0;
4729 /* we only 'lock' this peer reference when the queue is actually active
4731 peer
->clear_node_queue
->spec
.data
= peer
;
4734 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4735 struct bgp_table
*table
)
4737 struct bgp_dest
*dest
;
4738 int force
= peer
->bgp
->process_queue
? 0 : 1;
4741 table
= peer
->bgp
->rib
[afi
][safi
];
4743 /* If still no table => afi/safi isn't configured at all or smth. */
4747 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4748 struct bgp_path_info
*pi
, *next
;
4749 struct bgp_adj_in
*ain
;
4750 struct bgp_adj_in
*ain_next
;
4752 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4753 * queued for every clearing peer, regardless of whether it is
4754 * relevant to the peer at hand.
4756 * Overview: There are 3 different indices which need to be
4757 * scrubbed, potentially, when a peer is removed:
4759 * 1 peer's routes visible via the RIB (ie accepted routes)
4760 * 2 peer's routes visible by the (optional) peer's adj-in index
4761 * 3 other routes visible by the peer's adj-out index
4763 * 3 there is no hurry in scrubbing, once the struct peer is
4764 * removed from bgp->peer, we could just GC such deleted peer's
4765 * adj-outs at our leisure.
4767 * 1 and 2 must be 'scrubbed' in some way, at least made
4768 * invisible via RIB index before peer session is allowed to be
4769 * brought back up. So one needs to know when such a 'search' is
4774 * - there'd be a single global queue or a single RIB walker
4775 * - rather than tracking which route_nodes still need to be
4776 * examined on a peer basis, we'd track which peers still
4779 * Given that our per-peer prefix-counts now should be reliable,
4780 * this may actually be achievable. It doesn't seem to be a huge
4781 * problem at this time,
4783 * It is possible that we have multiple paths for a prefix from
4785 * if that peer is using AddPath.
4789 ain_next
= ain
->next
;
4791 if (ain
->peer
== peer
) {
4792 bgp_adj_in_remove(dest
, ain
);
4793 bgp_dest_unlock_node(dest
);
4799 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
4801 if (pi
->peer
!= peer
)
4805 bgp_path_info_reap(dest
, pi
);
4807 struct bgp_clear_node_queue
*cnq
;
4809 /* both unlocked in bgp_clear_node_queue_del */
4810 bgp_table_lock(bgp_dest_table(dest
));
4811 bgp_dest_lock_node(dest
);
4813 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4814 sizeof(struct bgp_clear_node_queue
));
4816 work_queue_add(peer
->clear_node_queue
, cnq
);
4824 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4826 struct bgp_dest
*dest
;
4827 struct bgp_table
*table
;
4829 if (peer
->clear_node_queue
== NULL
)
4830 bgp_clear_node_queue_init(peer
);
4832 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4833 * Idle until it receives a Clearing_Completed event. This protects
4834 * against peers which flap faster than we can we clear, which could
4837 * a) race with routes from the new session being installed before
4838 * clear_route_node visits the node (to delete the route of that
4840 * b) resource exhaustion, clear_route_node likely leads to an entry
4841 * on the process_main queue. Fast-flapping could cause that queue
4845 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4846 * the unlock will happen upon work-queue completion; other wise, the
4847 * unlock happens at the end of this function.
4849 if (!peer
->clear_node_queue
->thread
)
4852 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4853 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4855 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4856 dest
= bgp_route_next(dest
)) {
4857 table
= bgp_dest_get_bgp_table_info(dest
);
4861 bgp_clear_route_table(peer
, afi
, safi
, table
);
4864 /* unlock if no nodes got added to the clear-node-queue. */
4865 if (!peer
->clear_node_queue
->thread
)
4869 void bgp_clear_route_all(struct peer
*peer
)
4874 FOREACH_AFI_SAFI (afi
, safi
)
4875 bgp_clear_route(peer
, afi
, safi
);
4877 #ifdef ENABLE_BGP_VNC
4878 rfapiProcessPeerDown(peer
);
4882 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4884 struct bgp_table
*table
;
4885 struct bgp_dest
*dest
;
4886 struct bgp_adj_in
*ain
;
4887 struct bgp_adj_in
*ain_next
;
4889 table
= peer
->bgp
->rib
[afi
][safi
];
4891 /* It is possible that we have multiple paths for a prefix from a peer
4892 * if that peer is using AddPath.
4894 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
4898 ain_next
= ain
->next
;
4900 if (ain
->peer
== peer
) {
4901 bgp_adj_in_remove(dest
, ain
);
4902 bgp_dest_unlock_node(dest
);
4910 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4912 struct bgp_dest
*dest
;
4913 struct bgp_path_info
*pi
;
4914 struct bgp_table
*table
;
4916 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4917 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4918 dest
= bgp_route_next(dest
)) {
4919 struct bgp_dest
*rm
;
4921 /* look for neighbor in tables */
4922 table
= bgp_dest_get_bgp_table_info(dest
);
4926 for (rm
= bgp_table_top(table
); rm
;
4927 rm
= bgp_route_next(rm
))
4928 for (pi
= bgp_dest_get_bgp_path_info(rm
); pi
;
4930 if (pi
->peer
!= peer
)
4932 if (!CHECK_FLAG(pi
->flags
,
4936 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4941 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4942 dest
= bgp_route_next(dest
))
4943 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
4945 if (pi
->peer
!= peer
)
4947 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4949 bgp_rib_remove(dest
, pi
, peer
, afi
, safi
);
4955 void bgp_set_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4957 struct bgp_dest
*dest
, *ndest
;
4958 struct bgp_path_info
*pi
;
4959 struct bgp_table
*table
;
4961 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
4962 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
4963 dest
= bgp_route_next(dest
)) {
4964 table
= bgp_dest_get_bgp_table_info(dest
);
4968 for (ndest
= bgp_table_top(table
); ndest
;
4969 ndest
= bgp_route_next(ndest
)) {
4970 for (pi
= bgp_dest_get_bgp_path_info(ndest
); pi
;
4972 if (pi
->peer
!= peer
)
4976 peer
->af_sflags
[afi
][safi
],
4977 PEER_STATUS_ENHANCED_REFRESH
))
4978 && !CHECK_FLAG(pi
->flags
,
4982 BGP_PATH_UNUSEABLE
)) {
4983 if (bgp_debug_neighbor_events(
4986 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4990 bgp_dest_get_prefix(
4993 bgp_path_info_set_flag(
5001 for (dest
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); dest
;
5002 dest
= bgp_route_next(dest
)) {
5003 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
5005 if (pi
->peer
!= peer
)
5008 if ((CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
5009 PEER_STATUS_ENHANCED_REFRESH
))
5010 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
5011 && !CHECK_FLAG(pi
->flags
,
5012 BGP_PATH_UNUSEABLE
)) {
5013 if (bgp_debug_neighbor_events(peer
))
5015 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5019 bgp_dest_get_prefix(
5022 bgp_path_info_set_flag(dest
, pi
,
5030 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5032 if (peer
->sort
== BGP_PEER_IBGP
)
5035 if (peer
->sort
== BGP_PEER_EBGP
5036 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
5037 || FILTER_LIST_OUT_NAME(filter
)
5038 || DISTRIBUTE_OUT_NAME(filter
)))
5043 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
5045 if (peer
->sort
== BGP_PEER_IBGP
)
5048 if (peer
->sort
== BGP_PEER_EBGP
5049 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
5050 || FILTER_LIST_IN_NAME(filter
)
5051 || DISTRIBUTE_IN_NAME(filter
)))
5056 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
5059 struct bgp_dest
*dest
;
5060 struct bgp_path_info
*pi
;
5061 struct bgp_path_info
*next
;
5063 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
))
5064 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= next
) {
5065 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
5069 /* Unimport EVPN routes from VRFs */
5070 if (safi
== SAFI_EVPN
)
5071 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
5074 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
5075 && pi
->type
== ZEBRA_ROUTE_BGP
5076 && (pi
->sub_type
== BGP_ROUTE_NORMAL
5077 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
5078 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
5080 if (bgp_fibupd_safi(safi
))
5081 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
5084 bgp_path_info_reap(dest
, pi
);
5088 /* Delete all kernel routes. */
5089 void bgp_cleanup_routes(struct bgp
*bgp
)
5092 struct bgp_dest
*dest
;
5093 struct bgp_table
*table
;
5095 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
5096 if (afi
== AFI_L2VPN
)
5098 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
5101 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5103 if (afi
!= AFI_L2VPN
) {
5105 safi
= SAFI_MPLS_VPN
;
5106 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5107 dest
= bgp_route_next(dest
)) {
5108 table
= bgp_dest_get_bgp_table_info(dest
);
5109 if (table
!= NULL
) {
5110 bgp_cleanup_table(bgp
, table
, safi
);
5111 bgp_table_finish(&table
);
5112 bgp_dest_set_bgp_table_info(dest
, NULL
);
5113 bgp_dest_unlock_node(dest
);
5117 for (dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); dest
;
5118 dest
= bgp_route_next(dest
)) {
5119 table
= bgp_dest_get_bgp_table_info(dest
);
5120 if (table
!= NULL
) {
5121 bgp_cleanup_table(bgp
, table
, safi
);
5122 bgp_table_finish(&table
);
5123 bgp_dest_set_bgp_table_info(dest
, NULL
);
5124 bgp_dest_unlock_node(dest
);
5129 for (dest
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); dest
;
5130 dest
= bgp_route_next(dest
)) {
5131 table
= bgp_dest_get_bgp_table_info(dest
);
5132 if (table
!= NULL
) {
5133 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
5134 bgp_table_finish(&table
);
5135 bgp_dest_set_bgp_table_info(dest
, NULL
);
5136 bgp_dest_unlock_node(dest
);
5141 void bgp_reset(void)
5144 bgp_zclient_reset();
5145 access_list_reset();
5146 prefix_list_reset();
5149 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
5151 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
5152 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
5153 PEER_CAP_ADDPATH_AF_TX_RCV
));
5156 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5158 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
5159 struct bgp_nlri
*packet
)
5168 int addpath_encoded
;
5169 uint32_t addpath_id
;
5172 lim
= pnt
+ packet
->length
;
5174 safi
= packet
->safi
;
5176 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
5178 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5179 syntactic validity. If the field is syntactically incorrect,
5180 then the Error Subcode is set to Invalid Network Field. */
5181 for (; pnt
< lim
; pnt
+= psize
) {
5182 /* Clear prefix structure. */
5183 memset(&p
, 0, sizeof(struct prefix
));
5185 if (addpath_encoded
) {
5187 /* When packet overflow occurs return immediately. */
5188 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
5189 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5191 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
5192 addpath_id
= ntohl(addpath_id
);
5193 pnt
+= BGP_ADDPATH_ID_LEN
;
5196 /* Fetch prefix length. */
5197 p
.prefixlen
= *pnt
++;
5198 /* afi/safi validity already verified by caller,
5199 * bgp_update_receive */
5200 p
.family
= afi2family(afi
);
5202 /* Prefix length check. */
5203 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
5206 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
5207 peer
->host
, p
.prefixlen
, packet
->afi
);
5208 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
5211 /* Packet size overflow check. */
5212 psize
= PSIZE(p
.prefixlen
);
5214 /* When packet overflow occur return immediately. */
5215 if (pnt
+ psize
> lim
) {
5218 "%s [Error] Update packet error (prefix length %d overflows packet)",
5219 peer
->host
, p
.prefixlen
);
5220 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
5223 /* Defensive coding, double-check the psize fits in a struct
5225 if (psize
> (ssize_t
)sizeof(p
.u
)) {
5228 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5229 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
5230 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5233 /* Fetch prefix from NLRI packet. */
5234 memcpy(p
.u
.val
, pnt
, psize
);
5236 /* Check address. */
5237 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
5238 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
5239 /* From RFC4271 Section 6.3:
5241 * If a prefix in the NLRI field is semantically
5243 * (e.g., an unexpected multicast IP address),
5245 * be logged locally, and the prefix SHOULD be
5250 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5251 peer
->host
, &p
.u
.prefix4
);
5256 /* Check address. */
5257 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
5258 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5261 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5262 peer
->host
, &p
.u
.prefix6
);
5266 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
5269 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5270 peer
->host
, &p
.u
.prefix6
);
5276 /* Normal process. */
5278 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
5279 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
5280 NULL
, NULL
, 0, 0, NULL
);
5282 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
5283 safi
, ZEBRA_ROUTE_BGP
,
5284 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
5287 /* Do not send BGP notification twice when maximum-prefix count
5289 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
5290 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
5292 /* Address family configuration mismatch. */
5294 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
5297 /* Packet length consistency check. */
5301 "%s [Error] Update packet error (prefix length mismatch with total length)",
5303 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
5306 return BGP_NLRI_PARSE_OK
;
5309 static struct bgp_static
*bgp_static_new(void)
5311 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
5314 static void bgp_static_free(struct bgp_static
*bgp_static
)
5316 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5317 route_map_counter_decrement(bgp_static
->rmap
.map
);
5319 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
5320 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
5323 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
5324 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
5326 struct bgp_dest
*dest
;
5327 struct bgp_path_info
*pi
;
5328 struct bgp_path_info
*new;
5329 struct bgp_path_info rmap_path
;
5331 struct attr
*attr_new
;
5332 route_map_result_t ret
;
5333 #ifdef ENABLE_BGP_VNC
5334 int vnc_implicit_withdraw
= 0;
5339 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5341 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5343 attr
.nexthop
= bgp_static
->igpnexthop
;
5344 attr
.med
= bgp_static
->igpmetric
;
5345 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5347 if (bgp_static
->atomic
)
5348 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
5350 /* Store label index, if required. */
5351 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
5352 attr
.label_index
= bgp_static
->label_index
;
5353 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
5356 /* Apply route-map. */
5357 if (bgp_static
->rmap
.name
) {
5358 struct attr attr_tmp
= attr
;
5360 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
5361 rmap_path
.peer
= bgp
->peer_self
;
5362 rmap_path
.attr
= &attr_tmp
;
5364 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5366 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5368 bgp
->peer_self
->rmap_type
= 0;
5370 if (ret
== RMAP_DENYMATCH
) {
5371 /* Free uninterned attribute. */
5372 bgp_attr_flush(&attr_tmp
);
5374 /* Unintern original. */
5375 aspath_unintern(&attr
.aspath
);
5376 bgp_static_withdraw(bgp
, p
, afi
, safi
);
5380 if (bgp_in_graceful_shutdown(bgp
))
5381 bgp_attr_add_gshut_community(&attr_tmp
);
5383 attr_new
= bgp_attr_intern(&attr_tmp
);
5386 if (bgp_in_graceful_shutdown(bgp
))
5387 bgp_attr_add_gshut_community(&attr
);
5389 attr_new
= bgp_attr_intern(&attr
);
5392 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5393 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5394 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5398 if (attrhash_cmp(pi
->attr
, attr_new
)
5399 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
5400 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
5401 bgp_dest_unlock_node(dest
);
5402 bgp_attr_unintern(&attr_new
);
5403 aspath_unintern(&attr
.aspath
);
5406 /* The attribute is changed. */
5407 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5409 /* Rewrite BGP route information. */
5410 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5411 bgp_path_info_restore(dest
, pi
);
5413 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5414 #ifdef ENABLE_BGP_VNC
5415 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5416 && (safi
== SAFI_UNICAST
)) {
5417 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5419 * Implicit withdraw case.
5420 * We have to do this before pi is
5423 ++vnc_implicit_withdraw
;
5424 vnc_import_bgp_del_route(bgp
, p
, pi
);
5425 vnc_import_bgp_exterior_del_route(
5430 bgp_attr_unintern(&pi
->attr
);
5431 pi
->attr
= attr_new
;
5432 pi
->uptime
= bgp_clock();
5433 #ifdef ENABLE_BGP_VNC
5434 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5435 && (safi
== SAFI_UNICAST
)) {
5436 if (vnc_implicit_withdraw
) {
5437 vnc_import_bgp_add_route(bgp
, p
, pi
);
5438 vnc_import_bgp_exterior_add_route(
5444 /* Nexthop reachability check. */
5445 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5446 && (safi
== SAFI_UNICAST
5447 || safi
== SAFI_LABELED_UNICAST
)) {
5449 struct bgp
*bgp_nexthop
= bgp
;
5451 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5452 bgp_nexthop
= pi
->extra
->bgp_orig
;
5454 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5455 afi
, safi
, pi
, NULL
,
5457 bgp_path_info_set_flag(dest
, pi
,
5460 if (BGP_DEBUG(nht
, NHT
)) {
5461 char buf1
[INET6_ADDRSTRLEN
];
5462 inet_ntop(p
->family
,
5466 "%s(%s): Route not in table, not advertising",
5469 bgp_path_info_unset_flag(
5470 dest
, pi
, BGP_PATH_VALID
);
5473 /* Delete the NHT structure if any, if we're
5475 * enabling/disabling import check. We
5476 * deregister the route
5477 * from NHT to avoid overloading NHT and the
5478 * process interaction
5480 bgp_unlink_nexthop(pi
);
5481 bgp_path_info_set_flag(dest
, pi
,
5484 /* Process change. */
5485 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5486 bgp_process(bgp
, dest
, afi
, safi
);
5488 if (SAFI_UNICAST
== safi
5489 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5491 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5492 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5496 bgp_dest_unlock_node(dest
);
5497 aspath_unintern(&attr
.aspath
);
5502 /* Make new BGP info. */
5503 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5505 /* Nexthop reachability check. */
5506 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5507 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5508 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, safi
, new, NULL
, 0))
5509 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5511 if (BGP_DEBUG(nht
, NHT
)) {
5512 char buf1
[INET6_ADDRSTRLEN
];
5513 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5516 "%s(%s): Route not in table, not advertising",
5519 bgp_path_info_unset_flag(dest
, new, BGP_PATH_VALID
);
5522 /* Delete the NHT structure if any, if we're toggling between
5523 * enabling/disabling import check. We deregister the route
5524 * from NHT to avoid overloading NHT and the process interaction
5526 bgp_unlink_nexthop(new);
5528 bgp_path_info_set_flag(dest
, new, BGP_PATH_VALID
);
5531 /* Aggregate address increment. */
5532 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5534 /* Register new BGP information. */
5535 bgp_path_info_add(dest
, new);
5537 /* route_node_get lock */
5538 bgp_dest_unlock_node(dest
);
5540 /* Process change. */
5541 bgp_process(bgp
, dest
, afi
, safi
);
5543 if (SAFI_UNICAST
== safi
5544 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5545 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5546 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5549 /* Unintern original. */
5550 aspath_unintern(&attr
.aspath
);
5553 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5556 struct bgp_dest
*dest
;
5557 struct bgp_path_info
*pi
;
5559 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5561 /* Check selected route and self inserted route. */
5562 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5563 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5564 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5567 /* Withdraw static BGP route from routing table. */
5569 if (SAFI_UNICAST
== safi
5570 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5571 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5572 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5574 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5575 bgp_unlink_nexthop(pi
);
5576 bgp_path_info_delete(dest
, pi
);
5577 bgp_process(bgp
, dest
, afi
, safi
);
5580 /* Unlock bgp_node_lookup. */
5581 bgp_dest_unlock_node(dest
);
5585 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5587 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5588 afi_t afi
, safi_t safi
,
5589 struct prefix_rd
*prd
)
5591 struct bgp_dest
*dest
;
5592 struct bgp_path_info
*pi
;
5594 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5596 /* Check selected route and self inserted route. */
5597 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5598 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5599 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5602 /* Withdraw static BGP route from routing table. */
5604 #ifdef ENABLE_BGP_VNC
5605 rfapiProcessWithdraw(
5606 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5607 1); /* Kill, since it is an administrative change */
5609 if (SAFI_MPLS_VPN
== safi
5610 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5611 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5613 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5614 bgp_path_info_delete(dest
, pi
);
5615 bgp_process(bgp
, dest
, afi
, safi
);
5618 /* Unlock bgp_node_lookup. */
5619 bgp_dest_unlock_node(dest
);
5622 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5623 struct bgp_static
*bgp_static
, afi_t afi
,
5626 struct bgp_dest
*dest
;
5627 struct bgp_path_info
*new;
5628 struct attr
*attr_new
;
5629 struct attr attr
= {0};
5630 struct bgp_path_info
*pi
;
5631 #ifdef ENABLE_BGP_VNC
5632 mpls_label_t label
= 0;
5634 uint32_t num_labels
= 0;
5639 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5641 dest
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5644 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5646 attr
.nexthop
= bgp_static
->igpnexthop
;
5647 attr
.med
= bgp_static
->igpmetric
;
5648 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5650 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5651 || (safi
== SAFI_ENCAP
)) {
5652 if (afi
== AFI_IP
) {
5653 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5654 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5657 if (afi
== AFI_L2VPN
) {
5658 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5660 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5661 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5662 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5663 sizeof(struct in6_addr
));
5664 memcpy(&attr
.esi
, bgp_static
->eth_s_id
, sizeof(esi_t
));
5665 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5666 struct bgp_encap_type_vxlan bet
;
5667 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5668 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5669 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5671 if (bgp_static
->router_mac
) {
5672 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5675 /* Apply route-map. */
5676 if (bgp_static
->rmap
.name
) {
5677 struct attr attr_tmp
= attr
;
5678 struct bgp_path_info rmap_path
;
5679 route_map_result_t ret
;
5681 rmap_path
.peer
= bgp
->peer_self
;
5682 rmap_path
.attr
= &attr_tmp
;
5684 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5686 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, &rmap_path
);
5688 bgp
->peer_self
->rmap_type
= 0;
5690 if (ret
== RMAP_DENYMATCH
) {
5691 /* Free uninterned attribute. */
5692 bgp_attr_flush(&attr_tmp
);
5694 /* Unintern original. */
5695 aspath_unintern(&attr
.aspath
);
5696 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5701 attr_new
= bgp_attr_intern(&attr_tmp
);
5703 attr_new
= bgp_attr_intern(&attr
);
5706 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
5707 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5708 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5712 memset(&add
, 0, sizeof(union gw_addr
));
5713 if (attrhash_cmp(pi
->attr
, attr_new
)
5714 && overlay_index_equal(afi
, pi
, &add
)
5715 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5716 bgp_dest_unlock_node(dest
);
5717 bgp_attr_unintern(&attr_new
);
5718 aspath_unintern(&attr
.aspath
);
5721 /* The attribute is changed. */
5722 bgp_path_info_set_flag(dest
, pi
, BGP_PATH_ATTR_CHANGED
);
5724 /* Rewrite BGP route information. */
5725 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5726 bgp_path_info_restore(dest
, pi
);
5728 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5729 bgp_attr_unintern(&pi
->attr
);
5730 pi
->attr
= attr_new
;
5731 pi
->uptime
= bgp_clock();
5732 #ifdef ENABLE_BGP_VNC
5734 label
= decode_label(&pi
->extra
->label
[0]);
5737 /* Process change. */
5738 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5739 bgp_process(bgp
, dest
, afi
, safi
);
5741 if (SAFI_MPLS_VPN
== safi
5742 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5743 vpn_leak_to_vrf_update(bgp
, pi
);
5745 #ifdef ENABLE_BGP_VNC
5746 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5747 pi
->attr
, afi
, safi
, pi
->type
,
5748 pi
->sub_type
, &label
);
5750 bgp_dest_unlock_node(dest
);
5751 aspath_unintern(&attr
.aspath
);
5757 /* Make new BGP info. */
5758 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5760 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5761 new->extra
= bgp_path_info_extra_new();
5763 new->extra
->label
[0] = bgp_static
->label
;
5764 new->extra
->num_labels
= num_labels
;
5766 #ifdef ENABLE_BGP_VNC
5767 label
= decode_label(&bgp_static
->label
);
5770 /* Aggregate address increment. */
5771 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5773 /* Register new BGP information. */
5774 bgp_path_info_add(dest
, new);
5775 /* route_node_get lock */
5776 bgp_dest_unlock_node(dest
);
5778 /* Process change. */
5779 bgp_process(bgp
, dest
, afi
, safi
);
5781 if (SAFI_MPLS_VPN
== safi
5782 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5783 vpn_leak_to_vrf_update(bgp
, new);
5785 #ifdef ENABLE_BGP_VNC
5786 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5787 safi
, new->type
, new->sub_type
, &label
);
5790 /* Unintern original. */
5791 aspath_unintern(&attr
.aspath
);
5794 /* Configure static BGP network. When user don't run zebra, static
5795 route should be installed as valid. */
5796 int bgp_static_set(struct bgp
*bgp
, const char *negate
, struct prefix
*pfx
,
5797 afi_t afi
, safi_t safi
, const char *rmap
, int backdoor
,
5798 uint32_t label_index
, char *errmsg
, size_t errmsg_len
)
5801 struct bgp_static
*bgp_static
;
5802 struct bgp_dest
*dest
;
5803 uint8_t need_update
= 0;
5805 prefix_copy(&p
, pfx
);
5810 /* Set BGP static route configuration. */
5811 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5814 snprintf(errmsg
, errmsg_len
,
5815 "Can't find static route specified\n");
5819 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5821 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5822 && (label_index
!= bgp_static
->label_index
)) {
5823 snprintf(errmsg
, errmsg_len
,
5824 "label-index doesn't match static route\n");
5828 if ((rmap
&& bgp_static
->rmap
.name
)
5829 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5830 snprintf(errmsg
, errmsg_len
,
5831 "route-map name doesn't match static route\n");
5835 /* Update BGP RIB. */
5836 if (!bgp_static
->backdoor
)
5837 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5839 /* Clear configuration. */
5840 bgp_static_free(bgp_static
);
5841 bgp_dest_set_bgp_static_info(dest
, NULL
);
5842 bgp_dest_unlock_node(dest
);
5843 bgp_dest_unlock_node(dest
);
5846 /* Set BGP static route configuration. */
5847 dest
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5848 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5850 /* Configuration change. */
5851 /* Label index cannot be changed. */
5852 if (bgp_static
->label_index
!= label_index
) {
5853 snprintf(errmsg
, errmsg_len
,
5854 "cannot change label-index\n");
5858 /* Check previous routes are installed into BGP. */
5859 if (bgp_static
->valid
5860 && bgp_static
->backdoor
!= backdoor
)
5863 bgp_static
->backdoor
= backdoor
;
5866 XFREE(MTYPE_ROUTE_MAP_NAME
,
5867 bgp_static
->rmap
.name
);
5868 route_map_counter_decrement(
5869 bgp_static
->rmap
.map
);
5870 bgp_static
->rmap
.name
=
5871 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5872 bgp_static
->rmap
.map
=
5873 route_map_lookup_by_name(rmap
);
5874 route_map_counter_increment(
5875 bgp_static
->rmap
.map
);
5877 XFREE(MTYPE_ROUTE_MAP_NAME
,
5878 bgp_static
->rmap
.name
);
5879 route_map_counter_decrement(
5880 bgp_static
->rmap
.map
);
5881 bgp_static
->rmap
.map
= NULL
;
5882 bgp_static
->valid
= 0;
5884 bgp_dest_unlock_node(dest
);
5886 /* New configuration. */
5887 bgp_static
= bgp_static_new();
5888 bgp_static
->backdoor
= backdoor
;
5889 bgp_static
->valid
= 0;
5890 bgp_static
->igpmetric
= 0;
5891 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5892 bgp_static
->label_index
= label_index
;
5895 XFREE(MTYPE_ROUTE_MAP_NAME
,
5896 bgp_static
->rmap
.name
);
5897 route_map_counter_decrement(
5898 bgp_static
->rmap
.map
);
5899 bgp_static
->rmap
.name
=
5900 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5901 bgp_static
->rmap
.map
=
5902 route_map_lookup_by_name(rmap
);
5903 route_map_counter_increment(
5904 bgp_static
->rmap
.map
);
5906 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
5909 bgp_static
->valid
= 1;
5911 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5913 if (!bgp_static
->backdoor
)
5914 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5920 void bgp_static_add(struct bgp
*bgp
)
5924 struct bgp_dest
*dest
;
5925 struct bgp_dest
*rm
;
5926 struct bgp_table
*table
;
5927 struct bgp_static
*bgp_static
;
5929 FOREACH_AFI_SAFI (afi
, safi
)
5930 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5931 dest
= bgp_route_next(dest
)) {
5932 if (!bgp_dest_has_bgp_path_info_data(dest
))
5935 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5936 || (safi
== SAFI_EVPN
)) {
5937 table
= bgp_dest_get_bgp_table_info(dest
);
5939 for (rm
= bgp_table_top(table
); rm
;
5940 rm
= bgp_route_next(rm
)) {
5942 bgp_dest_get_bgp_static_info(
5944 bgp_static_update_safi(
5945 bgp
, bgp_dest_get_prefix(rm
),
5946 bgp_static
, afi
, safi
);
5950 bgp
, bgp_dest_get_prefix(dest
),
5951 bgp_dest_get_bgp_static_info(dest
), afi
,
5957 /* Called from bgp_delete(). Delete all static routes from the BGP
5959 void bgp_static_delete(struct bgp
*bgp
)
5963 struct bgp_dest
*dest
;
5964 struct bgp_dest
*rm
;
5965 struct bgp_table
*table
;
5966 struct bgp_static
*bgp_static
;
5968 FOREACH_AFI_SAFI (afi
, safi
)
5969 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
5970 dest
= bgp_route_next(dest
)) {
5971 if (!bgp_dest_has_bgp_path_info_data(dest
))
5974 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5975 || (safi
== SAFI_EVPN
)) {
5976 table
= bgp_dest_get_bgp_table_info(dest
);
5978 for (rm
= bgp_table_top(table
); rm
;
5979 rm
= bgp_route_next(rm
)) {
5981 bgp_dest_get_bgp_static_info(
5986 bgp_static_withdraw_safi(
5987 bgp
, bgp_dest_get_prefix(rm
),
5989 (struct prefix_rd
*)
5990 bgp_dest_get_prefix(
5992 bgp_static_free(bgp_static
);
5993 bgp_dest_set_bgp_static_info(rm
,
5995 bgp_dest_unlock_node(rm
);
5998 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
5999 bgp_static_withdraw(bgp
,
6000 bgp_dest_get_prefix(dest
),
6002 bgp_static_free(bgp_static
);
6003 bgp_dest_set_bgp_static_info(dest
, NULL
);
6004 bgp_dest_unlock_node(dest
);
6009 void bgp_static_redo_import_check(struct bgp
*bgp
)
6013 struct bgp_dest
*dest
;
6014 struct bgp_dest
*rm
;
6015 struct bgp_table
*table
;
6016 struct bgp_static
*bgp_static
;
6018 /* Use this flag to force reprocessing of the route */
6019 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6020 FOREACH_AFI_SAFI (afi
, safi
) {
6021 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
6022 dest
= bgp_route_next(dest
)) {
6023 if (!bgp_dest_has_bgp_path_info_data(dest
))
6026 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
6027 || (safi
== SAFI_EVPN
)) {
6028 table
= bgp_dest_get_bgp_table_info(dest
);
6030 for (rm
= bgp_table_top(table
); rm
;
6031 rm
= bgp_route_next(rm
)) {
6033 bgp_dest_get_bgp_static_info(
6035 bgp_static_update_safi(
6036 bgp
, bgp_dest_get_prefix(rm
),
6037 bgp_static
, afi
, safi
);
6040 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6041 bgp_static_update(bgp
,
6042 bgp_dest_get_prefix(dest
),
6043 bgp_static
, afi
, safi
);
6047 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
6050 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
6053 struct bgp_table
*table
;
6054 struct bgp_dest
*dest
;
6055 struct bgp_path_info
*pi
;
6057 /* Do not install the aggregate route if BGP is in the
6058 * process of termination.
6060 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6061 || (bgp
->peer_self
== NULL
))
6064 table
= bgp
->rib
[afi
][safi
];
6065 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
6066 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6067 if (pi
->peer
== bgp
->peer_self
6068 && ((pi
->type
== ZEBRA_ROUTE_BGP
6069 && pi
->sub_type
== BGP_ROUTE_STATIC
)
6070 || (pi
->type
!= ZEBRA_ROUTE_BGP
6072 == BGP_ROUTE_REDISTRIBUTE
))) {
6073 bgp_aggregate_decrement(
6074 bgp
, bgp_dest_get_prefix(dest
), pi
, afi
,
6076 bgp_unlink_nexthop(pi
);
6077 bgp_path_info_delete(dest
, pi
);
6078 bgp_process(bgp
, dest
, afi
, safi
);
6085 * Purge all networks and redistributed routes from routing table.
6086 * Invoked upon the instance going down.
6088 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
6093 FOREACH_AFI_SAFI (afi
, safi
)
6094 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
6099 * Currently this is used to set static routes for VPN and ENCAP.
6100 * I think it can probably be factored with bgp_static_set.
6102 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6103 const char *ip_str
, const char *rd_str
,
6104 const char *label_str
, const char *rmap_str
,
6105 int evpn_type
, const char *esi
, const char *gwip
,
6106 const char *ethtag
, const char *routermac
)
6108 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6111 struct prefix_rd prd
;
6112 struct bgp_dest
*pdest
;
6113 struct bgp_dest
*dest
;
6114 struct bgp_table
*table
;
6115 struct bgp_static
*bgp_static
;
6116 mpls_label_t label
= MPLS_INVALID_LABEL
;
6117 struct prefix gw_ip
;
6119 /* validate ip prefix */
6120 ret
= str2prefix(ip_str
, &p
);
6122 vty_out(vty
, "%% Malformed prefix\n");
6123 return CMD_WARNING_CONFIG_FAILED
;
6126 if ((afi
== AFI_L2VPN
)
6127 && (bgp_build_evpn_prefix(evpn_type
,
6128 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6129 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6130 return CMD_WARNING_CONFIG_FAILED
;
6133 ret
= str2prefix_rd(rd_str
, &prd
);
6135 vty_out(vty
, "%% Malformed rd\n");
6136 return CMD_WARNING_CONFIG_FAILED
;
6140 unsigned long label_val
;
6141 label_val
= strtoul(label_str
, NULL
, 10);
6142 encode_label(label_val
, &label
);
6145 if (safi
== SAFI_EVPN
) {
6146 if (esi
&& str2esi(esi
, NULL
) == 0) {
6147 vty_out(vty
, "%% Malformed ESI\n");
6148 return CMD_WARNING_CONFIG_FAILED
;
6150 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
6151 vty_out(vty
, "%% Malformed Router MAC\n");
6152 return CMD_WARNING_CONFIG_FAILED
;
6155 memset(&gw_ip
, 0, sizeof(struct prefix
));
6156 ret
= str2prefix(gwip
, &gw_ip
);
6158 vty_out(vty
, "%% Malformed GatewayIp\n");
6159 return CMD_WARNING_CONFIG_FAILED
;
6161 if ((gw_ip
.family
== AF_INET
6162 && is_evpn_prefix_ipaddr_v6(
6163 (struct prefix_evpn
*)&p
))
6164 || (gw_ip
.family
== AF_INET6
6165 && is_evpn_prefix_ipaddr_v4(
6166 (struct prefix_evpn
*)&p
))) {
6168 "%% GatewayIp family differs with IP prefix\n");
6169 return CMD_WARNING_CONFIG_FAILED
;
6173 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6174 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6175 bgp_dest_set_bgp_table_info(pdest
,
6176 bgp_table_init(bgp
, afi
, safi
));
6177 table
= bgp_dest_get_bgp_table_info(pdest
);
6179 dest
= bgp_node_get(table
, &p
);
6181 if (bgp_dest_has_bgp_path_info_data(dest
)) {
6182 vty_out(vty
, "%% Same network configuration exists\n");
6183 bgp_dest_unlock_node(dest
);
6185 /* New configuration. */
6186 bgp_static
= bgp_static_new();
6187 bgp_static
->backdoor
= 0;
6188 bgp_static
->valid
= 0;
6189 bgp_static
->igpmetric
= 0;
6190 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
6191 bgp_static
->label
= label
;
6192 bgp_static
->prd
= prd
;
6195 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
6196 route_map_counter_decrement(bgp_static
->rmap
.map
);
6197 bgp_static
->rmap
.name
=
6198 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
6199 bgp_static
->rmap
.map
=
6200 route_map_lookup_by_name(rmap_str
);
6201 route_map_counter_increment(bgp_static
->rmap
.map
);
6204 if (safi
== SAFI_EVPN
) {
6206 bgp_static
->eth_s_id
=
6209 str2esi(esi
, bgp_static
->eth_s_id
);
6212 bgp_static
->router_mac
=
6213 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
6214 (void)prefix_str2mac(routermac
,
6215 bgp_static
->router_mac
);
6218 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
6220 bgp_dest_set_bgp_static_info(dest
, bgp_static
);
6222 bgp_static
->valid
= 1;
6223 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
6229 /* Configure static BGP network. */
6230 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
6231 const char *ip_str
, const char *rd_str
,
6232 const char *label_str
, int evpn_type
, const char *esi
,
6233 const char *gwip
, const char *ethtag
)
6235 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6238 struct prefix_rd prd
;
6239 struct bgp_dest
*pdest
;
6240 struct bgp_dest
*dest
;
6241 struct bgp_table
*table
;
6242 struct bgp_static
*bgp_static
;
6243 mpls_label_t label
= MPLS_INVALID_LABEL
;
6245 /* Convert IP prefix string to struct prefix. */
6246 ret
= str2prefix(ip_str
, &p
);
6248 vty_out(vty
, "%% Malformed prefix\n");
6249 return CMD_WARNING_CONFIG_FAILED
;
6252 if ((afi
== AFI_L2VPN
)
6253 && (bgp_build_evpn_prefix(evpn_type
,
6254 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
6255 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
6256 return CMD_WARNING_CONFIG_FAILED
;
6258 ret
= str2prefix_rd(rd_str
, &prd
);
6260 vty_out(vty
, "%% Malformed rd\n");
6261 return CMD_WARNING_CONFIG_FAILED
;
6265 unsigned long label_val
;
6266 label_val
= strtoul(label_str
, NULL
, 10);
6267 encode_label(label_val
, &label
);
6270 pdest
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
6271 if (!bgp_dest_has_bgp_path_info_data(pdest
))
6272 bgp_dest_set_bgp_table_info(pdest
,
6273 bgp_table_init(bgp
, afi
, safi
));
6275 bgp_dest_unlock_node(pdest
);
6276 table
= bgp_dest_get_bgp_table_info(pdest
);
6278 dest
= bgp_node_lookup(table
, &p
);
6281 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
6283 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
6284 bgp_static_free(bgp_static
);
6285 bgp_dest_set_bgp_static_info(dest
, NULL
);
6286 bgp_dest_unlock_node(dest
);
6287 bgp_dest_unlock_node(dest
);
6289 vty_out(vty
, "%% Can't find the route\n");
6294 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
6295 const char *rmap_name
)
6297 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6298 struct bgp_rmap
*rmap
;
6300 rmap
= &bgp
->table_map
[afi
][safi
];
6302 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6303 route_map_counter_decrement(rmap
->map
);
6304 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
6305 rmap
->map
= route_map_lookup_by_name(rmap_name
);
6306 route_map_counter_increment(rmap
->map
);
6308 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6309 route_map_counter_decrement(rmap
->map
);
6313 if (bgp_fibupd_safi(safi
))
6314 bgp_zebra_announce_table(bgp
, afi
, safi
);
6319 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
6320 const char *rmap_name
)
6322 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6323 struct bgp_rmap
*rmap
;
6325 rmap
= &bgp
->table_map
[afi
][safi
];
6326 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
6327 route_map_counter_decrement(rmap
->map
);
6330 if (bgp_fibupd_safi(safi
))
6331 bgp_zebra_announce_table(bgp
, afi
, safi
);
6336 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6339 if (bgp
->table_map
[afi
][safi
].name
) {
6340 vty_out(vty
, " table-map %s\n",
6341 bgp
->table_map
[afi
][safi
].name
);
6345 DEFUN (bgp_table_map
,
6348 "BGP table to RIB route download filter\n"
6349 "Name of the route map\n")
6352 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6353 argv
[idx_word
]->arg
);
6355 DEFUN (no_bgp_table_map
,
6356 no_bgp_table_map_cmd
,
6357 "no table-map WORD",
6359 "BGP table to RIB route download filter\n"
6360 "Name of the route map\n")
6363 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
6364 argv
[idx_word
]->arg
);
6367 DEFPY_YANG (bgp_network
, bgp_network_cmd
,
6369 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6370 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6371 backdoor$backdoor}]",
6373 "Specify a network to announce via BGP\n"
6378 "Route-map to modify the attributes\n"
6379 "Name of the route map\n"
6380 "Label index to associate with the prefix\n"
6381 "Label index value\n"
6382 "Specify a BGP backdoor route\n")
6384 char addr_prefix_str
[PREFIX_STRLEN
];
6385 char base_xpath
[XPATH_MAXLEN
];
6392 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
6394 sizeof(addr_prefix_str
));
6396 vty_out(vty
, "%% Inconsistent address and mask\n");
6397 return CMD_WARNING_CONFIG_FAILED
;
6401 afi
= bgp_node_afi(vty
);
6402 safi
= bgp_node_safi(vty
);
6405 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6407 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6410 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6411 NB_OP_CREATE
, map_name
);
6413 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6414 NB_OP_DESTROY
, NULL
);
6416 if (label_index_str
)
6417 nb_cli_enqueue_change(vty
, "./label-index",
6418 NB_OP_MODIFY
, label_index_str
);
6420 nb_cli_enqueue_change(vty
, "./backdoor", NB_OP_MODIFY
,
6421 backdoor
? "true" : "false");
6425 base_xpath
, sizeof(base_xpath
),
6426 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6427 yang_afi_safi_value2identity(afi
, safi
),
6428 bgp_afi_safi_get_container_str(afi
, safi
),
6429 address_str
? addr_prefix_str
: prefix_str
);
6431 return nb_cli_apply_changes(vty
, base_xpath
);
6434 DEFPY_YANG (ipv6_bgp_network
,
6435 ipv6_bgp_network_cmd
,
6436 "[no] network X:X::X:X/M$prefix \
6437 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6439 "Specify a network to announce via BGP\n"
6441 "Route-map to modify the attributes\n"
6442 "Name of the route map\n"
6443 "Label index to associate with the prefix\n"
6444 "Label index value\n")
6446 char base_xpath
[XPATH_MAXLEN
];
6450 afi
= bgp_node_afi(vty
);
6451 safi
= bgp_node_safi(vty
);
6454 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
6456 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
6459 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6460 NB_OP_MODIFY
, map_name
);
6462 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
6463 NB_OP_DESTROY
, NULL
);
6465 if (label_index_str
)
6466 nb_cli_enqueue_change(vty
, "./label-index",
6467 NB_OP_MODIFY
, label_index_str
);
6471 base_xpath
, sizeof(base_xpath
),
6472 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6473 yang_afi_safi_value2identity(afi
, safi
),
6474 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
6476 return nb_cli_apply_changes(vty
, base_xpath
);
6479 void cli_show_bgp_global_afi_safi_network_config(struct vty
*vty
,
6480 struct lyd_node
*dnode
,
6483 vty_out(vty
, " network %s", yang_dnode_get_string(dnode
, "./prefix"));
6485 if (yang_dnode_exists(dnode
, "./label-index"))
6486 vty_out(vty
, " label-index %s",
6487 yang_dnode_get_string(dnode
, "./label-index"));
6489 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
6490 vty_out(vty
, " route-map %s",
6491 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
6493 if (yang_dnode_get_bool(dnode
, "./backdoor"))
6494 vty_out(vty
, " backdoor");
6499 static struct bgp_aggregate
*bgp_aggregate_new(void)
6501 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6504 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6506 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
6507 route_map_counter_decrement(aggregate
->suppress_map
);
6508 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6509 route_map_counter_decrement(aggregate
->rmap
.map
);
6510 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6514 * Helper function to avoid repeated code: prepare variables for a
6515 * `route_map_apply` call.
6517 * \returns `true` on route map match, otherwise `false`.
6519 static bool aggr_suppress_map_test(struct bgp
*bgp
,
6520 struct bgp_aggregate
*aggregate
,
6521 struct bgp_path_info
*pi
)
6523 const struct prefix
*p
= bgp_dest_get_prefix(pi
->net
);
6524 route_map_result_t rmr
= RMAP_DENYMATCH
;
6525 struct bgp_path_info rmap_path
= {};
6526 struct attr attr
= {};
6528 /* No route map entries created, just don't match. */
6529 if (aggregate
->suppress_map
== NULL
)
6532 /* Call route map matching and return result. */
6533 attr
.aspath
= aspath_empty();
6534 rmap_path
.peer
= bgp
->peer_self
;
6535 rmap_path
.attr
= &attr
;
6537 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_AGGREGATE
);
6538 rmr
= route_map_apply(aggregate
->suppress_map
, p
, &rmap_path
);
6539 bgp
->peer_self
->rmap_type
= 0;
6541 bgp_attr_flush(&attr
);
6543 return rmr
== RMAP_PERMITMATCH
;
6546 /** Test whether the aggregation has suppressed this path or not. */
6547 static bool aggr_suppress_exists(struct bgp_aggregate
*aggregate
,
6548 struct bgp_path_info
*pi
)
6550 if (pi
->extra
== NULL
|| pi
->extra
->aggr_suppressors
== NULL
)
6553 return listnode_lookup(pi
->extra
->aggr_suppressors
, aggregate
) != NULL
;
6557 * Suppress this path and keep the reference.
6559 * \returns `true` if needs processing otherwise `false`.
6561 static bool aggr_suppress_path(struct bgp_aggregate
*aggregate
,
6562 struct bgp_path_info
*pi
)
6564 struct bgp_path_info_extra
*pie
;
6566 /* Path is already suppressed by this aggregation. */
6567 if (aggr_suppress_exists(aggregate
, pi
))
6570 pie
= bgp_path_info_extra_get(pi
);
6572 /* This is the first suppression, allocate memory and list it. */
6573 if (pie
->aggr_suppressors
== NULL
)
6574 pie
->aggr_suppressors
= list_new();
6576 listnode_add(pie
->aggr_suppressors
, aggregate
);
6578 /* Only mark for processing if suppressed. */
6579 if (listcount(pie
->aggr_suppressors
) == 1) {
6580 if (BGP_DEBUG(update
, UPDATE_OUT
))
6581 zlog_debug("aggregate-address suppressing: %pFX",
6582 bgp_dest_get_prefix(pi
->net
));
6584 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6592 * Unsuppress this path and remove the reference.
6594 * \returns `true` if needs processing otherwise `false`.
6596 static bool aggr_unsuppress_path(struct bgp_aggregate
*aggregate
,
6597 struct bgp_path_info
*pi
)
6599 /* Path wasn't suppressed. */
6600 if (!aggr_suppress_exists(aggregate
, pi
))
6603 listnode_delete(pi
->extra
->aggr_suppressors
, aggregate
);
6605 /* Unsuppress and free extra memory if last item. */
6606 if (listcount(pi
->extra
->aggr_suppressors
) == 0) {
6607 if (BGP_DEBUG(update
, UPDATE_OUT
))
6608 zlog_debug("aggregate-address unsuppressing: %pFX",
6609 bgp_dest_get_prefix(pi
->net
));
6611 list_delete(&pi
->extra
->aggr_suppressors
);
6612 bgp_path_info_set_flag(pi
->net
, pi
, BGP_PATH_ATTR_CHANGED
);
6619 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6620 struct aspath
*aspath
,
6621 struct community
*comm
,
6622 struct ecommunity
*ecomm
,
6623 struct lcommunity
*lcomm
)
6625 static struct aspath
*ae
= NULL
;
6628 ae
= aspath_empty();
6633 if (origin
!= pi
->attr
->origin
)
6636 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6639 if (!community_cmp(pi
->attr
->community
, comm
))
6642 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6645 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6648 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6654 static void bgp_aggregate_install(
6655 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6656 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6657 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6658 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6660 struct bgp_dest
*dest
;
6661 struct bgp_table
*table
;
6662 struct bgp_path_info
*pi
, *orig
, *new;
6665 table
= bgp
->rib
[afi
][safi
];
6667 dest
= bgp_node_get(table
, p
);
6669 for (orig
= pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
6670 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6671 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6675 * If we have paths with different MEDs, then don't install
6676 * (or uninstall) the aggregate route.
6678 if (aggregate
->match_med
&& aggregate
->med_mismatched
)
6679 goto uninstall_aggregate_route
;
6681 if (aggregate
->count
> 0) {
6683 * If the aggregate information has not changed
6684 * no need to re-install it again.
6686 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6687 ecommunity
, lcommunity
)) {
6688 bgp_dest_unlock_node(dest
);
6691 aspath_free(aspath
);
6693 community_free(&community
);
6695 ecommunity_free(&ecommunity
);
6697 lcommunity_free(&lcommunity
);
6703 * Mark the old as unusable
6706 bgp_path_info_delete(dest
, pi
);
6708 attr
= bgp_attr_aggregate_intern(
6709 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6710 aggregate
, atomic_aggregate
, p
);
6713 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6714 if (BGP_DEBUG(update_groups
, UPDATE_GROUPS
))
6715 zlog_debug("%s: %pFX null attribute", __func__
,
6720 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6721 bgp
->peer_self
, attr
, dest
);
6723 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6725 bgp_path_info_add(dest
, new);
6726 bgp_process(bgp
, dest
, afi
, safi
);
6728 uninstall_aggregate_route
:
6729 for (pi
= orig
; pi
; pi
= pi
->next
)
6730 if (pi
->peer
== bgp
->peer_self
6731 && pi
->type
== ZEBRA_ROUTE_BGP
6732 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6735 /* Withdraw static BGP route from routing table. */
6737 bgp_path_info_delete(dest
, pi
);
6738 bgp_process(bgp
, dest
, afi
, safi
);
6742 bgp_dest_unlock_node(dest
);
6746 * Check if the current path has different MED than other known paths.
6748 * \returns `true` if the MED matched the others else `false`.
6750 static bool bgp_aggregate_med_match(struct bgp_aggregate
*aggregate
,
6751 struct bgp
*bgp
, struct bgp_path_info
*pi
)
6753 uint32_t cur_med
= bgp_med_value(pi
->attr
, bgp
);
6755 /* This is the first route being analyzed. */
6756 if (!aggregate
->med_initialized
) {
6757 aggregate
->med_initialized
= true;
6758 aggregate
->med_mismatched
= false;
6759 aggregate
->med_matched_value
= cur_med
;
6761 /* Check if routes with different MED showed up. */
6762 if (cur_med
!= aggregate
->med_matched_value
)
6763 aggregate
->med_mismatched
= true;
6766 return !aggregate
->med_mismatched
;
6770 * Initializes and tests all routes in the aggregate address path for MED
6773 * \returns `true` if all MEDs are the same otherwise `false`.
6775 static bool bgp_aggregate_test_all_med(struct bgp_aggregate
*aggregate
,
6776 struct bgp
*bgp
, const struct prefix
*p
,
6777 afi_t afi
, safi_t safi
)
6779 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6780 const struct prefix
*dest_p
;
6781 struct bgp_dest
*dest
, *top
;
6782 struct bgp_path_info
*pi
;
6783 bool med_matched
= true;
6785 aggregate
->med_initialized
= false;
6787 top
= bgp_node_get(table
, p
);
6788 for (dest
= bgp_node_get(table
, p
); dest
;
6789 dest
= bgp_route_next_until(dest
, top
)) {
6790 dest_p
= bgp_dest_get_prefix(dest
);
6791 if (dest_p
->prefixlen
<= p
->prefixlen
)
6794 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6795 if (BGP_PATH_HOLDDOWN(pi
))
6797 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6799 if (!bgp_aggregate_med_match(aggregate
, bgp
, pi
)) {
6800 med_matched
= false;
6807 bgp_dest_unlock_node(top
);
6813 * Toggles the route suppression status for this aggregate address
6816 void bgp_aggregate_toggle_suppressed(struct bgp_aggregate
*aggregate
,
6817 struct bgp
*bgp
, const struct prefix
*p
,
6818 afi_t afi
, safi_t safi
, bool suppress
)
6820 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
6821 const struct prefix
*dest_p
;
6822 struct bgp_dest
*dest
, *top
;
6823 struct bgp_path_info
*pi
;
6824 bool toggle_suppression
;
6826 /* We've found a different MED we must revert any suppressed routes. */
6827 top
= bgp_node_get(table
, p
);
6828 for (dest
= bgp_node_get(table
, p
); dest
;
6829 dest
= bgp_route_next_until(dest
, top
)) {
6830 dest_p
= bgp_dest_get_prefix(dest
);
6831 if (dest_p
->prefixlen
<= p
->prefixlen
)
6834 toggle_suppression
= false;
6835 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6836 if (BGP_PATH_HOLDDOWN(pi
))
6838 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6841 /* We are toggling suppression back. */
6843 /* Suppress route if not suppressed already. */
6844 if (aggr_suppress_path(aggregate
, pi
))
6845 toggle_suppression
= true;
6849 /* Install route if there is no more suppression. */
6850 if (aggr_unsuppress_path(aggregate
, pi
))
6851 toggle_suppression
= true;
6854 if (toggle_suppression
)
6855 bgp_process(bgp
, dest
, afi
, safi
);
6857 bgp_dest_unlock_node(top
);
6861 * Aggregate address MED matching incremental test: this function is called
6862 * when the initial aggregation occurred and we are only testing a single
6865 * In addition to testing and setting the MED validity it also installs back
6866 * suppressed routes (if summary is configured).
6868 * Must not be called in `bgp_aggregate_route`.
6870 static void bgp_aggregate_med_update(struct bgp_aggregate
*aggregate
,
6871 struct bgp
*bgp
, const struct prefix
*p
,
6872 afi_t afi
, safi_t safi
,
6873 struct bgp_path_info
*pi
, bool is_adding
)
6875 /* MED matching disabled. */
6876 if (!aggregate
->match_med
)
6879 /* Aggregation with different MED, nothing to do. */
6880 if (aggregate
->med_mismatched
)
6884 * Test the current entry:
6886 * is_adding == true: if the new entry doesn't match then we must
6887 * install all suppressed routes.
6889 * is_adding == false: if the entry being removed was the last
6890 * unmatching entry then we can suppress all routes.
6893 if (bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
)
6894 && aggregate
->summary_only
)
6895 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
,
6898 bgp_aggregate_med_match(aggregate
, bgp
, pi
);
6900 /* No mismatches, just quit. */
6901 if (!aggregate
->med_mismatched
)
6904 /* Route summarization is disabled. */
6905 if (!aggregate
->summary_only
)
6908 bgp_aggregate_toggle_suppressed(aggregate
, bgp
, p
, afi
, safi
, false);
6911 /* Update an aggregate as routes are added/removed from the BGP table */
6912 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6913 safi_t safi
, struct bgp_aggregate
*aggregate
)
6915 struct bgp_table
*table
;
6916 struct bgp_dest
*top
;
6917 struct bgp_dest
*dest
;
6919 struct aspath
*aspath
= NULL
;
6920 struct community
*community
= NULL
;
6921 struct ecommunity
*ecommunity
= NULL
;
6922 struct lcommunity
*lcommunity
= NULL
;
6923 struct bgp_path_info
*pi
;
6924 unsigned long match
= 0;
6925 uint8_t atomic_aggregate
= 0;
6927 /* If the bgp instance is being deleted or self peer is deleted
6928 * then do not create aggregate route
6930 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6931 || (bgp
->peer_self
== NULL
))
6934 /* Initialize and test routes for MED difference. */
6935 if (aggregate
->match_med
)
6936 bgp_aggregate_test_all_med(aggregate
, bgp
, p
, afi
, safi
);
6939 * Reset aggregate count: we might've been called from route map
6940 * update so in that case we must retest all more specific routes.
6942 * \see `bgp_route_map_process_update`.
6944 aggregate
->count
= 0;
6945 aggregate
->incomplete_origin_count
= 0;
6946 aggregate
->incomplete_origin_count
= 0;
6947 aggregate
->egp_origin_count
= 0;
6949 /* ORIGIN attribute: If at least one route among routes that are
6950 aggregated has ORIGIN with the value INCOMPLETE, then the
6951 aggregated route must have the ORIGIN attribute with the value
6952 INCOMPLETE. Otherwise, if at least one route among routes that
6953 are aggregated has ORIGIN with the value EGP, then the aggregated
6954 route must have the origin attribute with the value EGP. In all
6955 other case the value of the ORIGIN attribute of the aggregated
6956 route is INTERNAL. */
6957 origin
= BGP_ORIGIN_IGP
;
6959 table
= bgp
->rib
[afi
][safi
];
6961 top
= bgp_node_get(table
, p
);
6962 for (dest
= bgp_node_get(table
, p
); dest
;
6963 dest
= bgp_route_next_until(dest
, top
)) {
6964 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
6966 if (dest_p
->prefixlen
<= p
->prefixlen
)
6969 /* If suppress fib is enabled and route not installed
6970 * in FIB, skip the route
6972 if (!bgp_check_advertise(bgp
, dest
))
6977 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
6978 if (BGP_PATH_HOLDDOWN(pi
))
6982 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6983 atomic_aggregate
= 1;
6985 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6989 * summary-only aggregate route suppress
6990 * aggregated route announcements.
6993 * Don't create summaries if MED didn't match
6994 * otherwise neither the specific routes and the
6995 * aggregation will be announced.
6997 if (aggregate
->summary_only
6998 && AGGREGATE_MED_VALID(aggregate
)) {
6999 if (aggr_suppress_path(aggregate
, pi
))
7004 * Suppress more specific routes that match the route
7008 * Don't suppress routes if MED matching is enabled and
7009 * it mismatched otherwise we might end up with no
7010 * routes for this path.
7012 if (aggregate
->suppress_map_name
7013 && AGGREGATE_MED_VALID(aggregate
)
7014 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7015 if (aggr_suppress_path(aggregate
, pi
))
7022 * If at least one route among routes that are
7023 * aggregated has ORIGIN with the value INCOMPLETE,
7024 * then the aggregated route MUST have the ORIGIN
7025 * attribute with the value INCOMPLETE. Otherwise, if
7026 * at least one route among routes that are aggregated
7027 * has ORIGIN with the value EGP, then the aggregated
7028 * route MUST have the ORIGIN attribute with the value
7031 switch (pi
->attr
->origin
) {
7032 case BGP_ORIGIN_INCOMPLETE
:
7033 aggregate
->incomplete_origin_count
++;
7035 case BGP_ORIGIN_EGP
:
7036 aggregate
->egp_origin_count
++;
7044 if (!aggregate
->as_set
)
7048 * as-set aggregate route generate origin, as path,
7049 * and community aggregation.
7051 /* Compute aggregate route's as-path.
7053 bgp_compute_aggregate_aspath_hash(aggregate
,
7056 /* Compute aggregate route's community.
7058 if (pi
->attr
->community
)
7059 bgp_compute_aggregate_community_hash(
7061 pi
->attr
->community
);
7063 /* Compute aggregate route's extended community.
7065 if (pi
->attr
->ecommunity
)
7066 bgp_compute_aggregate_ecommunity_hash(
7068 pi
->attr
->ecommunity
);
7070 /* Compute aggregate route's large community.
7072 if (pi
->attr
->lcommunity
)
7073 bgp_compute_aggregate_lcommunity_hash(
7075 pi
->attr
->lcommunity
);
7078 bgp_process(bgp
, dest
, afi
, safi
);
7080 if (aggregate
->as_set
) {
7081 bgp_compute_aggregate_aspath_val(aggregate
);
7082 bgp_compute_aggregate_community_val(aggregate
);
7083 bgp_compute_aggregate_ecommunity_val(aggregate
);
7084 bgp_compute_aggregate_lcommunity_val(aggregate
);
7088 bgp_dest_unlock_node(top
);
7091 if (aggregate
->incomplete_origin_count
> 0)
7092 origin
= BGP_ORIGIN_INCOMPLETE
;
7093 else if (aggregate
->egp_origin_count
> 0)
7094 origin
= BGP_ORIGIN_EGP
;
7096 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7097 origin
= aggregate
->origin
;
7099 if (aggregate
->as_set
) {
7100 if (aggregate
->aspath
)
7101 /* Retrieve aggregate route's as-path.
7103 aspath
= aspath_dup(aggregate
->aspath
);
7105 if (aggregate
->community
)
7106 /* Retrieve aggregate route's community.
7108 community
= community_dup(aggregate
->community
);
7110 if (aggregate
->ecommunity
)
7111 /* Retrieve aggregate route's ecommunity.
7113 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7115 if (aggregate
->lcommunity
)
7116 /* Retrieve aggregate route's lcommunity.
7118 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7121 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
7122 ecommunity
, lcommunity
, atomic_aggregate
,
7126 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
7127 safi_t safi
, struct bgp_aggregate
*aggregate
)
7129 struct bgp_table
*table
;
7130 struct bgp_dest
*top
;
7131 struct bgp_dest
*dest
;
7132 struct bgp_path_info
*pi
;
7133 unsigned long match
;
7135 table
= bgp
->rib
[afi
][safi
];
7137 /* If routes exists below this node, generate aggregate routes. */
7138 top
= bgp_node_get(table
, p
);
7139 for (dest
= bgp_node_get(table
, p
); dest
;
7140 dest
= bgp_route_next_until(dest
, top
)) {
7141 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7143 if (dest_p
->prefixlen
<= p
->prefixlen
)
7147 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
7148 if (BGP_PATH_HOLDDOWN(pi
))
7151 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7154 if (aggregate
->summary_only
&& pi
->extra
7155 && AGGREGATE_MED_VALID(aggregate
)) {
7156 if (aggr_unsuppress_path(aggregate
, pi
))
7160 if (aggregate
->suppress_map_name
7161 && AGGREGATE_MED_VALID(aggregate
)
7162 && aggr_suppress_map_test(bgp
, aggregate
, pi
)) {
7163 if (aggr_unsuppress_path(aggregate
, pi
))
7169 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7170 aggregate
->incomplete_origin_count
--;
7171 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7172 aggregate
->egp_origin_count
--;
7174 if (aggregate
->as_set
) {
7175 /* Remove as-path from aggregate.
7177 bgp_remove_aspath_from_aggregate_hash(
7181 if (pi
->attr
->community
)
7182 /* Remove community from aggregate.
7184 bgp_remove_comm_from_aggregate_hash(
7186 pi
->attr
->community
);
7188 if (pi
->attr
->ecommunity
)
7189 /* Remove ecommunity from aggregate.
7191 bgp_remove_ecomm_from_aggregate_hash(
7193 pi
->attr
->ecommunity
);
7195 if (pi
->attr
->lcommunity
)
7196 /* Remove lcommunity from aggregate.
7198 bgp_remove_lcomm_from_aggregate_hash(
7200 pi
->attr
->lcommunity
);
7204 /* If this node was suppressed, process the change. */
7206 bgp_process(bgp
, dest
, afi
, safi
);
7208 if (aggregate
->as_set
) {
7209 aspath_free(aggregate
->aspath
);
7210 aggregate
->aspath
= NULL
;
7211 if (aggregate
->community
)
7212 community_free(&aggregate
->community
);
7213 if (aggregate
->ecommunity
)
7214 ecommunity_free(&aggregate
->ecommunity
);
7215 if (aggregate
->lcommunity
)
7216 lcommunity_free(&aggregate
->lcommunity
);
7219 bgp_dest_unlock_node(top
);
7222 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
7223 const struct prefix
*aggr_p
,
7224 struct bgp_path_info
*pinew
, afi_t afi
,
7226 struct bgp_aggregate
*aggregate
)
7229 struct aspath
*aspath
= NULL
;
7230 uint8_t atomic_aggregate
= 0;
7231 struct community
*community
= NULL
;
7232 struct ecommunity
*ecommunity
= NULL
;
7233 struct lcommunity
*lcommunity
= NULL
;
7235 /* If the bgp instance is being deleted or self peer is deleted
7236 * then do not create aggregate route
7238 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7239 || (bgp
->peer_self
== NULL
))
7242 /* ORIGIN attribute: If at least one route among routes that are
7243 * aggregated has ORIGIN with the value INCOMPLETE, then the
7244 * aggregated route must have the ORIGIN attribute with the value
7245 * INCOMPLETE. Otherwise, if at least one route among routes that
7246 * are aggregated has ORIGIN with the value EGP, then the aggregated
7247 * route must have the origin attribute with the value EGP. In all
7248 * other case the value of the ORIGIN attribute of the aggregated
7249 * route is INTERNAL.
7251 origin
= BGP_ORIGIN_IGP
;
7256 * This must be called before `summary` check to avoid
7257 * "suppressing" twice.
7259 if (aggregate
->match_med
)
7260 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
,
7263 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7264 aggr_suppress_path(aggregate
, pinew
);
7266 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7267 && aggr_suppress_map_test(bgp
, aggregate
, pinew
))
7268 aggr_suppress_path(aggregate
, pinew
);
7270 switch (pinew
->attr
->origin
) {
7271 case BGP_ORIGIN_INCOMPLETE
:
7272 aggregate
->incomplete_origin_count
++;
7274 case BGP_ORIGIN_EGP
:
7275 aggregate
->egp_origin_count
++;
7283 if (aggregate
->incomplete_origin_count
> 0)
7284 origin
= BGP_ORIGIN_INCOMPLETE
;
7285 else if (aggregate
->egp_origin_count
> 0)
7286 origin
= BGP_ORIGIN_EGP
;
7288 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7289 origin
= aggregate
->origin
;
7291 if (aggregate
->as_set
) {
7292 /* Compute aggregate route's as-path.
7294 bgp_compute_aggregate_aspath(aggregate
,
7295 pinew
->attr
->aspath
);
7297 /* Compute aggregate route's community.
7299 if (pinew
->attr
->community
)
7300 bgp_compute_aggregate_community(
7302 pinew
->attr
->community
);
7304 /* Compute aggregate route's extended community.
7306 if (pinew
->attr
->ecommunity
)
7307 bgp_compute_aggregate_ecommunity(
7309 pinew
->attr
->ecommunity
);
7311 /* Compute aggregate route's large community.
7313 if (pinew
->attr
->lcommunity
)
7314 bgp_compute_aggregate_lcommunity(
7316 pinew
->attr
->lcommunity
);
7318 /* Retrieve aggregate route's as-path.
7320 if (aggregate
->aspath
)
7321 aspath
= aspath_dup(aggregate
->aspath
);
7323 /* Retrieve aggregate route's community.
7325 if (aggregate
->community
)
7326 community
= community_dup(aggregate
->community
);
7328 /* Retrieve aggregate route's ecommunity.
7330 if (aggregate
->ecommunity
)
7331 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7333 /* Retrieve aggregate route's lcommunity.
7335 if (aggregate
->lcommunity
)
7336 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7339 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7340 aspath
, community
, ecommunity
,
7341 lcommunity
, atomic_aggregate
, aggregate
);
7344 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
7346 struct bgp_path_info
*pi
,
7347 struct bgp_aggregate
*aggregate
,
7348 const struct prefix
*aggr_p
)
7351 struct aspath
*aspath
= NULL
;
7352 uint8_t atomic_aggregate
= 0;
7353 struct community
*community
= NULL
;
7354 struct ecommunity
*ecommunity
= NULL
;
7355 struct lcommunity
*lcommunity
= NULL
;
7356 unsigned long match
= 0;
7358 /* If the bgp instance is being deleted or self peer is deleted
7359 * then do not create aggregate route
7361 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7362 || (bgp
->peer_self
== NULL
))
7365 if (BGP_PATH_HOLDDOWN(pi
))
7368 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
7371 if (aggregate
->summary_only
&& AGGREGATE_MED_VALID(aggregate
))
7372 if (aggr_unsuppress_path(aggregate
, pi
))
7375 if (aggregate
->suppress_map_name
&& AGGREGATE_MED_VALID(aggregate
)
7376 && aggr_suppress_map_test(bgp
, aggregate
, pi
))
7377 if (aggr_unsuppress_path(aggregate
, pi
))
7381 * This must be called after `summary`, `suppress-map` check to avoid
7382 * "unsuppressing" twice.
7384 if (aggregate
->match_med
)
7385 bgp_aggregate_med_update(aggregate
, bgp
, aggr_p
, afi
, safi
, pi
,
7388 if (aggregate
->count
> 0)
7391 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
7392 aggregate
->incomplete_origin_count
--;
7393 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
7394 aggregate
->egp_origin_count
--;
7396 if (aggregate
->as_set
) {
7397 /* Remove as-path from aggregate.
7399 bgp_remove_aspath_from_aggregate(aggregate
,
7402 if (pi
->attr
->community
)
7403 /* Remove community from aggregate.
7405 bgp_remove_community_from_aggregate(
7407 pi
->attr
->community
);
7409 if (pi
->attr
->ecommunity
)
7410 /* Remove ecommunity from aggregate.
7412 bgp_remove_ecommunity_from_aggregate(
7414 pi
->attr
->ecommunity
);
7416 if (pi
->attr
->lcommunity
)
7417 /* Remove lcommunity from aggregate.
7419 bgp_remove_lcommunity_from_aggregate(
7421 pi
->attr
->lcommunity
);
7424 /* If this node was suppressed, process the change. */
7426 bgp_process(bgp
, pi
->net
, afi
, safi
);
7428 origin
= BGP_ORIGIN_IGP
;
7429 if (aggregate
->incomplete_origin_count
> 0)
7430 origin
= BGP_ORIGIN_INCOMPLETE
;
7431 else if (aggregate
->egp_origin_count
> 0)
7432 origin
= BGP_ORIGIN_EGP
;
7434 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
7435 origin
= aggregate
->origin
;
7437 if (aggregate
->as_set
) {
7438 /* Retrieve aggregate route's as-path.
7440 if (aggregate
->aspath
)
7441 aspath
= aspath_dup(aggregate
->aspath
);
7443 /* Retrieve aggregate route's community.
7445 if (aggregate
->community
)
7446 community
= community_dup(aggregate
->community
);
7448 /* Retrieve aggregate route's ecommunity.
7450 if (aggregate
->ecommunity
)
7451 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
7453 /* Retrieve aggregate route's lcommunity.
7455 if (aggregate
->lcommunity
)
7456 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
7459 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
7460 aspath
, community
, ecommunity
,
7461 lcommunity
, atomic_aggregate
, aggregate
);
7464 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
7465 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
7467 struct bgp_dest
*child
;
7468 struct bgp_dest
*dest
;
7469 struct bgp_aggregate
*aggregate
;
7470 struct bgp_table
*table
;
7472 table
= bgp
->aggregate
[afi
][safi
];
7474 /* No aggregates configured. */
7475 if (bgp_table_top_nolock(table
) == NULL
)
7478 if (p
->prefixlen
== 0)
7481 if (BGP_PATH_HOLDDOWN(pi
))
7484 /* If suppress fib is enabled and route not installed
7485 * in FIB, do not update the aggregate route
7487 if (!bgp_check_advertise(bgp
, pi
->net
))
7490 child
= bgp_node_get(table
, p
);
7492 /* Aggregate address configuration check. */
7493 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7494 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7496 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7497 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7498 bgp_add_route_to_aggregate(bgp
, dest_p
, pi
, afi
, safi
,
7502 bgp_dest_unlock_node(child
);
7505 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
7506 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
7508 struct bgp_dest
*child
;
7509 struct bgp_dest
*dest
;
7510 struct bgp_aggregate
*aggregate
;
7511 struct bgp_table
*table
;
7513 table
= bgp
->aggregate
[afi
][safi
];
7515 /* No aggregates configured. */
7516 if (bgp_table_top_nolock(table
) == NULL
)
7519 if (p
->prefixlen
== 0)
7522 child
= bgp_node_get(table
, p
);
7524 /* Aggregate address configuration check. */
7525 for (dest
= child
; dest
; dest
= bgp_dest_parent_nolock(dest
)) {
7526 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
7528 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7529 if (aggregate
!= NULL
&& dest_p
->prefixlen
< p
->prefixlen
) {
7530 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
7534 bgp_dest_unlock_node(child
);
7537 /* Aggregate route attribute. */
7538 #define AGGREGATE_SUMMARY_ONLY 1
7539 #define AGGREGATE_AS_SET 1
7540 #define AGGREGATE_AS_UNSET 0
7542 static const char *bgp_origin2str(uint8_t origin
)
7545 case BGP_ORIGIN_IGP
:
7547 case BGP_ORIGIN_EGP
:
7549 case BGP_ORIGIN_INCOMPLETE
:
7550 return "incomplete";
7555 static const char *bgp_rpki_validation2str(enum rpki_states v_state
)
7558 case RPKI_NOT_BEING_USED
:
7568 assert(!"We should never get here this is a dev escape");
7572 int bgp_aggregate_unset(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7573 safi_t safi
, char *errmsg
, size_t errmsg_len
)
7575 struct bgp_dest
*dest
;
7576 struct bgp_aggregate
*aggregate
;
7578 /* If the bgp instance is being deleted or self peer is deleted
7579 * then do not create aggregate route
7581 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
7582 || (bgp
->peer_self
== NULL
))
7586 /* Old configuration check. */
7587 dest
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], prefix
);
7589 snprintf(errmsg
, errmsg_len
,
7590 "There is no aggregate-address configuration.\n");
7594 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7595 bgp_aggregate_delete(bgp
, prefix
, afi
, safi
, aggregate
);
7596 bgp_aggregate_install(bgp
, afi
, safi
, prefix
, 0, NULL
, NULL
, NULL
, NULL
,
7599 /* Unlock aggregate address configuration. */
7600 bgp_dest_set_bgp_aggregate_info(dest
, NULL
);
7602 if (aggregate
->community
)
7603 community_free(&aggregate
->community
);
7605 if (aggregate
->community_hash
) {
7606 /* Delete all communities in the hash.
7608 hash_clean(aggregate
->community_hash
,
7609 bgp_aggr_community_remove
);
7610 /* Free up the community_hash.
7612 hash_free(aggregate
->community_hash
);
7615 if (aggregate
->ecommunity
)
7616 ecommunity_free(&aggregate
->ecommunity
);
7618 if (aggregate
->ecommunity_hash
) {
7619 /* Delete all ecommunities in the hash.
7621 hash_clean(aggregate
->ecommunity_hash
,
7622 bgp_aggr_ecommunity_remove
);
7623 /* Free up the ecommunity_hash.
7625 hash_free(aggregate
->ecommunity_hash
);
7628 if (aggregate
->lcommunity
)
7629 lcommunity_free(&aggregate
->lcommunity
);
7631 if (aggregate
->lcommunity_hash
) {
7632 /* Delete all lcommunities in the hash.
7634 hash_clean(aggregate
->lcommunity_hash
,
7635 bgp_aggr_lcommunity_remove
);
7636 /* Free up the lcommunity_hash.
7638 hash_free(aggregate
->lcommunity_hash
);
7641 if (aggregate
->aspath
)
7642 aspath_free(aggregate
->aspath
);
7644 if (aggregate
->aspath_hash
) {
7645 /* Delete all as-paths in the hash.
7647 hash_clean(aggregate
->aspath_hash
,
7648 bgp_aggr_aspath_remove
);
7649 /* Free up the aspath_hash.
7651 hash_free(aggregate
->aspath_hash
);
7654 bgp_aggregate_free(aggregate
);
7655 bgp_dest_unlock_node(dest
);
7656 bgp_dest_unlock_node(dest
);
7661 int bgp_aggregate_set(struct bgp
*bgp
, struct prefix
*prefix
, afi_t afi
,
7662 safi_t safi
, const char *rmap
, uint8_t summary_only
,
7663 uint8_t as_set
, uint8_t origin
, bool match_med
,
7664 const char *suppress_map
,
7665 char *errmsg
, size_t errmsg_len
)
7668 struct bgp_dest
*dest
;
7669 struct bgp_aggregate
*aggregate
;
7670 uint8_t as_set_new
= as_set
;
7671 char buf
[PREFIX2STR_BUFFER
];
7673 if (suppress_map
&& summary_only
) {
7674 snprintf(errmsg
, errmsg_len
,
7675 "'summary-only' and 'suppress-map' can't be used at the same time\n");
7681 if ((afi
== AFI_IP
&& prefix
->prefixlen
== IPV4_MAX_BITLEN
)
7682 || (afi
== AFI_IP6
&& prefix
->prefixlen
== IPV6_MAX_BITLEN
)) {
7685 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7686 prefix2str(prefix
, buf
, PREFIX_STRLEN
));
7690 /* Old configuration check. */
7691 dest
= bgp_node_get(bgp
->aggregate
[afi
][safi
], prefix
);
7692 aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
7695 snprintf(errmsg
, errmsg_len
,
7696 "There is already same aggregate network.\n");
7697 /* try to remove the old entry */
7698 ret
= bgp_aggregate_unset(bgp
, prefix
, afi
, safi
, errmsg
,
7701 snprintf(errmsg
, errmsg_len
,
7702 "Error deleting aggregate.\n");
7703 bgp_dest_unlock_node(dest
);
7708 /* Make aggregate address structure. */
7709 aggregate
= bgp_aggregate_new();
7710 aggregate
->summary_only
= summary_only
;
7711 aggregate
->match_med
= match_med
;
7713 /* Network operators MUST NOT locally generate any new
7714 * announcements containing AS_SET or AS_CONFED_SET. If they have
7715 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7716 * SHOULD withdraw those routes and re-announce routes for the
7717 * aggregate or component prefixes (i.e., the more-specific routes
7718 * subsumed by the previously aggregated route) without AS_SET
7719 * or AS_CONFED_SET in the updates.
7721 if (bgp
->reject_as_sets
) {
7722 if (as_set
== AGGREGATE_AS_SET
) {
7723 as_set_new
= AGGREGATE_AS_UNSET
;
7725 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
7729 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7733 aggregate
->as_set
= as_set_new
;
7734 aggregate
->safi
= safi
;
7735 /* Override ORIGIN attribute if defined.
7736 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7737 * to IGP which is not what rfc4271 says.
7738 * This enables the same behavior, optionally.
7740 aggregate
->origin
= origin
;
7743 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
7744 route_map_counter_decrement(aggregate
->rmap
.map
);
7745 aggregate
->rmap
.name
=
7746 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
7747 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
7748 route_map_counter_increment(aggregate
->rmap
.map
);
7752 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->suppress_map_name
);
7753 route_map_counter_decrement(aggregate
->suppress_map
);
7755 aggregate
->suppress_map_name
=
7756 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, suppress_map
);
7757 aggregate
->suppress_map
=
7758 route_map_lookup_by_name(aggregate
->suppress_map_name
);
7759 route_map_counter_increment(aggregate
->suppress_map
);
7762 bgp_dest_set_bgp_aggregate_info(dest
, aggregate
);
7764 /* Aggregate address insert into BGP routing table. */
7765 bgp_aggregate_route(bgp
, prefix
, afi
, safi
, aggregate
);
7771 aggregate_addressv4
, aggregate_addressv4_cmd
,
7772 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7774 "|summary-only$summary_only"
7775 "|route-map WORD$rmap_name"
7776 "|origin <egp|igp|incomplete>$origin_s"
7777 "|matching-MED-only$match_med"
7778 "|suppress-map WORD$suppress_map"
7781 "Configure BGP aggregate entries\n"
7782 "Aggregate prefix\n"
7783 "Aggregate address\n"
7785 "Generate AS set path information\n"
7786 "Filter more specific routes from updates\n"
7787 "Apply route map to aggregate network\n"
7792 "Unknown heritage\n"
7793 "Only aggregate routes with matching MED\n"
7794 "Suppress the selected more specific routes\n"
7795 "Route map with the route selectors\n")
7797 char base_xpath
[XPATH_MAXLEN
];
7798 safi_t safi
= bgp_node_safi(vty
);
7799 char prefix_buf
[PREFIX2STR_BUFFER
];
7802 if (netmask_str2prefix_str(addr_str
, mask_str
, prefix_buf
,
7805 vty_out(vty
, "%% Inconsistent address and mask\n");
7806 return CMD_WARNING_CONFIG_FAILED
;
7809 strlcpy(prefix_buf
, prefix_str
, sizeof(prefix_buf
));
7812 if (!no
&& origin_s
)
7813 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7815 if (!no
&& as_set_s
)
7816 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7818 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7820 if (!no
&& summary_only
)
7821 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7824 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7827 if (!no
&& match_med
)
7828 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7830 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7834 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7837 nb_cli_enqueue_change(vty
, "./rmap-policy-export",
7838 NB_OP_DESTROY
, NULL
);
7841 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7844 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7848 base_xpath
, sizeof(base_xpath
),
7849 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7850 yang_afi_safi_value2identity(AFI_IP
, safi
),
7851 bgp_afi_safi_get_container_str(AFI_IP
, safi
), prefix_buf
);
7854 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7856 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7858 return nb_cli_apply_changes(vty
, base_xpath
);
7861 DEFPY_YANG(aggregate_addressv6
, aggregate_addressv6_cmd
,
7862 "[no] aggregate-address X:X::X:X/M$prefix {"
7864 "|summary-only$summary_only"
7865 "|route-map WORD$rmap_name"
7866 "|origin <egp|igp|incomplete>$origin_s"
7867 "|matching-MED-only$match_med"
7868 "|suppress-map WORD$suppress_map"
7871 "Configure BGP aggregate entries\n"
7872 "Aggregate prefix\n"
7873 "Generate AS set path information\n"
7874 "Filter more specific routes from updates\n"
7875 "Apply route map to aggregate network\n"
7880 "Unknown heritage\n"
7881 "Only aggregate routes with matching MED\n"
7882 "Suppress the selected more specific routes\n"
7883 "Route map with the route selectors\n")
7885 char base_xpath
[XPATH_MAXLEN
];
7886 safi_t safi
= bgp_node_safi(vty
);
7888 if (!no
&& origin_s
)
7889 nb_cli_enqueue_change(vty
, "./origin", NB_OP_MODIFY
, origin_s
);
7891 if (!no
&& as_set_s
)
7892 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "true");
7894 nb_cli_enqueue_change(vty
, "./as-set", NB_OP_MODIFY
, "false");
7896 if (!no
&& summary_only
)
7897 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7900 nb_cli_enqueue_change(vty
, "./summary-only", NB_OP_MODIFY
,
7903 if (!no
&& match_med
)
7904 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
, "true");
7906 nb_cli_enqueue_change(vty
, "./match-med", NB_OP_MODIFY
,
7910 nb_cli_enqueue_change(vty
, "./rmap-policy-export", NB_OP_MODIFY
,
7914 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_MODIFY
,
7917 nb_cli_enqueue_change(vty
, "./suppress-map", NB_OP_DESTROY
,
7921 base_xpath
, sizeof(base_xpath
),
7922 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7923 yang_afi_safi_value2identity(AFI_IP6
, safi
),
7924 bgp_afi_safi_get_container_str(AFI_IP6
, safi
), prefix_str
);
7927 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
7929 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
7931 return nb_cli_apply_changes(vty
, base_xpath
);
7934 void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7935 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
7939 vty_out(vty
, " aggregate-address %s",
7940 yang_dnode_get_string(dnode
, "./prefix"));
7942 if (yang_dnode_get_bool(dnode
, "./as-set"))
7943 vty_out(vty
, " as-set");
7945 if (yang_dnode_get_bool(dnode
, "./summary-only"))
7946 vty_out(vty
, " summary-only");
7948 if (yang_dnode_exists(dnode
, "./rmap-policy-export"))
7949 vty_out(vty
, " route-map %s",
7950 yang_dnode_get_string(dnode
, "./rmap-policy-export"));
7952 origin
= yang_dnode_get_enum(dnode
, "./origin");
7953 if (origin
!= BGP_ORIGIN_UNSPECIFIED
)
7954 vty_out(vty
, " origin %s", bgp_origin2str(origin
));
7956 if (yang_dnode_get_bool(dnode
, "./match-med"))
7957 vty_out(vty
, " matching-MED-only");
7962 /* Redistribute route treatment. */
7963 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7964 const union g_addr
*nexthop
, ifindex_t ifindex
,
7965 enum nexthop_types_t nhtype
, uint32_t metric
,
7966 uint8_t type
, unsigned short instance
,
7969 struct bgp_path_info
*new;
7970 struct bgp_path_info
*bpi
;
7971 struct bgp_path_info rmap_path
;
7972 struct bgp_dest
*bn
;
7974 struct attr
*new_attr
;
7976 route_map_result_t ret
;
7977 struct bgp_redist
*red
;
7979 /* Make default attribute. */
7980 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7982 * This must not be NULL to satisfy Coverity SA
7984 assert(attr
.aspath
);
7987 case NEXTHOP_TYPE_IFINDEX
:
7989 case NEXTHOP_TYPE_IPV4
:
7990 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7991 attr
.nexthop
= nexthop
->ipv4
;
7993 case NEXTHOP_TYPE_IPV6
:
7994 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7995 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7996 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7998 case NEXTHOP_TYPE_BLACKHOLE
:
7999 switch (p
->family
) {
8001 attr
.nexthop
.s_addr
= INADDR_ANY
;
8004 memset(&attr
.mp_nexthop_global
, 0,
8005 sizeof(attr
.mp_nexthop_global
));
8006 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
8011 attr
.nh_ifindex
= ifindex
;
8014 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
8017 afi
= family2afi(p
->family
);
8019 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8021 struct attr attr_new
;
8023 /* Copy attribute for modification. */
8026 if (red
->redist_metric_flag
)
8027 attr_new
.med
= red
->redist_metric
;
8029 /* Apply route-map. */
8030 if (red
->rmap
.name
) {
8031 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
8032 rmap_path
.peer
= bgp
->peer_self
;
8033 rmap_path
.attr
= &attr_new
;
8035 SET_FLAG(bgp
->peer_self
->rmap_type
,
8036 PEER_RMAP_TYPE_REDISTRIBUTE
);
8038 ret
= route_map_apply(red
->rmap
.map
, p
, &rmap_path
);
8040 bgp
->peer_self
->rmap_type
= 0;
8042 if (ret
== RMAP_DENYMATCH
) {
8043 /* Free uninterned attribute. */
8044 bgp_attr_flush(&attr_new
);
8046 /* Unintern original. */
8047 aspath_unintern(&attr
.aspath
);
8048 bgp_redistribute_delete(bgp
, p
, type
, instance
);
8053 if (bgp_in_graceful_shutdown(bgp
))
8054 bgp_attr_add_gshut_community(&attr_new
);
8056 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8057 SAFI_UNICAST
, p
, NULL
);
8059 new_attr
= bgp_attr_intern(&attr_new
);
8061 for (bpi
= bgp_dest_get_bgp_path_info(bn
); bpi
; bpi
= bpi
->next
)
8062 if (bpi
->peer
== bgp
->peer_self
8063 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
8067 /* Ensure the (source route) type is updated. */
8069 if (attrhash_cmp(bpi
->attr
, new_attr
)
8070 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
8071 bgp_attr_unintern(&new_attr
);
8072 aspath_unintern(&attr
.aspath
);
8073 bgp_dest_unlock_node(bn
);
8076 /* The attribute is changed. */
8077 bgp_path_info_set_flag(bn
, bpi
,
8078 BGP_PATH_ATTR_CHANGED
);
8080 /* Rewrite BGP route information. */
8081 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
8082 bgp_path_info_restore(bn
, bpi
);
8084 bgp_aggregate_decrement(
8085 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
8086 bgp_attr_unintern(&bpi
->attr
);
8087 bpi
->attr
= new_attr
;
8088 bpi
->uptime
= bgp_clock();
8090 /* Process change. */
8091 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
8093 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8094 bgp_dest_unlock_node(bn
);
8095 aspath_unintern(&attr
.aspath
);
8097 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8099 == BGP_INSTANCE_TYPE_DEFAULT
)) {
8101 vpn_leak_from_vrf_update(
8102 bgp_get_default(), bgp
, bpi
);
8108 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
8109 bgp
->peer_self
, new_attr
, bn
);
8110 SET_FLAG(new->flags
, BGP_PATH_VALID
);
8112 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
8113 bgp_path_info_add(bn
, new);
8114 bgp_dest_unlock_node(bn
);
8115 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
8117 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8118 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8120 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
8124 /* Unintern original. */
8125 aspath_unintern(&attr
.aspath
);
8128 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
8129 unsigned short instance
)
8132 struct bgp_dest
*dest
;
8133 struct bgp_path_info
*pi
;
8134 struct bgp_redist
*red
;
8136 afi
= family2afi(p
->family
);
8138 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
8140 dest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
8141 SAFI_UNICAST
, p
, NULL
);
8143 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8144 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
8148 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8149 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8151 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8154 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
8155 bgp_path_info_delete(dest
, pi
);
8156 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8158 bgp_dest_unlock_node(dest
);
8162 /* Withdraw specified route type's route. */
8163 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
8164 unsigned short instance
)
8166 struct bgp_dest
*dest
;
8167 struct bgp_path_info
*pi
;
8168 struct bgp_table
*table
;
8170 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
8172 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
8173 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
)
8174 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
8175 && pi
->instance
== instance
)
8179 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
8180 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
8182 vpn_leak_from_vrf_withdraw(bgp_get_default(),
8185 bgp_aggregate_decrement(bgp
, bgp_dest_get_prefix(dest
),
8186 pi
, afi
, SAFI_UNICAST
);
8187 bgp_path_info_delete(dest
, pi
);
8188 bgp_process(bgp
, dest
, afi
, SAFI_UNICAST
);
8193 /* Static function to display route. */
8194 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
8195 json_object
*json
, bool wide
)
8201 if (p
->family
== AF_INET
) {
8203 len
= vty_out(vty
, "%pFX", p
);
8205 json_object_string_add(json
, "prefix",
8206 inet_ntop(p
->family
,
8209 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8210 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8211 json_object_string_add(json
, "network", buf2
);
8213 } else if (p
->family
== AF_ETHERNET
) {
8214 len
= vty_out(vty
, "%pFX", p
);
8215 } else if (p
->family
== AF_EVPN
) {
8217 len
= vty_out(vty
, "%pFX", (struct prefix_evpn
*)p
);
8219 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
8220 } else if (p
->family
== AF_FLOWSPEC
) {
8221 route_vty_out_flowspec(vty
, p
, NULL
,
8223 NLRI_STRING_FORMAT_JSON_SIMPLE
:
8224 NLRI_STRING_FORMAT_MIN
, json
);
8227 len
= vty_out(vty
, "%pFX", p
);
8229 json_object_string_add(json
, "prefix",
8230 inet_ntop(p
->family
,
8233 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
8234 prefix2str(p
, buf2
, PREFIX_STRLEN
);
8235 json_object_string_add(json
, "network", buf2
);
8240 len
= wide
? (45 - len
) : (17 - len
);
8242 vty_out(vty
, "\n%*s", 20, " ");
8244 vty_out(vty
, "%*s", len
, " ");
8248 enum bgp_display_type
{
8253 bgp_path_selection_reason2str(enum bgp_path_selection_reason reason
)
8256 case bgp_path_selection_none
:
8257 return "Nothing to Select";
8258 case bgp_path_selection_first
:
8259 return "First path received";
8260 case bgp_path_selection_evpn_sticky_mac
:
8261 return "EVPN Sticky Mac";
8262 case bgp_path_selection_evpn_seq
:
8263 return "EVPN sequence number";
8264 case bgp_path_selection_evpn_lower_ip
:
8265 return "EVPN lower IP";
8266 case bgp_path_selection_evpn_local_path
:
8267 return "EVPN local ES path";
8268 case bgp_path_selection_evpn_non_proxy
:
8269 return "EVPN non proxy";
8270 case bgp_path_selection_weight
:
8272 case bgp_path_selection_local_pref
:
8273 return "Local Pref";
8274 case bgp_path_selection_local_route
:
8275 return "Local Route";
8276 case bgp_path_selection_confed_as_path
:
8277 return "Confederation based AS Path";
8278 case bgp_path_selection_as_path
:
8280 case bgp_path_selection_origin
:
8282 case bgp_path_selection_med
:
8284 case bgp_path_selection_peer
:
8286 case bgp_path_selection_confed
:
8287 return "Confed Peer Type";
8288 case bgp_path_selection_igp_metric
:
8289 return "IGP Metric";
8290 case bgp_path_selection_older
:
8291 return "Older Path";
8292 case bgp_path_selection_router_id
:
8294 case bgp_path_selection_cluster_length
:
8295 return "Cluster length";
8296 case bgp_path_selection_stale
:
8297 return "Path Staleness";
8298 case bgp_path_selection_local_configured
:
8299 return "Locally configured route";
8300 case bgp_path_selection_neighbor_ip
:
8301 return "Neighbor IP";
8302 case bgp_path_selection_default
:
8303 return "Nothing left to compare";
8305 return "Invalid (internal error)";
8308 /* Print the short form route status for a bgp_path_info */
8309 static void route_vty_short_status_out(struct vty
*vty
,
8310 struct bgp_path_info
*path
,
8311 json_object
*json_path
)
8315 /* Route status display. */
8316 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8317 json_object_boolean_true_add(json_path
, "removed");
8319 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8320 json_object_boolean_true_add(json_path
, "stale");
8322 if (path
->extra
&& bgp_path_suppressed(path
))
8323 json_object_boolean_true_add(json_path
, "suppressed");
8325 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8326 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8327 json_object_boolean_true_add(json_path
, "valid");
8330 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8331 json_object_boolean_true_add(json_path
, "history");
8333 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8334 json_object_boolean_true_add(json_path
, "damped");
8336 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8337 json_object_boolean_true_add(json_path
, "bestpath");
8338 json_object_string_add(json_path
, "selectionReason",
8339 bgp_path_selection_reason2str(
8340 path
->net
->reason
));
8343 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8344 json_object_boolean_true_add(json_path
, "multipath");
8346 /* Internal route. */
8347 if ((path
->peer
->as
)
8348 && (path
->peer
->as
== path
->peer
->local_as
))
8349 json_object_string_add(json_path
, "pathFrom",
8352 json_object_string_add(json_path
, "pathFrom",
8358 /* Route status display. */
8359 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
8361 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
8363 else if (bgp_path_suppressed(path
))
8365 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
8366 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8372 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
8374 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
8376 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
8378 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
8383 /* Internal route. */
8384 if (path
->peer
&& (path
->peer
->as
)
8385 && (path
->peer
->as
== path
->peer
->local_as
))
8391 static char *bgp_nexthop_hostname(struct peer
*peer
,
8392 struct bgp_nexthop_cache
*bnc
)
8395 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME
))
8396 return peer
->hostname
;
8400 /* called from terminal list command */
8401 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8402 struct bgp_path_info
*path
, int display
, safi_t safi
,
8403 json_object
*json_paths
, bool wide
)
8406 struct attr
*attr
= path
->attr
;
8407 json_object
*json_path
= NULL
;
8408 json_object
*json_nexthops
= NULL
;
8409 json_object
*json_nexthop_global
= NULL
;
8410 json_object
*json_nexthop_ll
= NULL
;
8411 json_object
*json_ext_community
= NULL
;
8412 char vrf_id_str
[VRF_NAMSIZ
] = {0};
8414 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8415 bool nexthop_othervrf
= false;
8416 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
8417 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
8418 char *nexthop_hostname
=
8419 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
8420 char esi_buf
[ESI_STR_LEN
];
8423 json_path
= json_object_new_object();
8425 /* short status lead text */
8426 route_vty_short_status_out(vty
, path
, json_path
);
8429 /* print prefix and mask */
8431 route_vty_out_route(p
, vty
, json_path
, wide
);
8433 vty_out(vty
, "%*s", (wide
? 45 : 17), " ");
8435 route_vty_out_route(p
, vty
, json_path
, wide
);
8439 * If vrf id of nexthop is different from that of prefix,
8440 * set up printable string to append
8442 if (path
->extra
&& path
->extra
->bgp_orig
) {
8443 const char *self
= "";
8448 nexthop_othervrf
= true;
8449 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8451 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
8452 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
8453 "@%s%s", VRFID_NONE_STR
, self
);
8455 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
8456 path
->extra
->bgp_orig
->vrf_id
, self
);
8458 if (path
->extra
->bgp_orig
->inst_type
8459 != BGP_INSTANCE_TYPE_DEFAULT
)
8461 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
8463 const char *self
= "";
8468 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
8472 * For ENCAP and EVPN routes, nexthop address family is not
8473 * neccessarily the same as the prefix address family.
8474 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8475 * EVPN routes are also exchanged with a MP nexthop. Currently,
8477 * is only IPv4, the value will be present in either
8479 * attr->mp_nexthop_global_in
8481 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
8484 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8488 snprintf(nexthop
, sizeof(nexthop
), "%s",
8489 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
8493 snprintf(nexthop
, sizeof(nexthop
), "%s",
8494 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
8498 snprintf(nexthop
, sizeof(nexthop
), "?");
8503 json_nexthop_global
= json_object_new_object();
8505 json_object_string_add(json_nexthop_global
, "ip",
8508 if (path
->peer
->hostname
)
8509 json_object_string_add(json_nexthop_global
,
8511 path
->peer
->hostname
);
8513 json_object_string_add(json_nexthop_global
, "afi",
8514 (af
== AF_INET
) ? "ipv4"
8516 json_object_boolean_true_add(json_nexthop_global
,
8519 if (nexthop_hostname
)
8520 len
= vty_out(vty
, "%s(%s)%s", nexthop
,
8521 nexthop_hostname
, vrf_id_str
);
8523 len
= vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
8525 len
= wide
? (41 - len
) : (16 - len
);
8527 vty_out(vty
, "\n%*s", 36, " ");
8529 vty_out(vty
, "%*s", len
, " ");
8531 } else if (safi
== SAFI_EVPN
) {
8533 char buf
[BUFSIZ
] = {0};
8535 json_nexthop_global
= json_object_new_object();
8537 json_object_string_add(json_nexthop_global
, "ip",
8539 &attr
->nexthop
, buf
,
8542 if (path
->peer
->hostname
)
8543 json_object_string_add(json_nexthop_global
,
8545 path
->peer
->hostname
);
8547 json_object_string_add(json_nexthop_global
, "afi",
8549 json_object_boolean_true_add(json_nexthop_global
,
8552 if (nexthop_hostname
)
8553 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8554 nexthop_hostname
, vrf_id_str
);
8556 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8559 len
= wide
? (41 - len
) : (16 - len
);
8561 vty_out(vty
, "\n%*s", 36, " ");
8563 vty_out(vty
, "%*s", len
, " ");
8565 } else if (safi
== SAFI_FLOWSPEC
) {
8566 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
8568 char buf
[BUFSIZ
] = {0};
8570 json_nexthop_global
= json_object_new_object();
8572 json_object_string_add(json_nexthop_global
,
8574 json_object_string_add(
8575 json_nexthop_global
, "ip",
8576 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
8579 if (path
->peer
->hostname
)
8580 json_object_string_add(
8581 json_nexthop_global
, "hostname",
8582 path
->peer
->hostname
);
8584 json_object_boolean_true_add(
8585 json_nexthop_global
,
8588 if (nexthop_hostname
)
8589 len
= vty_out(vty
, "%pI4(%s)%s",
8594 len
= vty_out(vty
, "%pI4%s",
8598 len
= wide
? (41 - len
) : (16 - len
);
8600 vty_out(vty
, "\n%*s", 36, " ");
8602 vty_out(vty
, "%*s", len
, " ");
8605 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8607 char buf
[BUFSIZ
] = {0};
8609 json_nexthop_global
= json_object_new_object();
8611 json_object_string_add(json_nexthop_global
, "ip",
8613 &attr
->nexthop
, buf
,
8616 if (path
->peer
->hostname
)
8617 json_object_string_add(json_nexthop_global
,
8619 path
->peer
->hostname
);
8621 json_object_string_add(json_nexthop_global
, "afi",
8623 json_object_boolean_true_add(json_nexthop_global
,
8626 if (nexthop_hostname
)
8627 len
= vty_out(vty
, "%pI4(%s)%s", &attr
->nexthop
,
8628 nexthop_hostname
, vrf_id_str
);
8630 len
= vty_out(vty
, "%pI4%s", &attr
->nexthop
,
8633 len
= wide
? (41 - len
) : (16 - len
);
8635 vty_out(vty
, "\n%*s", 36, " ");
8637 vty_out(vty
, "%*s", len
, " ");
8642 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8646 json_nexthop_global
= json_object_new_object();
8647 json_object_string_add(
8648 json_nexthop_global
, "ip",
8649 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8652 if (path
->peer
->hostname
)
8653 json_object_string_add(json_nexthop_global
,
8655 path
->peer
->hostname
);
8657 json_object_string_add(json_nexthop_global
, "afi",
8659 json_object_string_add(json_nexthop_global
, "scope",
8662 /* We display both LL & GL if both have been
8664 if ((attr
->mp_nexthop_len
8665 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8666 || (path
->peer
->conf_if
)) {
8667 json_nexthop_ll
= json_object_new_object();
8668 json_object_string_add(
8669 json_nexthop_ll
, "ip",
8671 &attr
->mp_nexthop_local
, buf
,
8674 if (path
->peer
->hostname
)
8675 json_object_string_add(
8676 json_nexthop_ll
, "hostname",
8677 path
->peer
->hostname
);
8679 json_object_string_add(json_nexthop_ll
, "afi",
8681 json_object_string_add(json_nexthop_ll
, "scope",
8684 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
8685 &attr
->mp_nexthop_local
)
8687 && !attr
->mp_nexthop_prefer_global
)
8688 json_object_boolean_true_add(
8689 json_nexthop_ll
, "used");
8691 json_object_boolean_true_add(
8692 json_nexthop_global
, "used");
8694 json_object_boolean_true_add(
8695 json_nexthop_global
, "used");
8697 /* Display LL if LL/Global both in table unless
8698 * prefer-global is set */
8699 if (((attr
->mp_nexthop_len
8700 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
8701 && !attr
->mp_nexthop_prefer_global
)
8702 || (path
->peer
->conf_if
)) {
8703 if (path
->peer
->conf_if
) {
8704 len
= vty_out(vty
, "%s",
8705 path
->peer
->conf_if
);
8706 /* len of IPv6 addr + max len of def
8708 len
= wide
? (41 - len
) : (16 - len
);
8711 vty_out(vty
, "\n%*s", 36, " ");
8713 vty_out(vty
, "%*s", len
, " ");
8715 if (nexthop_hostname
)
8718 &attr
->mp_nexthop_local
,
8724 &attr
->mp_nexthop_local
,
8727 len
= wide
? (41 - len
) : (16 - len
);
8730 vty_out(vty
, "\n%*s", 36, " ");
8732 vty_out(vty
, "%*s", len
, " ");
8735 if (nexthop_hostname
)
8736 len
= vty_out(vty
, "%pI6(%s)%s",
8737 &attr
->mp_nexthop_global
,
8741 len
= vty_out(vty
, "%pI6%s",
8742 &attr
->mp_nexthop_global
,
8745 len
= wide
? (41 - len
) : (16 - len
);
8748 vty_out(vty
, "\n%*s", 36, " ");
8750 vty_out(vty
, "%*s", len
, " ");
8756 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8758 json_object_int_add(json_path
, "metric", attr
->med
);
8760 vty_out(vty
, "%7u", attr
->med
);
8762 vty_out(vty
, "%10u", attr
->med
);
8763 else if (!json_paths
) {
8765 vty_out(vty
, "%*s", 7, " ");
8767 vty_out(vty
, "%*s", 10, " ");
8771 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8773 json_object_int_add(json_path
, "locPrf",
8776 vty_out(vty
, "%7u", attr
->local_pref
);
8777 else if (!json_paths
)
8781 json_object_int_add(json_path
, "weight", attr
->weight
);
8783 vty_out(vty
, "%7u ", attr
->weight
);
8787 json_object_string_add(
8788 json_path
, "peerId",
8789 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
8795 json_object_string_add(json_path
, "path",
8798 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8803 json_object_string_add(json_path
, "origin",
8804 bgp_origin_long_str
[attr
->origin
]);
8806 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8809 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8810 json_object_string_add(json_path
, "esi",
8811 esi_to_str(&attr
->esi
,
8812 esi_buf
, sizeof(esi_buf
)));
8814 if (safi
== SAFI_EVPN
&&
8815 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8816 json_ext_community
= json_object_new_object();
8817 json_object_string_add(json_ext_community
,
8819 attr
->ecommunity
->str
);
8820 json_object_object_add(json_path
,
8821 "extendedCommunity",
8822 json_ext_community
);
8826 json_object_boolean_true_add(json_path
,
8827 "announceNexthopSelf");
8828 if (nexthop_othervrf
) {
8829 json_object_string_add(json_path
, "nhVrfName",
8832 json_object_int_add(json_path
, "nhVrfId",
8833 ((nexthop_vrfid
== VRF_UNKNOWN
)
8835 : (int)nexthop_vrfid
));
8840 if (json_nexthop_global
|| json_nexthop_ll
) {
8841 json_nexthops
= json_object_new_array();
8843 if (json_nexthop_global
)
8844 json_object_array_add(json_nexthops
,
8845 json_nexthop_global
);
8847 if (json_nexthop_ll
)
8848 json_object_array_add(json_nexthops
,
8851 json_object_object_add(json_path
, "nexthops",
8855 json_object_array_add(json_paths
, json_path
);
8859 if (safi
== SAFI_EVPN
) {
8860 struct bgp_path_es_info
*path_es_info
= NULL
;
8862 if (bgp_evpn_is_esi_valid(&attr
->esi
)) {
8863 /* XXX - add these params to the json out */
8864 vty_out(vty
, "%*s", 20, " ");
8865 vty_out(vty
, "ESI:%s",
8866 esi_to_str(&attr
->esi
, esi_buf
,
8869 if (path
->extra
&& path
->extra
->mh_info
)
8871 path
->extra
->mh_info
->es_info
;
8873 if (path_es_info
&& path_es_info
->es
)
8874 vty_out(vty
, " VNI: %u",
8879 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8880 vty_out(vty
, "%*s", 20, " ");
8881 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
8885 #ifdef ENABLE_BGP_VNC
8886 /* prints an additional line, indented, with VNC info, if
8888 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
8889 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
8894 /* called from terminal list command */
8895 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
8896 struct attr
*attr
, safi_t safi
, bool use_json
,
8897 json_object
*json_ar
, bool wide
)
8899 json_object
*json_status
= NULL
;
8900 json_object
*json_net
= NULL
;
8904 /* Route status display. */
8906 json_status
= json_object_new_object();
8907 json_net
= json_object_new_object();
8914 /* print prefix and mask */
8916 if (safi
== SAFI_EVPN
)
8917 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
8918 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
8919 json_object_string_add(
8920 json_net
, "addrPrefix",
8921 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
8923 json_object_int_add(json_net
, "prefixLen",
8925 prefix2str(p
, buff
, PREFIX_STRLEN
);
8926 json_object_string_add(json_net
, "network", buff
);
8929 route_vty_out_route(p
, vty
, NULL
, wide
);
8931 /* Print attribute */
8934 char buf
[BUFSIZ
] = {0};
8936 if (p
->family
== AF_INET
8937 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8938 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8939 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8940 json_object_string_add(
8941 json_net
, "nextHop",
8944 &attr
->mp_nexthop_global_in
,
8947 json_object_string_add(
8948 json_net
, "nextHop",
8950 &attr
->nexthop
, buf
,
8952 } else if (p
->family
== AF_INET6
8953 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8956 json_object_string_add(
8957 json_net
, "nextHopGlobal",
8959 &attr
->mp_nexthop_global
, buf
,
8961 } else if (p
->family
== AF_EVPN
8962 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8963 char buf
[BUFSIZ
] = {0};
8965 json_object_string_add(
8966 json_net
, "nextHop",
8968 &attr
->mp_nexthop_global_in
,
8973 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8974 json_object_int_add(json_net
, "metric",
8977 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8978 json_object_int_add(json_net
, "locPrf",
8981 json_object_int_add(json_net
, "weight", attr
->weight
);
8985 json_object_string_add(json_net
, "path",
8989 json_object_string_add(json_net
, "bgpOriginCode",
8990 bgp_origin_str
[attr
->origin
]);
8992 if (p
->family
== AF_INET
8993 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8994 || safi
== SAFI_EVPN
8995 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8996 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8997 || safi
== SAFI_EVPN
)
8998 vty_out(vty
, "%-16pI4",
8999 &attr
->mp_nexthop_global_in
);
9001 vty_out(vty
, "%-41pI4", &attr
->nexthop
);
9003 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9004 } else if (p
->family
== AF_INET6
9005 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
9011 &attr
->mp_nexthop_global
, buf
,
9013 len
= wide
? (41 - len
) : (16 - len
);
9015 vty_out(vty
, "\n%*s", 36, " ");
9017 vty_out(vty
, "%*s", len
, " ");
9020 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
9022 vty_out(vty
, "%7u", attr
->med
);
9024 vty_out(vty
, "%10u", attr
->med
);
9030 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
9031 vty_out(vty
, "%7u", attr
->local_pref
);
9035 vty_out(vty
, "%7u ", attr
->weight
);
9039 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9042 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9046 json_object_boolean_true_add(json_status
, "*");
9047 json_object_boolean_true_add(json_status
, ">");
9048 json_object_object_add(json_net
, "appliedStatusSymbols",
9051 prefix2str(p
, buff
, PREFIX_STRLEN
);
9052 json_object_object_add(json_ar
, buff
, json_net
);
9057 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
9058 struct bgp_path_info
*path
, int display
, safi_t safi
,
9061 json_object
*json_out
= NULL
;
9063 mpls_label_t label
= MPLS_INVALID_LABEL
;
9069 json_out
= json_object_new_object();
9071 /* short status lead text */
9072 route_vty_short_status_out(vty
, path
, json_out
);
9074 /* print prefix and mask */
9077 route_vty_out_route(p
, vty
, NULL
, false);
9079 vty_out(vty
, "%*s", 17, " ");
9082 /* Print attribute */
9084 if (((p
->family
== AF_INET
)
9085 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9086 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9087 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9088 char buf
[BUFSIZ
] = {0};
9090 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9091 || safi
== SAFI_EVPN
) {
9093 json_object_string_add(
9094 json_out
, "mpNexthopGlobalIn",
9096 &attr
->mp_nexthop_global_in
,
9099 vty_out(vty
, "%-16pI4",
9100 &attr
->mp_nexthop_global_in
);
9103 json_object_string_add(
9104 json_out
, "nexthop",
9105 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9108 vty_out(vty
, "%-16pI4", &attr
->nexthop
);
9110 } else if (((p
->family
== AF_INET6
)
9111 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
9112 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
9113 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9116 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
9118 json_object_string_add(
9119 json_out
, "mpNexthopGlobalIn",
9121 &attr
->mp_nexthop_global
,
9122 buf_a
, sizeof(buf_a
)));
9126 &attr
->mp_nexthop_global
,
9127 buf_a
, sizeof(buf_a
)));
9128 } else if (attr
->mp_nexthop_len
9129 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9130 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
9131 &attr
->mp_nexthop_global
,
9132 &attr
->mp_nexthop_local
);
9134 json_object_string_add(json_out
,
9135 "mpNexthopGlobalLocal",
9138 vty_out(vty
, "%s", buf_a
);
9142 label
= decode_label(&path
->extra
->label
[0]);
9144 if (bgp_is_valid_label(&label
)) {
9146 json_object_int_add(json_out
, "notag", label
);
9147 json_object_array_add(json
, json_out
);
9149 vty_out(vty
, "notag/%d", label
);
9155 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
9156 struct bgp_path_info
*path
, int display
,
9157 json_object
*json_paths
)
9160 char buf
[BUFSIZ
] = {0};
9161 json_object
*json_path
= NULL
;
9162 json_object
*json_nexthop
= NULL
;
9163 json_object
*json_overlay
= NULL
;
9169 json_path
= json_object_new_object();
9170 json_overlay
= json_object_new_object();
9171 json_nexthop
= json_object_new_object();
9174 /* short status lead text */
9175 route_vty_short_status_out(vty
, path
, json_path
);
9177 /* print prefix and mask */
9179 route_vty_out_route(p
, vty
, json_path
, false);
9181 vty_out(vty
, "%*s", 17, " ");
9183 /* Print attribute */
9186 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
9190 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
9192 vty_out(vty
, "%-16s", buf
);
9194 json_object_string_add(json_nexthop
, "ip", buf
);
9196 json_object_string_add(json_nexthop
, "afi", "ipv4");
9198 json_object_object_add(json_path
, "nexthop",
9203 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
9204 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
9206 vty_out(vty
, "%s(%s)", buf
, buf1
);
9208 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
9210 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
9213 json_object_string_add(json_nexthop
, "afi", "ipv6");
9215 json_object_object_add(json_path
, "nexthop",
9223 json_object_string_add(json_nexthop
, "Error",
9224 "Unsupported address-family");
9228 const struct bgp_route_evpn
*eo
= bgp_attr_get_evpn_overlay(attr
);
9230 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
))
9231 inet_ntop(AF_INET
, &eo
->gw_ip
.ipv4
, buf
, BUFSIZ
);
9232 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
))
9233 inet_ntop(AF_INET6
, &eo
->gw_ip
.ipv6
, buf
, BUFSIZ
);
9236 vty_out(vty
, "/%s", buf
);
9238 json_object_string_add(json_overlay
, "gw", buf
);
9240 if (attr
->ecommunity
) {
9242 struct ecommunity_val
*routermac
= ecommunity_lookup(
9243 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
9244 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
9247 mac
= ecom_mac2str((char *)routermac
->val
);
9250 vty_out(vty
, "/%s", mac
);
9252 json_object_string_add(json_overlay
, "rmac",
9255 XFREE(MTYPE_TMP
, mac
);
9262 json_object_object_add(json_path
, "overlay", json_overlay
);
9264 json_object_array_add(json_paths
, json_path
);
9268 /* dampening route */
9269 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9270 struct bgp_path_info
*path
, int display
,
9271 afi_t afi
, safi_t safi
, bool use_json
,
9276 char timebuf
[BGP_UPTIME_LEN
];
9278 /* short status lead text */
9279 route_vty_short_status_out(vty
, path
, json
);
9281 /* print prefix and mask */
9284 route_vty_out_route(p
, vty
, NULL
, false);
9286 vty_out(vty
, "%*s", 17, " ");
9289 len
= vty_out(vty
, "%s", path
->peer
->host
);
9293 vty_out(vty
, "\n%*s", 34, " ");
9296 json_object_int_add(json
, "peerHost", len
);
9298 vty_out(vty
, "%*s", len
, " ");
9302 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
9303 safi
, use_json
, json
);
9306 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9307 BGP_UPTIME_LEN
, afi
, safi
,
9310 /* Print attribute */
9316 json_object_string_add(json
, "asPath",
9319 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9324 json_object_string_add(json
, "origin",
9325 bgp_origin_str
[attr
->origin
]);
9327 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9334 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
9335 struct bgp_path_info
*path
, int display
,
9336 afi_t afi
, safi_t safi
, bool use_json
,
9340 struct bgp_damp_info
*bdi
;
9341 char timebuf
[BGP_UPTIME_LEN
];
9347 bdi
= path
->extra
->damp_info
;
9349 /* short status lead text */
9350 route_vty_short_status_out(vty
, path
, json
);
9352 /* print prefix and mask */
9355 route_vty_out_route(p
, vty
, NULL
, false);
9357 vty_out(vty
, "%*s", 17, " ");
9360 len
= vty_out(vty
, "%s", path
->peer
->host
);
9364 vty_out(vty
, "\n%*s", 33, " ");
9367 json_object_int_add(json
, "peerHost", len
);
9369 vty_out(vty
, "%*s", len
, " ");
9372 len
= vty_out(vty
, "%d", bdi
->flap
);
9379 json_object_int_add(json
, "bdiFlap", len
);
9381 vty_out(vty
, "%*s", len
, " ");
9385 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
9388 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
9389 BGP_UPTIME_LEN
, 0, NULL
));
9391 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
9392 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9394 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9395 BGP_UPTIME_LEN
, afi
, safi
,
9399 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
9400 BGP_UPTIME_LEN
, afi
,
9401 safi
, use_json
, json
));
9404 vty_out(vty
, "%*s ", 8, " ");
9407 /* Print attribute */
9413 json_object_string_add(json
, "asPath",
9416 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
9421 json_object_string_add(json
, "origin",
9422 bgp_origin_str
[attr
->origin
]);
9424 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
9430 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
9431 int *first
, const char *header
,
9432 json_object
*json_adv_to
)
9434 char buf1
[INET6_ADDRSTRLEN
];
9435 json_object
*json_peer
= NULL
;
9438 /* 'advertised-to' is a dictionary of peers we have advertised
9440 * prefix too. The key is the peer's IP or swpX, the value is
9442 * hostname if we know it and "" if not.
9444 json_peer
= json_object_new_object();
9447 json_object_string_add(json_peer
, "hostname",
9451 json_object_object_add(json_adv_to
, peer
->conf_if
,
9454 json_object_object_add(
9456 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
9460 vty_out(vty
, "%s", header
);
9465 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
9467 vty_out(vty
, " %s(%s)", peer
->hostname
,
9470 vty_out(vty
, " %s(%s)", peer
->hostname
,
9471 sockunion2str(&peer
->su
, buf1
,
9475 vty_out(vty
, " %s", peer
->conf_if
);
9478 sockunion2str(&peer
->su
, buf1
,
9484 static void route_vty_out_tx_ids(struct vty
*vty
,
9485 struct bgp_addpath_info_data
*d
)
9489 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9490 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
9491 d
->addpath_tx_id
[i
],
9492 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
9496 static void route_vty_out_detail_es_info(struct vty
*vty
,
9497 struct bgp_path_info
*pi
,
9499 json_object
*json_path
)
9501 char esi_buf
[ESI_STR_LEN
];
9502 bool es_local
= !!CHECK_FLAG(attr
->es_flags
, ATTR_ES_IS_LOCAL
);
9503 bool peer_router
= !!CHECK_FLAG(attr
->es_flags
,
9504 ATTR_ES_PEER_ROUTER
);
9505 bool peer_active
= !!CHECK_FLAG(attr
->es_flags
,
9506 ATTR_ES_PEER_ACTIVE
);
9507 bool peer_proxy
= !!CHECK_FLAG(attr
->es_flags
,
9508 ATTR_ES_PEER_PROXY
);
9509 esi_to_str(&attr
->esi
, esi_buf
, sizeof(esi_buf
));
9511 json_object
*json_es_info
= NULL
;
9513 json_object_string_add(
9516 if (es_local
|| bgp_evpn_attr_is_sync(attr
)) {
9517 json_es_info
= json_object_new_object();
9519 json_object_boolean_true_add(
9520 json_es_info
, "localEs");
9522 json_object_boolean_true_add(
9523 json_es_info
, "peerActive");
9525 json_object_boolean_true_add(
9526 json_es_info
, "peerProxy");
9528 json_object_boolean_true_add(
9529 json_es_info
, "peerRouter");
9530 if (attr
->mm_sync_seqnum
)
9531 json_object_int_add(
9532 json_es_info
, "peerSeq",
9533 attr
->mm_sync_seqnum
);
9534 json_object_object_add(
9535 json_path
, "es_info",
9539 if (bgp_evpn_attr_is_sync(attr
))
9541 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9543 es_local
? "local-es":"",
9544 peer_proxy
? "proxy " : "",
9545 peer_active
? "active ":"",
9546 peer_router
? "router ":"",
9547 attr
->mm_sync_seqnum
);
9549 vty_out(vty
, " ESI %s %s\n",
9551 es_local
? "local-es":"");
9555 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct bgp_dest
*bn
,
9556 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
9557 enum rpki_states curr_state
, json_object
*json_paths
)
9559 char buf
[INET6_ADDRSTRLEN
];
9561 struct attr
*attr
= path
->attr
;
9562 int sockunion_vty_out(struct vty
*, union sockunion
*);
9564 json_object
*json_bestpath
= NULL
;
9565 json_object
*json_cluster_list
= NULL
;
9566 json_object
*json_cluster_list_list
= NULL
;
9567 json_object
*json_ext_community
= NULL
;
9568 json_object
*json_last_update
= NULL
;
9569 json_object
*json_pmsi
= NULL
;
9570 json_object
*json_nexthop_global
= NULL
;
9571 json_object
*json_nexthop_ll
= NULL
;
9572 json_object
*json_nexthops
= NULL
;
9573 json_object
*json_path
= NULL
;
9574 json_object
*json_peer
= NULL
;
9575 json_object
*json_string
= NULL
;
9576 json_object
*json_adv_to
= NULL
;
9578 struct listnode
*node
, *nnode
;
9580 int addpath_capable
;
9582 unsigned int first_as
;
9584 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
9586 char *nexthop_hostname
=
9587 bgp_nexthop_hostname(path
->peer
, path
->nexthop
);
9590 json_path
= json_object_new_object();
9591 json_peer
= json_object_new_object();
9592 json_nexthop_global
= json_object_new_object();
9599 if (path
->extra
&& path
->extra
->num_labels
) {
9600 bgp_evpn_label2str(path
->extra
->label
,
9601 path
->extra
->num_labels
, tag_buf
,
9604 if (safi
== SAFI_EVPN
) {
9606 vty_out(vty
, " Route %pFX",
9607 (struct prefix_evpn
*)
9608 bgp_dest_get_prefix(bn
));
9609 if (tag_buf
[0] != '\0')
9610 vty_out(vty
, " VNI %s", tag_buf
);
9614 json_object_string_add(json_path
, "VNI",
9619 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
9620 struct bgp_path_info
*parent_ri
;
9621 struct bgp_dest
*dest
, *pdest
;
9623 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
9624 dest
= parent_ri
->net
;
9625 if (dest
&& dest
->pdest
) {
9626 pdest
= dest
->pdest
;
9628 (struct prefix_rd
*)bgp_dest_get_prefix(
9630 buf1
, sizeof(buf1
));
9631 if (is_pi_family_evpn(parent_ri
)) {
9633 " Imported from %s:%pFX, VNI %s",
9635 (struct prefix_evpn
*)
9636 bgp_dest_get_prefix(
9639 if (attr
->es_flags
& ATTR_ES_L3_NHG
)
9640 vty_out(vty
, ", L3NHG %s",
9642 & ATTR_ES_L3_NHG_ACTIVE
)
9649 " Imported from %s:%pFX\n",
9651 (struct prefix_evpn
*)
9652 bgp_dest_get_prefix(
9658 /* Line1 display AS-path, Aggregator */
9661 if (!attr
->aspath
->json
)
9662 aspath_str_update(attr
->aspath
, true);
9663 json_object_lock(attr
->aspath
->json
);
9664 json_object_object_add(json_path
, "aspath",
9665 attr
->aspath
->json
);
9667 if (attr
->aspath
->segments
)
9668 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
9670 vty_out(vty
, " Local");
9674 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
9676 json_object_boolean_true_add(json_path
, "removed");
9678 vty_out(vty
, ", (removed)");
9681 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
9683 json_object_boolean_true_add(json_path
, "stale");
9685 vty_out(vty
, ", (stale)");
9688 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
9690 char buf
[BUFSIZ
] = {0};
9692 json_object_int_add(json_path
, "aggregatorAs",
9693 attr
->aggregator_as
);
9694 json_object_string_add(json_path
, "aggregatorId",
9696 &attr
->aggregator_addr
,
9699 vty_out(vty
, ", (aggregated by %u %pI4)",
9700 attr
->aggregator_as
, &attr
->aggregator_addr
);
9704 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9705 PEER_FLAG_REFLECTOR_CLIENT
)) {
9707 json_object_boolean_true_add(json_path
,
9708 "rxedFromRrClient");
9710 vty_out(vty
, ", (Received from a RR-client)");
9713 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
9714 PEER_FLAG_RSERVER_CLIENT
)) {
9716 json_object_boolean_true_add(json_path
,
9717 "rxedFromRsClient");
9719 vty_out(vty
, ", (Received from a RS-client)");
9722 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9724 json_object_boolean_true_add(json_path
,
9725 "dampeningHistoryEntry");
9727 vty_out(vty
, ", (history entry)");
9728 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
9730 json_object_boolean_true_add(json_path
,
9731 "dampeningSuppressed");
9733 vty_out(vty
, ", (suppressed due to dampening)");
9739 /* Line2 display Next-hop, Neighbor, Router-id */
9740 /* Display the nexthop */
9741 const struct prefix
*bn_p
= bgp_dest_get_prefix(bn
);
9743 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
9744 || bn_p
->family
== AF_EVPN
)
9745 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
9746 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9747 char buf
[BUFSIZ
] = {0};
9749 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
9750 || safi
== SAFI_EVPN
) {
9752 json_object_string_add(
9753 json_nexthop_global
, "ip",
9755 &attr
->mp_nexthop_global_in
,
9758 if (path
->peer
->hostname
)
9759 json_object_string_add(
9760 json_nexthop_global
, "hostname",
9761 path
->peer
->hostname
);
9763 if (nexthop_hostname
)
9764 vty_out(vty
, " %pI4(%s)",
9765 &attr
->mp_nexthop_global_in
,
9768 vty_out(vty
, " %pI4",
9769 &attr
->mp_nexthop_global_in
);
9773 json_object_string_add(
9774 json_nexthop_global
, "ip",
9775 inet_ntop(AF_INET
, &attr
->nexthop
, buf
,
9778 if (path
->peer
->hostname
)
9779 json_object_string_add(
9780 json_nexthop_global
, "hostname",
9781 path
->peer
->hostname
);
9783 if (nexthop_hostname
)
9784 vty_out(vty
, " %pI4(%s)",
9788 vty_out(vty
, " %pI4",
9794 json_object_string_add(json_nexthop_global
, "afi",
9798 json_object_string_add(
9799 json_nexthop_global
, "ip",
9800 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
9801 buf
, INET6_ADDRSTRLEN
));
9803 if (path
->peer
->hostname
)
9804 json_object_string_add(json_nexthop_global
,
9806 path
->peer
->hostname
);
9808 json_object_string_add(json_nexthop_global
, "afi",
9810 json_object_string_add(json_nexthop_global
, "scope",
9813 if (nexthop_hostname
)
9814 vty_out(vty
, " %pI6(%s)",
9815 &attr
->mp_nexthop_global
,
9818 vty_out(vty
, " %pI6",
9819 &attr
->mp_nexthop_global
);
9823 /* Display the IGP cost or 'inaccessible' */
9824 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9826 json_object_boolean_false_add(json_nexthop_global
,
9829 vty_out(vty
, " (inaccessible)");
9831 if (path
->extra
&& path
->extra
->igpmetric
) {
9833 json_object_int_add(json_nexthop_global
,
9835 path
->extra
->igpmetric
);
9837 vty_out(vty
, " (metric %u)",
9838 path
->extra
->igpmetric
);
9841 /* IGP cost is 0, display this only for json */
9844 json_object_int_add(json_nexthop_global
,
9849 json_object_boolean_true_add(json_nexthop_global
,
9853 /* Display peer "from" output */
9854 /* This path was originated locally */
9855 if (path
->peer
== bgp
->peer_self
) {
9857 if (safi
== SAFI_EVPN
9858 || (bn_p
->family
== AF_INET
9859 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
9861 json_object_string_add(json_peer
, "peerId",
9864 vty_out(vty
, " from 0.0.0.0 ");
9867 json_object_string_add(json_peer
, "peerId",
9870 vty_out(vty
, " from :: ");
9874 char buf
[BUFSIZ
] = {0};
9876 json_object_string_add(json_peer
, "routerId",
9878 &bgp
->router_id
, buf
,
9881 vty_out(vty
, "(%pI4)", &bgp
->router_id
);
9885 /* We RXed this path from one of our peers */
9889 json_object_string_add(json_peer
, "peerId",
9890 sockunion2str(&path
->peer
->su
,
9893 json_object_string_add(json_peer
, "routerId",
9895 &path
->peer
->remote_id
,
9896 buf1
, sizeof(buf1
)));
9898 if (path
->peer
->hostname
)
9899 json_object_string_add(json_peer
, "hostname",
9900 path
->peer
->hostname
);
9902 if (path
->peer
->domainname
)
9903 json_object_string_add(json_peer
, "domainname",
9904 path
->peer
->domainname
);
9906 if (path
->peer
->conf_if
)
9907 json_object_string_add(json_peer
, "interface",
9908 path
->peer
->conf_if
);
9910 if (path
->peer
->conf_if
) {
9911 if (path
->peer
->hostname
9912 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9913 BGP_FLAG_SHOW_HOSTNAME
))
9914 vty_out(vty
, " from %s(%s)",
9915 path
->peer
->hostname
,
9916 path
->peer
->conf_if
);
9918 vty_out(vty
, " from %s",
9919 path
->peer
->conf_if
);
9921 if (path
->peer
->hostname
9922 && CHECK_FLAG(path
->peer
->bgp
->flags
,
9923 BGP_FLAG_SHOW_HOSTNAME
))
9924 vty_out(vty
, " from %s(%s)",
9925 path
->peer
->hostname
,
9928 vty_out(vty
, " from %s",
9929 sockunion2str(&path
->peer
->su
,
9934 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9935 vty_out(vty
, " (%pI4)", &attr
->originator_id
);
9937 vty_out(vty
, " (%s)",
9939 &path
->peer
->remote_id
, buf1
,
9945 * Note when vrfid of nexthop is different from that of prefix
9947 if (path
->extra
&& path
->extra
->bgp_orig
) {
9948 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
9953 if (path
->extra
->bgp_orig
->inst_type
9954 == BGP_INSTANCE_TYPE_DEFAULT
)
9955 vn
= VRF_DEFAULT_NAME
;
9957 vn
= path
->extra
->bgp_orig
->name
;
9959 json_object_string_add(json_path
, "nhVrfName", vn
);
9961 if (nexthop_vrfid
== VRF_UNKNOWN
) {
9962 json_object_int_add(json_path
, "nhVrfId", -1);
9964 json_object_int_add(json_path
, "nhVrfId",
9965 (int)nexthop_vrfid
);
9968 if (nexthop_vrfid
== VRF_UNKNOWN
)
9969 vty_out(vty
, " vrf ?");
9973 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9974 vty_out(vty
, " vrf %s(%u)",
9975 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9982 json_object_boolean_true_add(json_path
,
9983 "announceNexthopSelf");
9985 vty_out(vty
, " announce-nh-self");
9992 /* display the link-local nexthop */
9993 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9995 json_nexthop_ll
= json_object_new_object();
9996 json_object_string_add(
9997 json_nexthop_ll
, "ip",
9998 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9999 buf
, INET6_ADDRSTRLEN
));
10001 if (path
->peer
->hostname
)
10002 json_object_string_add(json_nexthop_ll
,
10004 path
->peer
->hostname
);
10006 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
10007 json_object_string_add(json_nexthop_ll
, "scope",
10010 json_object_boolean_true_add(json_nexthop_ll
,
10013 if (!attr
->mp_nexthop_prefer_global
)
10014 json_object_boolean_true_add(json_nexthop_ll
,
10017 json_object_boolean_true_add(
10018 json_nexthop_global
, "used");
10020 vty_out(vty
, " (%s) %s\n",
10021 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
10022 buf
, INET6_ADDRSTRLEN
),
10023 attr
->mp_nexthop_prefer_global
10024 ? "(prefer-global)"
10028 /* If we do not have a link-local nexthop then we must flag the
10029 global as "used" */
10032 json_object_boolean_true_add(json_nexthop_global
,
10036 if (safi
== SAFI_EVPN
&&
10037 bgp_evpn_is_esi_valid(&attr
->esi
)) {
10038 route_vty_out_detail_es_info(vty
, path
, attr
, json_path
);
10041 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10042 * Int/Ext/Local, Atomic, best */
10044 json_object_string_add(json_path
, "origin",
10045 bgp_origin_long_str
[attr
->origin
]);
10047 vty_out(vty
, " Origin %s",
10048 bgp_origin_long_str
[attr
->origin
]);
10050 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
10052 json_object_int_add(json_path
, "metric", attr
->med
);
10054 vty_out(vty
, ", metric %u", attr
->med
);
10057 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
10059 json_object_int_add(json_path
, "locPrf",
10062 vty_out(vty
, ", localpref %u", attr
->local_pref
);
10065 if (attr
->weight
!= 0) {
10067 json_object_int_add(json_path
, "weight", attr
->weight
);
10069 vty_out(vty
, ", weight %u", attr
->weight
);
10072 if (attr
->tag
!= 0) {
10074 json_object_int_add(json_path
, "tag", attr
->tag
);
10076 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
10079 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
10081 json_object_boolean_false_add(json_path
, "valid");
10083 vty_out(vty
, ", invalid");
10084 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
10086 json_object_boolean_true_add(json_path
, "valid");
10088 vty_out(vty
, ", valid");
10091 if (path
->peer
!= bgp
->peer_self
) {
10092 if (path
->peer
->as
== path
->peer
->local_as
) {
10093 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
10095 json_object_string_add(
10097 "confed-internal");
10099 vty_out(vty
, ", confed-internal");
10102 json_object_string_add(
10103 json_peer
, "type", "internal");
10105 vty_out(vty
, ", internal");
10108 if (bgp_confederation_peers_check(bgp
,
10111 json_object_string_add(
10113 "confed-external");
10115 vty_out(vty
, ", confed-external");
10118 json_object_string_add(
10119 json_peer
, "type", "external");
10121 vty_out(vty
, ", external");
10124 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
10126 json_object_boolean_true_add(json_path
, "aggregated");
10127 json_object_boolean_true_add(json_path
, "local");
10129 vty_out(vty
, ", aggregated, local");
10131 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
10133 json_object_boolean_true_add(json_path
, "sourced");
10135 vty_out(vty
, ", sourced");
10138 json_object_boolean_true_add(json_path
, "sourced");
10139 json_object_boolean_true_add(json_path
, "local");
10141 vty_out(vty
, ", sourced, local");
10145 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
10147 json_object_boolean_true_add(json_path
,
10148 "atomicAggregate");
10150 vty_out(vty
, ", atomic-aggregate");
10153 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
10154 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
10155 && bgp_path_info_mpath_count(path
))) {
10157 json_object_boolean_true_add(json_path
, "multipath");
10159 vty_out(vty
, ", multipath");
10162 // Mark the bestpath(s)
10163 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
10164 first_as
= aspath_get_first_as(attr
->aspath
);
10167 if (!json_bestpath
)
10168 json_bestpath
= json_object_new_object();
10169 json_object_int_add(json_bestpath
, "bestpathFromAs",
10173 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
10175 vty_out(vty
, ", bestpath-from-AS Local");
10179 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
10181 if (!json_bestpath
)
10182 json_bestpath
= json_object_new_object();
10183 json_object_boolean_true_add(json_bestpath
, "overall");
10184 json_object_string_add(
10185 json_bestpath
, "selectionReason",
10186 bgp_path_selection_reason2str(bn
->reason
));
10188 vty_out(vty
, ", best");
10189 vty_out(vty
, " (%s)",
10190 bgp_path_selection_reason2str(bn
->reason
));
10194 if (curr_state
!= RPKI_NOT_BEING_USED
) {
10196 json_object_string_add(
10197 json_path
, "rpkiValidationState",
10198 bgp_rpki_validation2str(curr_state
));
10200 vty_out(vty
, ", rpki validation-state: %s",
10201 bgp_rpki_validation2str(curr_state
));
10205 json_object_object_add(json_path
, "bestpath", json_bestpath
);
10208 vty_out(vty
, "\n");
10210 /* Line 4 display Community */
10211 if (attr
->community
) {
10213 if (!attr
->community
->json
)
10214 community_str(attr
->community
, true);
10215 json_object_lock(attr
->community
->json
);
10216 json_object_object_add(json_path
, "community",
10217 attr
->community
->json
);
10219 vty_out(vty
, " Community: %s\n",
10220 attr
->community
->str
);
10224 /* Line 5 display Extended-community */
10225 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
10227 json_ext_community
= json_object_new_object();
10228 json_object_string_add(json_ext_community
, "string",
10229 attr
->ecommunity
->str
);
10230 json_object_object_add(json_path
, "extendedCommunity",
10231 json_ext_community
);
10233 vty_out(vty
, " Extended Community: %s\n",
10234 attr
->ecommunity
->str
);
10238 /* Line 6 display Large community */
10239 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
10241 if (!attr
->lcommunity
->json
)
10242 lcommunity_str(attr
->lcommunity
, true);
10243 json_object_lock(attr
->lcommunity
->json
);
10244 json_object_object_add(json_path
, "largeCommunity",
10245 attr
->lcommunity
->json
);
10247 vty_out(vty
, " Large Community: %s\n",
10248 attr
->lcommunity
->str
);
10252 /* Line 7 display Originator, Cluster-id */
10253 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
10254 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
10255 char buf
[BUFSIZ
] = {0};
10257 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
10259 json_object_string_add(
10260 json_path
, "originatorId",
10261 inet_ntop(AF_INET
, &attr
->originator_id
,
10262 buf
, sizeof(buf
)));
10264 vty_out(vty
, " Originator: %pI4",
10265 &attr
->originator_id
);
10268 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
10269 struct cluster_list
*cluster
=
10270 bgp_attr_get_cluster(attr
);
10274 json_cluster_list
= json_object_new_object();
10275 json_cluster_list_list
=
10276 json_object_new_array();
10278 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10279 json_string
= json_object_new_string(
10282 buf
, sizeof(buf
)));
10283 json_object_array_add(
10284 json_cluster_list_list
,
10289 * struct cluster_list does not have
10290 * "str" variable like aspath and community
10291 * do. Add this someday if someone asks
10293 * json_object_string_add(json_cluster_list,
10294 * "string", cluster->str);
10296 json_object_object_add(json_cluster_list
,
10298 json_cluster_list_list
);
10299 json_object_object_add(json_path
, "clusterList",
10300 json_cluster_list
);
10302 vty_out(vty
, ", Cluster list: ");
10304 for (i
= 0; i
< cluster
->length
/ 4; i
++) {
10305 vty_out(vty
, "%pI4 ",
10306 &cluster
->list
[i
]);
10312 vty_out(vty
, "\n");
10315 if (path
->extra
&& path
->extra
->damp_info
)
10316 bgp_damp_info_vty(vty
, bgp
, path
, afi
, safi
, json_path
);
10319 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
10320 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
10321 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
10324 json_object_int_add(json_path
, "remoteLabel", label
);
10326 vty_out(vty
, " Remote label: %d\n", label
);
10330 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
10331 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
10333 json_object_string_add(json_path
, "remoteSid", buf
);
10335 vty_out(vty
, " Remote SID: %s\n", buf
);
10339 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
10341 json_object_int_add(json_path
, "labelIndex",
10342 attr
->label_index
);
10344 vty_out(vty
, " Label Index: %d\n",
10345 attr
->label_index
);
10348 /* Line 8 display Addpath IDs */
10349 if (path
->addpath_rx_id
10350 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
10352 json_object_int_add(json_path
, "addpathRxId",
10353 path
->addpath_rx_id
);
10355 /* Keep backwards compatibility with the old API
10356 * by putting TX All's ID in the old field
10358 json_object_int_add(
10359 json_path
, "addpathTxId",
10361 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
10363 /* ... but create a specific field for each
10366 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
10367 json_object_int_add(
10369 bgp_addpath_names(i
)->id_json_name
,
10370 path
->tx_addpath
.addpath_tx_id
[i
]);
10373 vty_out(vty
, " AddPath ID: RX %u, ",
10374 path
->addpath_rx_id
);
10376 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
10380 /* If we used addpath to TX a non-bestpath we need to display
10381 * "Advertised to" on a path-by-path basis
10383 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10386 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10388 bgp_addpath_encode_tx(peer
, afi
, safi
);
10389 has_adj
= bgp_adj_out_lookup(
10391 bgp_addpath_id_for_peer(peer
, afi
, safi
,
10392 &path
->tx_addpath
));
10394 if ((addpath_capable
&& has_adj
)
10395 || (!addpath_capable
&& has_adj
10396 && CHECK_FLAG(path
->flags
,
10397 BGP_PATH_SELECTED
))) {
10398 if (json_path
&& !json_adv_to
)
10399 json_adv_to
= json_object_new_object();
10401 route_vty_out_advertised_to(
10403 " Advertised to:", json_adv_to
);
10409 json_object_object_add(
10410 json_path
, "advertisedTo", json_adv_to
);
10414 vty_out(vty
, "\n");
10419 /* Line 9 display Uptime */
10420 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
10422 json_last_update
= json_object_new_object();
10423 json_object_int_add(json_last_update
, "epoch", tbuf
);
10424 json_object_string_add(json_last_update
, "string",
10426 json_object_object_add(json_path
, "lastUpdate",
10429 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
10431 /* Line 10 display PMSI tunnel attribute, if present */
10432 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
10433 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
10434 bgp_attr_get_pmsi_tnl_type(attr
),
10435 PMSI_TNLTYPE_STR_DEFAULT
);
10438 json_pmsi
= json_object_new_object();
10439 json_object_string_add(json_pmsi
, "tunnelType", str
);
10440 json_object_int_add(json_pmsi
, "label",
10441 label2vni(&attr
->label
));
10442 json_object_object_add(json_path
, "pmsi", json_pmsi
);
10444 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
10445 str
, label2vni(&attr
->label
));
10448 /* Output some debug about internal state of the dest flags */
10450 if (CHECK_FLAG(bn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
10451 json_object_boolean_true_add(json_path
, "processScheduled");
10452 if (CHECK_FLAG(bn
->flags
, BGP_NODE_USER_CLEAR
))
10453 json_object_boolean_true_add(json_path
, "userCleared");
10454 if (CHECK_FLAG(bn
->flags
, BGP_NODE_LABEL_CHANGED
))
10455 json_object_boolean_true_add(json_path
, "labelChanged");
10456 if (CHECK_FLAG(bn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
))
10457 json_object_boolean_true_add(json_path
, "registeredForLabel");
10458 if (CHECK_FLAG(bn
->flags
, BGP_NODE_SELECT_DEFER
))
10459 json_object_boolean_true_add(json_path
, "selectDefered");
10460 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALLED
))
10461 json_object_boolean_true_add(json_path
, "fibInstalled");
10462 if (CHECK_FLAG(bn
->flags
, BGP_NODE_FIB_INSTALL_PENDING
))
10463 json_object_boolean_true_add(json_path
, "fibPending");
10466 /* We've constructed the json object for this path, add it to the json
10470 if (json_nexthop_global
|| json_nexthop_ll
) {
10471 json_nexthops
= json_object_new_array();
10473 if (json_nexthop_global
)
10474 json_object_array_add(json_nexthops
,
10475 json_nexthop_global
);
10477 if (json_nexthop_ll
)
10478 json_object_array_add(json_nexthops
,
10481 json_object_object_add(json_path
, "nexthops",
10485 json_object_object_add(json_path
, "peer", json_peer
);
10486 json_object_array_add(json_paths
, json_path
);
10490 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
10491 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10492 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
10494 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10495 const char *prefix_list_str
, afi_t afi
,
10496 safi_t safi
, enum bgp_show_type type
);
10497 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10498 const char *filter
, afi_t afi
, safi_t safi
,
10499 enum bgp_show_type type
);
10500 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10501 const char *rmap_str
, afi_t afi
, safi_t safi
,
10502 enum bgp_show_type type
);
10503 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10504 const char *com
, int exact
, afi_t afi
,
10506 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10507 const char *prefix
, afi_t afi
, safi_t safi
,
10508 enum bgp_show_type type
);
10509 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10510 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10512 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10513 const char *comstr
, int exact
, afi_t afi
,
10514 safi_t safi
, uint8_t show_flags
);
10517 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10518 struct bgp_table
*table
, enum bgp_show_type type
,
10519 void *output_arg
, char *rd
, int is_last
,
10520 unsigned long *output_cum
, unsigned long *total_cum
,
10521 unsigned long *json_header_depth
, uint8_t show_flags
)
10523 struct bgp_path_info
*pi
;
10524 struct bgp_dest
*dest
;
10527 unsigned long output_count
= 0;
10528 unsigned long total_count
= 0;
10530 json_object
*json_paths
= NULL
;
10532 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10533 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
10534 bool all
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
10536 if (output_cum
&& *output_cum
!= 0)
10539 if (use_json
&& !*json_header_depth
) {
10541 *json_header_depth
= 1;
10543 vty_out(vty
, "{\n");
10544 *json_header_depth
= 2;
10548 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10549 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
10550 " \"localAS\": %u,\n \"routes\": { ",
10551 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
10552 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
10555 table
->version
, &bgp
->router_id
,
10556 bgp
->default_local_pref
, bgp
->as
);
10558 vty_out(vty
, " \"routeDistinguishers\" : {");
10559 ++*json_header_depth
;
10563 if (use_json
&& rd
) {
10564 vty_out(vty
, " \"%s\" : { ", rd
);
10567 /* Start processing of routes. */
10568 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
10569 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10571 pi
= bgp_dest_get_bgp_path_info(dest
);
10577 json_paths
= json_object_new_array();
10581 for (; pi
; pi
= pi
->next
) {
10583 if (type
== bgp_show_type_flap_statistics
10584 || type
== bgp_show_type_flap_neighbor
10585 || type
== bgp_show_type_dampend_paths
10586 || type
== bgp_show_type_damp_neighbor
) {
10587 if (!(pi
->extra
&& pi
->extra
->damp_info
))
10590 if (type
== bgp_show_type_regexp
) {
10591 regex_t
*regex
= output_arg
;
10593 if (bgp_regexec(regex
, pi
->attr
->aspath
)
10597 if (type
== bgp_show_type_prefix_list
) {
10598 struct prefix_list
*plist
= output_arg
;
10600 if (prefix_list_apply(plist
, dest_p
)
10604 if (type
== bgp_show_type_filter_list
) {
10605 struct as_list
*as_list
= output_arg
;
10607 if (as_list_apply(as_list
, pi
->attr
->aspath
)
10608 != AS_FILTER_PERMIT
)
10611 if (type
== bgp_show_type_route_map
) {
10612 struct route_map
*rmap
= output_arg
;
10613 struct bgp_path_info path
;
10614 struct attr dummy_attr
;
10615 route_map_result_t ret
;
10617 dummy_attr
= *pi
->attr
;
10619 path
.peer
= pi
->peer
;
10620 path
.attr
= &dummy_attr
;
10622 ret
= route_map_apply(rmap
, dest_p
, &path
);
10623 if (ret
== RMAP_DENYMATCH
)
10626 if (type
== bgp_show_type_neighbor
10627 || type
== bgp_show_type_flap_neighbor
10628 || type
== bgp_show_type_damp_neighbor
) {
10629 union sockunion
*su
= output_arg
;
10631 if (pi
->peer
== NULL
10632 || pi
->peer
->su_remote
== NULL
10633 || !sockunion_same(pi
->peer
->su_remote
, su
))
10636 if (type
== bgp_show_type_cidr_only
) {
10637 uint32_t destination
;
10639 destination
= ntohl(dest_p
->u
.prefix4
.s_addr
);
10640 if (IN_CLASSC(destination
)
10641 && dest_p
->prefixlen
== 24)
10643 if (IN_CLASSB(destination
)
10644 && dest_p
->prefixlen
== 16)
10646 if (IN_CLASSA(destination
)
10647 && dest_p
->prefixlen
== 8)
10650 if (type
== bgp_show_type_prefix_longer
) {
10652 if (!prefix_match(p
, dest_p
))
10655 if (type
== bgp_show_type_community_all
) {
10656 if (!pi
->attr
->community
)
10659 if (type
== bgp_show_type_community
) {
10660 struct community
*com
= output_arg
;
10662 if (!pi
->attr
->community
10663 || !community_match(pi
->attr
->community
,
10667 if (type
== bgp_show_type_community_exact
) {
10668 struct community
*com
= output_arg
;
10670 if (!pi
->attr
->community
10671 || !community_cmp(pi
->attr
->community
, com
))
10674 if (type
== bgp_show_type_community_list
) {
10675 struct community_list
*list
= output_arg
;
10677 if (!community_list_match(pi
->attr
->community
,
10681 if (type
== bgp_show_type_community_list_exact
) {
10682 struct community_list
*list
= output_arg
;
10684 if (!community_list_exact_match(
10685 pi
->attr
->community
, list
))
10688 if (type
== bgp_show_type_lcommunity
) {
10689 struct lcommunity
*lcom
= output_arg
;
10691 if (!pi
->attr
->lcommunity
10692 || !lcommunity_match(pi
->attr
->lcommunity
,
10697 if (type
== bgp_show_type_lcommunity_exact
) {
10698 struct lcommunity
*lcom
= output_arg
;
10700 if (!pi
->attr
->lcommunity
10701 || !lcommunity_cmp(pi
->attr
->lcommunity
,
10705 if (type
== bgp_show_type_lcommunity_list
) {
10706 struct community_list
*list
= output_arg
;
10708 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
10713 == bgp_show_type_lcommunity_list_exact
) {
10714 struct community_list
*list
= output_arg
;
10716 if (!lcommunity_list_exact_match(
10717 pi
->attr
->lcommunity
, list
))
10720 if (type
== bgp_show_type_lcommunity_all
) {
10721 if (!pi
->attr
->lcommunity
)
10724 if (type
== bgp_show_type_dampend_paths
10725 || type
== bgp_show_type_damp_neighbor
) {
10726 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
10727 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10731 if (!use_json
&& header
) {
10733 "BGP table version is %" PRIu64
10734 ", local router ID is %pI4, vrf id ",
10735 table
->version
, &bgp
->router_id
);
10736 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10737 vty_out(vty
, "%s", VRFID_NONE_STR
);
10739 vty_out(vty
, "%u", bgp
->vrf_id
);
10740 vty_out(vty
, "\n");
10741 vty_out(vty
, "Default local pref %u, ",
10742 bgp
->default_local_pref
);
10743 vty_out(vty
, "local AS %u\n", bgp
->as
);
10744 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10745 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10746 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10747 if (type
== bgp_show_type_dampend_paths
10748 || type
== bgp_show_type_damp_neighbor
)
10749 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
10750 else if (type
== bgp_show_type_flap_statistics
10751 || type
== bgp_show_type_flap_neighbor
)
10752 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
10754 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
10755 : BGP_SHOW_HEADER
));
10758 if (rd
!= NULL
&& !display
&& !output_count
) {
10761 "Route Distinguisher: %s\n",
10764 if (type
== bgp_show_type_dampend_paths
10765 || type
== bgp_show_type_damp_neighbor
)
10766 damp_route_vty_out(vty
, dest_p
, pi
, display
,
10767 AFI_IP
, safi
, use_json
,
10769 else if (type
== bgp_show_type_flap_statistics
10770 || type
== bgp_show_type_flap_neighbor
)
10771 flap_route_vty_out(vty
, dest_p
, pi
, display
,
10772 AFI_IP
, safi
, use_json
,
10775 route_vty_out(vty
, dest_p
, pi
, display
, safi
,
10785 /* encode prefix */
10786 if (dest_p
->family
== AF_FLOWSPEC
) {
10787 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
10790 bgp_fs_nlri_get_string(
10792 dest_p
->u
.prefix_flowspec
.ptr
,
10793 dest_p
->u
.prefix_flowspec
.prefixlen
,
10794 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
,
10795 family2afi(dest_p
->u
10796 .prefix_flowspec
.family
));
10798 vty_out(vty
, "\"%s/%d\": ", retstr
,
10799 dest_p
->u
.prefix_flowspec
10802 vty_out(vty
, ",\"%s/%d\": ", retstr
,
10803 dest_p
->u
.prefix_flowspec
10807 vty_out(vty
, "\"%pFX\": ", dest_p
);
10809 vty_out(vty
, ",\"%pFX\": ", dest_p
);
10812 json_object_to_json_string_ext(
10813 json_paths
, JSON_C_TO_STRING_PRETTY
));
10814 json_object_free(json_paths
);
10818 json_object_free(json_paths
);
10822 output_count
+= *output_cum
;
10823 *output_cum
= output_count
;
10826 total_count
+= *total_cum
;
10827 *total_cum
= total_count
;
10831 vty_out(vty
, " }%s ", (is_last
? "" : ","));
10835 for (i
= 0; i
< *json_header_depth
; ++i
)
10836 vty_out(vty
, " } ");
10838 vty_out(vty
, "\n");
10842 /* No route is displayed */
10843 if (output_count
== 0) {
10844 if (type
== bgp_show_type_normal
)
10846 "No BGP prefixes displayed, %ld exist\n",
10850 "\nDisplayed %ld routes and %ld total paths\n",
10851 output_count
, total_count
);
10855 return CMD_SUCCESS
;
10858 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
10859 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
10860 enum bgp_show_type type
, void *output_arg
, bool use_json
)
10862 struct bgp_dest
*dest
, *next
;
10863 unsigned long output_cum
= 0;
10864 unsigned long total_cum
= 0;
10865 unsigned long json_header_depth
= 0;
10866 struct bgp_table
*itable
;
10868 uint8_t show_flags
= 0;
10870 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
10873 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10875 for (dest
= bgp_table_top(table
); dest
; dest
= next
) {
10876 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
10878 next
= bgp_route_next(dest
);
10879 if (prd_match
&& memcmp(dest_p
->u
.val
, prd_match
->val
, 8) != 0)
10882 itable
= bgp_dest_get_bgp_table_info(dest
);
10883 if (itable
!= NULL
) {
10884 struct prefix_rd prd
;
10885 char rd
[RD_ADDRSTRLEN
];
10887 memcpy(&prd
, dest_p
, sizeof(struct prefix_rd
));
10888 prefix_rd2str(&prd
, rd
, sizeof(rd
));
10889 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
10890 rd
, next
== NULL
, &output_cum
,
10891 &total_cum
, &json_header_depth
,
10898 if (output_cum
== 0)
10899 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
10903 "\nDisplayed %ld routes and %ld total paths\n",
10904 output_cum
, total_cum
);
10906 return CMD_SUCCESS
;
10908 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
10909 enum bgp_show_type type
, void *output_arg
,
10910 uint8_t show_flags
)
10912 struct bgp_table
*table
;
10913 unsigned long json_header_depth
= 0;
10914 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10917 bgp
= bgp_get_default();
10922 vty_out(vty
, "No BGP process is configured\n");
10924 vty_out(vty
, "{}\n");
10925 return CMD_WARNING
;
10928 table
= bgp
->rib
[afi
][safi
];
10929 /* use MPLS and ENCAP specific shows until they are merged */
10930 if (safi
== SAFI_MPLS_VPN
) {
10931 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
10932 output_arg
, use_json
);
10935 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
10936 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
10937 output_arg
, use_json
,
10940 /* labeled-unicast routes live in the unicast table */
10941 else if (safi
== SAFI_LABELED_UNICAST
)
10942 safi
= SAFI_UNICAST
;
10944 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, NULL
, 1,
10945 NULL
, NULL
, &json_header_depth
, show_flags
);
10948 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
10949 safi_t safi
, uint8_t show_flags
)
10951 struct listnode
*node
, *nnode
;
10954 bool route_output
= false;
10955 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
10958 vty_out(vty
, "{\n");
10960 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
10961 route_output
= true;
10964 vty_out(vty
, ",\n");
10968 vty_out(vty
, "\"%s\":",
10969 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10973 vty_out(vty
, "\nInstance %s:\n",
10974 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10978 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
10983 vty_out(vty
, "}\n");
10984 else if (!route_output
)
10985 vty_out(vty
, "%% BGP instance not found\n");
10988 /* Header of detailed BGP route information */
10989 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
10990 struct bgp_dest
*dest
, struct prefix_rd
*prd
,
10991 afi_t afi
, safi_t safi
, json_object
*json
)
10993 struct bgp_path_info
*pi
;
10994 const struct prefix
*p
;
10996 struct listnode
*node
, *nnode
;
10997 char buf1
[RD_ADDRSTRLEN
];
10998 char prefix_str
[BUFSIZ
];
11002 int accept_own
= 0;
11003 int route_filter_translated_v4
= 0;
11004 int route_filter_v4
= 0;
11005 int route_filter_translated_v6
= 0;
11006 int route_filter_v6
= 0;
11007 int llgr_stale
= 0;
11009 int accept_own_nexthop
= 0;
11012 int no_advertise
= 0;
11016 int has_valid_label
= 0;
11017 mpls_label_t label
= 0;
11018 json_object
*json_adv_to
= NULL
;
11020 p
= bgp_dest_get_prefix(dest
);
11021 has_valid_label
= bgp_is_valid_label(&dest
->local_label
);
11023 if (has_valid_label
)
11024 label
= label_pton(&dest
->local_label
);
11026 if (safi
== SAFI_EVPN
) {
11029 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11030 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
11032 prd
? ":" : "", (struct prefix_evpn
*)p
);
11034 json_object_string_add(json
, "rd",
11035 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
11037 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
11041 vty_out(vty
, "BGP routing table entry for %s%s%pFX\n",
11042 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
11043 ? prefix_rd2str(prd
, buf1
,
11046 safi
== SAFI_MPLS_VPN
? ":" : "", p
);
11049 json_object_string_add(json
, "prefix",
11050 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
11053 if (has_valid_label
) {
11055 json_object_int_add(json
, "localLabel", label
);
11057 vty_out(vty
, "Local label: %d\n", label
);
11061 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
11062 vty_out(vty
, "not allocated\n");
11064 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
11066 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
11068 if (bgp_path_suppressed(pi
))
11071 if (pi
->attr
->community
== NULL
)
11074 no_advertise
+= community_include(
11075 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
11076 no_export
+= community_include(pi
->attr
->community
,
11077 COMMUNITY_NO_EXPORT
);
11078 local_as
+= community_include(pi
->attr
->community
,
11079 COMMUNITY_LOCAL_AS
);
11080 accept_own
+= community_include(pi
->attr
->community
,
11081 COMMUNITY_ACCEPT_OWN
);
11082 route_filter_translated_v4
+= community_include(
11083 pi
->attr
->community
,
11084 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
11085 route_filter_translated_v6
+= community_include(
11086 pi
->attr
->community
,
11087 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
11088 route_filter_v4
+= community_include(
11089 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
11090 route_filter_v6
+= community_include(
11091 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
11092 llgr_stale
+= community_include(pi
->attr
->community
,
11093 COMMUNITY_LLGR_STALE
);
11094 no_llgr
+= community_include(pi
->attr
->community
,
11095 COMMUNITY_NO_LLGR
);
11096 accept_own_nexthop
+=
11097 community_include(pi
->attr
->community
,
11098 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
11099 blackhole
+= community_include(pi
->attr
->community
,
11100 COMMUNITY_BLACKHOLE
);
11101 no_peer
+= community_include(pi
->attr
->community
,
11102 COMMUNITY_NO_PEER
);
11107 vty_out(vty
, "Paths: (%d available", count
);
11109 vty_out(vty
, ", best #%d", best
);
11110 if (safi
== SAFI_UNICAST
) {
11111 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
11112 vty_out(vty
, ", table %s",
11115 vty_out(vty
, ", vrf %s",
11119 vty_out(vty
, ", no best path");
11123 ", accept own local route exported and imported in different VRF");
11124 else if (route_filter_translated_v4
)
11126 ", mark translated RTs for VPNv4 route filtering");
11127 else if (route_filter_v4
)
11129 ", attach RT as-is for VPNv4 route filtering");
11130 else if (route_filter_translated_v6
)
11132 ", mark translated RTs for VPNv6 route filtering");
11133 else if (route_filter_v6
)
11135 ", attach RT as-is for VPNv6 route filtering");
11136 else if (llgr_stale
)
11138 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11141 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11142 else if (accept_own_nexthop
)
11144 ", accept local nexthop");
11145 else if (blackhole
)
11146 vty_out(vty
, ", inform peer to blackhole prefix");
11147 else if (no_export
)
11148 vty_out(vty
, ", not advertised to EBGP peer");
11149 else if (no_advertise
)
11150 vty_out(vty
, ", not advertised to any peer");
11152 vty_out(vty
, ", not advertised outside local AS");
11155 ", inform EBGP peer not to advertise to their EBGP peers");
11159 ", Advertisements suppressed by an aggregate.");
11160 vty_out(vty
, ")\n");
11163 /* If we are not using addpath then we can display Advertised to and
11165 * show what peers we advertised the bestpath to. If we are using
11167 * though then we must display Advertised to on a path-by-path basis. */
11168 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
11169 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
11170 if (bgp_adj_out_lookup(peer
, dest
, 0)) {
11171 if (json
&& !json_adv_to
)
11172 json_adv_to
= json_object_new_object();
11174 route_vty_out_advertised_to(
11176 " Advertised to non peer-group peers:\n ",
11183 json_object_object_add(json
, "advertisedTo",
11188 vty_out(vty
, " Not advertised to any peer");
11189 vty_out(vty
, "\n");
11194 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
11195 struct bgp_dest
*bgp_node
, struct vty
*vty
,
11196 struct bgp
*bgp
, afi_t afi
, safi_t safi
,
11197 json_object
*json
, enum bgp_path_type pathtype
,
11198 int *display
, enum rpki_states target_state
)
11200 struct bgp_path_info
*pi
;
11202 char rdbuf
[RD_ADDRSTRLEN
];
11203 json_object
*json_header
= NULL
;
11204 json_object
*json_paths
= NULL
;
11205 const struct prefix
*p
= bgp_dest_get_prefix(bgp_node
);
11207 for (pi
= bgp_dest_get_bgp_path_info(bgp_node
); pi
; pi
= pi
->next
) {
11208 enum rpki_states curr_state
= RPKI_NOT_BEING_USED
;
11210 if (p
->family
== AF_INET
|| p
->family
== AF_INET6
)
11211 curr_state
= hook_call(bgp_rpki_prefix_status
, pi
->peer
,
11214 if (target_state
!= RPKI_NOT_BEING_USED
11215 && curr_state
!= target_state
)
11218 if (json
&& !json_paths
) {
11219 /* Instantiate json_paths only if path is valid */
11220 json_paths
= json_object_new_array();
11222 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
11223 json_header
= json_object_new_object();
11225 json_header
= json
;
11229 route_vty_out_detail_header(
11230 vty
, bgp
, bgp_node
, pfx_rd
,
11231 AFI_IP
, safi
, json_header
);
11236 if (pathtype
== BGP_PATH_SHOW_ALL
11237 || (pathtype
== BGP_PATH_SHOW_BESTPATH
11238 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
11239 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
11240 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
11241 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
11242 route_vty_out_detail(vty
, bgp
, bgp_node
, pi
, AFI_IP
,
11243 safi
, curr_state
, json_paths
);
11246 if (json
&& json_paths
) {
11247 json_object_object_add(json_header
, "paths", json_paths
);
11250 json_object_object_add(json
, rdbuf
, json_header
);
11254 /* Display specified route of BGP table. */
11255 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
11256 struct bgp_table
*rib
, const char *ip_str
,
11257 afi_t afi
, safi_t safi
,
11258 struct prefix_rd
*prd
, int prefix_check
,
11259 enum bgp_path_type pathtype
, bool use_json
)
11263 struct prefix match
;
11264 struct bgp_dest
*dest
;
11265 struct bgp_dest
*rm
;
11266 struct bgp_table
*table
;
11267 json_object
*json
= NULL
;
11268 json_object
*json_paths
= NULL
;
11270 /* Check IP address argument. */
11271 ret
= str2prefix(ip_str
, &match
);
11273 vty_out(vty
, "address is malformed\n");
11274 return CMD_WARNING
;
11277 match
.family
= afi2family(afi
);
11280 json
= json_object_new_object();
11282 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
11283 for (dest
= bgp_table_top(rib
); dest
;
11284 dest
= bgp_route_next(dest
)) {
11285 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11287 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
11289 table
= bgp_dest_get_bgp_table_info(dest
);
11293 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11296 const struct prefix
*rm_p
= bgp_dest_get_prefix(rm
);
11298 && rm_p
->prefixlen
!= match
.prefixlen
) {
11299 bgp_dest_unlock_node(rm
);
11303 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11304 bgp
, afi
, safi
, json
, pathtype
,
11305 &display
, RPKI_NOT_BEING_USED
);
11307 bgp_dest_unlock_node(rm
);
11309 } else if (safi
== SAFI_EVPN
) {
11310 struct bgp_dest
*longest_pfx
;
11311 bool is_exact_pfxlen_match
= false;
11313 for (dest
= bgp_table_top(rib
); dest
;
11314 dest
= bgp_route_next(dest
)) {
11315 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11317 if (prd
&& memcmp(&dest_p
->u
.val
, prd
->val
, 8) != 0)
11319 table
= bgp_dest_get_bgp_table_info(dest
);
11323 longest_pfx
= NULL
;
11324 is_exact_pfxlen_match
= false;
11326 * Search through all the prefixes for a match. The
11327 * pfx's are enumerated in ascending order of pfxlens.
11328 * So, the last pfx match is the longest match. Set
11329 * is_exact_pfxlen_match when we get exact pfxlen match
11331 for (rm
= bgp_table_top(table
); rm
;
11332 rm
= bgp_route_next(rm
)) {
11333 const struct prefix
*rm_p
=
11334 bgp_dest_get_prefix(rm
);
11336 * Get prefixlen of the ip-prefix within type5
11339 if (evpn_type5_prefix_match(rm_p
, &match
)
11343 bgp_evpn_get_type5_prefixlen(
11345 if (type5_pfxlen
== match
.prefixlen
) {
11346 is_exact_pfxlen_match
= true;
11347 bgp_dest_unlock_node(rm
);
11356 if (prefix_check
&& !is_exact_pfxlen_match
)
11360 bgp_dest_lock_node(rm
);
11362 bgp_show_path_info((struct prefix_rd
*)dest_p
, rm
, vty
,
11363 bgp
, afi
, safi
, json
, pathtype
,
11364 &display
, RPKI_NOT_BEING_USED
);
11366 bgp_dest_unlock_node(rm
);
11368 } else if (safi
== SAFI_FLOWSPEC
) {
11370 json_paths
= json_object_new_array();
11372 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
11373 &match
, prefix_check
,
11379 json_object_object_add(json
, "paths",
11382 json_object_free(json_paths
);
11385 if ((dest
= bgp_node_match(rib
, &match
)) != NULL
) {
11386 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
11388 || dest_p
->prefixlen
== match
.prefixlen
) {
11389 bgp_show_path_info(NULL
, dest
, vty
, bgp
, afi
,
11390 safi
, json
, pathtype
,
11392 RPKI_NOT_BEING_USED
);
11395 bgp_dest_unlock_node(dest
);
11400 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11401 json
, JSON_C_TO_STRING_PRETTY
|
11402 JSON_C_TO_STRING_NOSLASHESCAPE
));
11403 json_object_free(json
);
11406 vty_out(vty
, "%% Network not in table\n");
11407 return CMD_WARNING
;
11411 return CMD_SUCCESS
;
11414 /* Display specified route of Main RIB */
11415 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
11416 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
11417 int prefix_check
, enum bgp_path_type pathtype
,
11421 bgp
= bgp_get_default();
11424 vty_out(vty
, "No BGP process is configured\n");
11426 vty_out(vty
, "{}\n");
11427 return CMD_WARNING
;
11431 /* labeled-unicast routes live in the unicast table */
11432 if (safi
== SAFI_LABELED_UNICAST
)
11433 safi
= SAFI_UNICAST
;
11435 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
11436 afi
, safi
, prd
, prefix_check
, pathtype
,
11440 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
11441 struct cmd_token
**argv
, bool exact
, afi_t afi
,
11442 safi_t safi
, bool uj
)
11444 struct lcommunity
*lcom
;
11449 uint8_t show_flags
= 0;
11453 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11455 b
= buffer_new(1024);
11456 for (i
= 0; i
< argc
; i
++) {
11458 buffer_putc(b
, ' ');
11460 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
11462 buffer_putstr(b
, argv
[i
]->arg
);
11466 buffer_putc(b
, '\0');
11468 str
= buffer_getstr(b
);
11471 lcom
= lcommunity_str2com(str
);
11472 XFREE(MTYPE_TMP
, str
);
11474 vty_out(vty
, "%% Large-community malformed\n");
11475 return CMD_WARNING
;
11478 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11479 (exact
? bgp_show_type_lcommunity_exact
11480 : bgp_show_type_lcommunity
),
11483 lcommunity_free(&lcom
);
11487 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
11488 const char *lcom
, bool exact
, afi_t afi
,
11489 safi_t safi
, bool uj
)
11491 struct community_list
*list
;
11492 uint8_t show_flags
= 0;
11495 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11498 list
= community_list_lookup(bgp_clist
, lcom
, 0,
11499 LARGE_COMMUNITY_LIST_MASTER
);
11500 if (list
== NULL
) {
11501 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
11503 return CMD_WARNING
;
11506 return bgp_show(vty
, bgp
, afi
, safi
,
11507 (exact
? bgp_show_type_lcommunity_list_exact
11508 : bgp_show_type_lcommunity_list
),
11512 DEFUN (show_ip_bgp_large_community_list
,
11513 show_ip_bgp_large_community_list_cmd
,
11514 "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]",
11518 BGP_INSTANCE_HELP_STR
11520 BGP_SAFI_WITH_LABEL_HELP_STR
11521 "Display routes matching the large-community-list\n"
11522 "large-community-list number\n"
11523 "large-community-list name\n"
11524 "Exact match of the large-communities\n"
11527 afi_t afi
= AFI_IP6
;
11528 safi_t safi
= SAFI_UNICAST
;
11530 bool exact_match
= 0;
11531 struct bgp
*bgp
= NULL
;
11532 bool uj
= use_json(argc
, argv
);
11537 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11540 return CMD_WARNING
;
11542 argv_find(argv
, argc
, "large-community-list", &idx
);
11544 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11546 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11549 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
11550 exact_match
, afi
, safi
, uj
);
11552 DEFUN (show_ip_bgp_large_community
,
11553 show_ip_bgp_large_community_cmd
,
11554 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
11558 BGP_INSTANCE_HELP_STR
11560 BGP_SAFI_WITH_LABEL_HELP_STR
11561 "Display routes matching the large-communities\n"
11562 "List of large-community numbers\n"
11563 "Exact match of the large-communities\n"
11566 afi_t afi
= AFI_IP6
;
11567 safi_t safi
= SAFI_UNICAST
;
11569 bool exact_match
= 0;
11570 struct bgp
*bgp
= NULL
;
11571 bool uj
= use_json(argc
, argv
);
11572 uint8_t show_flags
= 0;
11576 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11579 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11582 return CMD_WARNING
;
11584 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
11585 if (argv_find(argv
, argc
, "exact-match", &idx
))
11587 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
11588 exact_match
, afi
, safi
, uj
);
11590 return bgp_show(vty
, bgp
, afi
, safi
,
11591 bgp_show_type_lcommunity_all
, NULL
, show_flags
);
11594 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11595 safi_t safi
, struct json_object
*json_array
);
11596 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11597 safi_t safi
, struct json_object
*json
);
11600 DEFUN(show_ip_bgp_statistics_all
, show_ip_bgp_statistics_all_cmd
,
11601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11602 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11603 "Display number of prefixes for all afi/safi\n" JSON_STR
)
11605 bool uj
= use_json(argc
, argv
);
11606 struct bgp
*bgp
= NULL
;
11607 safi_t safi
= SAFI_UNICAST
;
11608 afi_t afi
= AFI_IP6
;
11610 struct json_object
*json_all
= NULL
;
11611 struct json_object
*json_afi_safi
= NULL
;
11613 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11616 return CMD_WARNING
;
11619 json_all
= json_object_new_object();
11621 FOREACH_AFI_SAFI (afi
, safi
) {
11623 * So limit output to those afi/safi pairs that
11624 * actually have something interesting in them
11626 if (strmatch(get_afi_safi_str(afi
, safi
, true),
11631 json_afi_safi
= json_object_new_array();
11632 json_object_object_add(
11634 get_afi_safi_str(afi
, safi
, true),
11637 json_afi_safi
= NULL
;
11640 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11645 json_object_to_json_string_ext(
11646 json_all
, JSON_C_TO_STRING_PRETTY
));
11647 json_object_free(json_all
);
11650 return CMD_SUCCESS
;
11653 /* BGP route print out function without JSON */
11654 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
11655 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
11656 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
11660 BGP_INSTANCE_HELP_STR
11663 "BGP RIB advertisement statistics\n"
11666 afi_t afi
= AFI_IP6
;
11667 safi_t safi
= SAFI_UNICAST
;
11668 struct bgp
*bgp
= NULL
;
11670 bool uj
= use_json(argc
, argv
);
11671 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11673 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11676 return CMD_WARNING
;
11679 json_afi_safi
= json_object_new_array();
11681 json_afi_safi
= NULL
;
11683 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11686 json
= json_object_new_object();
11687 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11689 vty_out(vty
, "%s", json_object_to_json_string_ext(
11690 json
, JSON_C_TO_STRING_PRETTY
));
11691 json_object_free(json
);
11696 /* BGP route print out function without JSON */
11697 DEFUN(show_ip_bgp_afi_safi_statistics
, show_ip_bgp_afi_safi_statistics_cmd
,
11698 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11699 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11701 statistics [json]",
11702 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11703 BGP_SAFI_WITH_LABEL_HELP_STR
11704 "BGP RIB advertisement statistics\n" JSON_STR
)
11706 afi_t afi
= AFI_IP6
;
11707 safi_t safi
= SAFI_UNICAST
;
11708 struct bgp
*bgp
= NULL
;
11710 bool uj
= use_json(argc
, argv
);
11711 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
11713 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11716 return CMD_WARNING
;
11719 json_afi_safi
= json_object_new_array();
11721 json_afi_safi
= NULL
;
11723 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
11726 json
= json_object_new_object();
11727 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
11730 json_object_to_json_string_ext(
11731 json
, JSON_C_TO_STRING_PRETTY
));
11732 json_object_free(json
);
11737 /* BGP route print out function without JSON */
11738 DEFPY(show_ip_bgp
, show_ip_bgp_cmd
,
11739 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11740 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11742 <[all$all] dampening <parameters>\
11746 |community-list <(1-500)|WORD> [exact-match]\
11747 |A.B.C.D/M longer-prefixes\
11748 |X:X::X:X/M longer-prefixes\
11750 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11751 BGP_SAFI_WITH_LABEL_HELP_STR
11752 "Display the entries for all address families\n"
11753 "Display detailed information about dampening\n"
11754 "Display detail of configured dampening parameters\n"
11755 "Display routes matching the route-map\n"
11756 "A route-map to match on\n"
11757 "Display routes conforming to the prefix-list\n"
11758 "Prefix-list name\n"
11759 "Display routes conforming to the filter-list\n"
11760 "Regular expression access list name\n"
11761 "Display routes matching the community-list\n"
11762 "community-list number\n"
11763 "community-list name\n"
11764 "Exact match of the communities\n"
11766 "Display route and more specific routes\n"
11768 "Display route and more specific routes\n")
11770 afi_t afi
= AFI_IP6
;
11771 safi_t safi
= SAFI_UNICAST
;
11772 int exact_match
= 0;
11773 struct bgp
*bgp
= NULL
;
11775 uint8_t show_flags
= 0;
11777 /* [<ipv4|ipv6> [all]] */
11779 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11780 if (argv_find(argv
, argc
, "ipv4", &idx
))
11781 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11783 if (argv_find(argv
, argc
, "ipv6", &idx
))
11784 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11787 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11790 return CMD_WARNING
;
11792 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11793 if (argv_find(argv
, argc
, "parameters", &idx
))
11794 return bgp_show_dampening_parameters(vty
, afi
, safi
,
11798 if (argv_find(argv
, argc
, "prefix-list", &idx
))
11799 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11800 safi
, bgp_show_type_prefix_list
);
11802 if (argv_find(argv
, argc
, "filter-list", &idx
))
11803 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11804 safi
, bgp_show_type_filter_list
);
11806 if (argv_find(argv
, argc
, "route-map", &idx
))
11807 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
11808 safi
, bgp_show_type_route_map
);
11810 if (argv_find(argv
, argc
, "community-list", &idx
)) {
11811 const char *clist_number_or_name
= argv
[++idx
]->arg
;
11812 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
11814 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
11815 exact_match
, afi
, safi
);
11817 /* prefix-longer */
11818 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
11819 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
11820 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
11822 bgp_show_type_prefix_longer
);
11824 return CMD_WARNING
;
11827 /* BGP route print out function with JSON */
11828 DEFPY (show_ip_bgp_json
,
11829 show_ip_bgp_json_cmd
,
11830 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
11833 |dampening <flap-statistics|dampened-paths>\
11834 |community [AA:NN|local-AS|no-advertise|no-export\
11835 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11836 |accept-own|accept-own-nexthop|route-filter-v6\
11837 |route-filter-v4|route-filter-translated-v6\
11838 |route-filter-translated-v4] [exact-match]\
11839 ] [json$uj | wide$wide]",
11843 BGP_INSTANCE_HELP_STR
11845 BGP_SAFI_WITH_LABEL_HELP_STR
11846 "Display the entries for all address families\n"
11847 "Display only routes with non-natural netmasks\n"
11848 "Display detailed information about dampening\n"
11849 "Display flap statistics of routes\n"
11850 "Display paths suppressed due to dampening\n"
11851 "Display routes matching the communities\n"
11853 "Do not send outside local AS (well-known community)\n"
11854 "Do not advertise to any peer (well-known community)\n"
11855 "Do not export to next AS (well-known community)\n"
11856 "Graceful shutdown (well-known community)\n"
11857 "Do not export to any peer (well-known community)\n"
11858 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11859 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11860 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11861 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11862 "Should accept VPN route with local nexthop (well-known community)\n"
11863 "RT VPNv6 route filtering (well-known community)\n"
11864 "RT VPNv4 route filtering (well-known community)\n"
11865 "RT translated VPNv6 route filtering (well-known community)\n"
11866 "RT translated VPNv4 route filtering (well-known community)\n"
11867 "Exact match of the communities\n"
11869 "Increase table width for longer prefixes\n")
11871 afi_t afi
= AFI_IP6
;
11872 safi_t safi
= SAFI_UNICAST
;
11873 enum bgp_show_type sh_type
= bgp_show_type_normal
;
11874 struct bgp
*bgp
= NULL
;
11876 int exact_match
= 0;
11877 char *community
= NULL
;
11879 uint8_t show_flags
= 0;
11884 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
11887 /* [<ipv4|ipv6> [all]] */
11889 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
11891 if (argv_find(argv
, argc
, "ipv4", &idx
))
11892 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
11894 if (argv_find(argv
, argc
, "ipv6", &idx
))
11895 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
11899 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
11901 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11904 return CMD_WARNING
;
11906 if (argv_find(argv
, argc
, "cidr-only", &idx
))
11907 sh_type
= bgp_show_type_cidr_only
;
11909 if (argv_find(argv
, argc
, "dampening", &idx
)) {
11910 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
11911 sh_type
= bgp_show_type_dampend_paths
;
11912 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11913 sh_type
= bgp_show_type_flap_statistics
;
11916 if (argv_find(argv
, argc
, "community", &idx
)) {
11917 char *maybecomm
= NULL
;
11919 if (idx
+ 1 < argc
) {
11920 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
11921 maybecomm
= argv
[idx
+ 1]->arg
;
11923 maybecomm
= argv
[idx
+ 1]->text
;
11926 if (maybecomm
&& !strmatch(maybecomm
, "json")
11927 && !strmatch(maybecomm
, "exact-match"))
11928 community
= maybecomm
;
11930 if (argv_find(argv
, argc
, "exact-match", &idx
))
11934 sh_type
= bgp_show_type_community_all
;
11938 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
11940 return bgp_show_community(vty
, bgp
, community
,
11941 exact_match
, afi
, safi
,
11944 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
,
11947 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11951 vty_out(vty
, "{\n");
11953 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11954 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
11955 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
11958 FOREACH_SAFI (safi
) {
11959 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11966 vty_out(vty
, ",\n");
11967 vty_out(vty
, "\"%s\":{\n",
11968 get_afi_safi_str(afi
, safi
,
11972 "\nFor address family: %s\n",
11973 get_afi_safi_str(afi
, safi
,
11977 bgp_show_community(vty
, bgp
, community
,
11981 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
11984 vty_out(vty
, "}\n");
11987 /* show <ip> bgp all: for each AFI and SAFI*/
11988 FOREACH_AFI_SAFI (afi
, safi
) {
11989 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
11996 vty_out(vty
, ",\n");
11998 vty_out(vty
, "\"%s\":{\n",
11999 get_afi_safi_str(afi
, safi
,
12003 "\nFor address family: %s\n",
12004 get_afi_safi_str(afi
, safi
,
12008 bgp_show_community(vty
, bgp
, community
,
12012 bgp_show(vty
, bgp
, afi
, safi
, sh_type
,
12015 vty_out(vty
, "}\n");
12019 vty_out(vty
, "}\n");
12021 return CMD_SUCCESS
;
12024 DEFUN (show_ip_bgp_route
,
12025 show_ip_bgp_route_cmd
,
12026 "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]",
12030 BGP_INSTANCE_HELP_STR
12032 BGP_SAFI_WITH_LABEL_HELP_STR
12033 "Network in the BGP routing table to display\n"
12035 "Network in the BGP routing table to display\n"
12037 "Display only the bestpath\n"
12038 "Display only multipaths\n"
12041 int prefix_check
= 0;
12043 afi_t afi
= AFI_IP6
;
12044 safi_t safi
= SAFI_UNICAST
;
12045 char *prefix
= NULL
;
12046 struct bgp
*bgp
= NULL
;
12047 enum bgp_path_type path_type
;
12048 bool uj
= use_json(argc
, argv
);
12052 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12055 return CMD_WARNING
;
12059 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12060 return CMD_WARNING
;
12063 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12064 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
12065 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
12067 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
12068 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
12071 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
12072 && afi
!= AFI_IP6
) {
12074 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12075 return CMD_WARNING
;
12077 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
12078 && afi
!= AFI_IP
) {
12080 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12081 return CMD_WARNING
;
12084 prefix
= argv
[idx
]->arg
;
12086 /* [<bestpath|multipath>] */
12087 if (argv_find(argv
, argc
, "bestpath", &idx
))
12088 path_type
= BGP_PATH_SHOW_BESTPATH
;
12089 else if (argv_find(argv
, argc
, "multipath", &idx
))
12090 path_type
= BGP_PATH_SHOW_MULTIPATH
;
12092 path_type
= BGP_PATH_SHOW_ALL
;
12094 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
12098 DEFUN (show_ip_bgp_regexp
,
12099 show_ip_bgp_regexp_cmd
,
12100 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
12104 BGP_INSTANCE_HELP_STR
12106 BGP_SAFI_WITH_LABEL_HELP_STR
12107 "Display routes matching the AS path regular expression\n"
12108 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12111 afi_t afi
= AFI_IP6
;
12112 safi_t safi
= SAFI_UNICAST
;
12113 struct bgp
*bgp
= NULL
;
12114 bool uj
= use_json(argc
, argv
);
12115 char *regstr
= NULL
;
12118 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12121 return CMD_WARNING
;
12123 // get index of regex
12124 if (argv_find(argv
, argc
, "REGEX", &idx
))
12125 regstr
= argv
[idx
]->arg
;
12128 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
12129 bgp_show_type_regexp
, uj
);
12132 DEFPY (show_ip_bgp_instance_all
,
12133 show_ip_bgp_instance_all_cmd
,
12134 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json$uj | wide$wide]",
12138 BGP_INSTANCE_ALL_HELP_STR
12140 BGP_SAFI_WITH_LABEL_HELP_STR
12142 "Increase table width for longer prefixes\n")
12144 afi_t afi
= AFI_IP
;
12145 safi_t safi
= SAFI_UNICAST
;
12146 struct bgp
*bgp
= NULL
;
12148 uint8_t show_flags
= 0;
12152 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12156 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
12158 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12161 return CMD_WARNING
;
12163 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, show_flags
);
12164 return CMD_SUCCESS
;
12167 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
12168 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
12173 uint8_t show_flags
= 0;
12176 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
12178 if (!config_bgp_aspath_validate(regstr
)) {
12179 vty_out(vty
, "Invalid character in REGEX %s\n",
12181 return CMD_WARNING_CONFIG_FAILED
;
12184 regex
= bgp_regcomp(regstr
);
12186 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
12187 return CMD_WARNING
;
12190 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, show_flags
);
12191 bgp_regex_free(regex
);
12195 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
12196 const char *prefix_list_str
, afi_t afi
,
12197 safi_t safi
, enum bgp_show_type type
)
12199 struct prefix_list
*plist
;
12200 uint8_t show_flags
= 0;
12202 plist
= prefix_list_lookup(afi
, prefix_list_str
);
12203 if (plist
== NULL
) {
12204 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
12206 return CMD_WARNING
;
12209 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, show_flags
);
12212 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
12213 const char *filter
, afi_t afi
, safi_t safi
,
12214 enum bgp_show_type type
)
12216 struct as_list
*as_list
;
12217 uint8_t show_flags
= 0;
12219 as_list
= as_list_lookup(filter
);
12220 if (as_list
== NULL
) {
12221 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
12223 return CMD_WARNING
;
12226 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, show_flags
);
12229 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
12230 const char *rmap_str
, afi_t afi
, safi_t safi
,
12231 enum bgp_show_type type
)
12233 struct route_map
*rmap
;
12234 uint8_t show_flags
= 0;
12236 rmap
= route_map_lookup_by_name(rmap_str
);
12238 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
12239 return CMD_WARNING
;
12242 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, show_flags
);
12245 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
12246 const char *comstr
, int exact
, afi_t afi
,
12247 safi_t safi
, uint8_t show_flags
)
12249 struct community
*com
;
12252 com
= community_str2com(comstr
);
12254 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
12255 return CMD_WARNING
;
12258 ret
= bgp_show(vty
, bgp
, afi
, safi
,
12259 (exact
? bgp_show_type_community_exact
12260 : bgp_show_type_community
),
12262 community_free(&com
);
12267 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
12268 const char *com
, int exact
, afi_t afi
,
12271 struct community_list
*list
;
12272 uint8_t show_flags
= 0;
12274 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
12275 if (list
== NULL
) {
12276 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
12277 return CMD_WARNING
;
12280 return bgp_show(vty
, bgp
, afi
, safi
,
12281 (exact
? bgp_show_type_community_list_exact
12282 : bgp_show_type_community_list
),
12286 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
12287 const char *prefix
, afi_t afi
, safi_t safi
,
12288 enum bgp_show_type type
)
12292 uint8_t show_flags
= 0;
12296 ret
= str2prefix(prefix
, p
);
12298 vty_out(vty
, "%% Malformed Prefix\n");
12299 return CMD_WARNING
;
12302 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, show_flags
);
12308 BGP_STATS_MAXBITLEN
= 0,
12310 BGP_STATS_PREFIXES
,
12312 BGP_STATS_UNAGGREGATEABLE
,
12313 BGP_STATS_MAX_AGGREGATEABLE
,
12314 BGP_STATS_AGGREGATES
,
12316 BGP_STATS_ASPATH_COUNT
,
12317 BGP_STATS_ASPATH_MAXHOPS
,
12318 BGP_STATS_ASPATH_TOTHOPS
,
12319 BGP_STATS_ASPATH_MAXSIZE
,
12320 BGP_STATS_ASPATH_TOTSIZE
,
12321 BGP_STATS_ASN_HIGHEST
,
12325 #define TABLE_STATS_IDX_VTY 0
12326 #define TABLE_STATS_IDX_JSON 1
12328 static const char *table_stats_strs
[][2] = {
12329 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
12330 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
12331 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
12332 [BGP_STATS_UNAGGREGATEABLE
] = {"Unaggregateable prefixes",
12333 "unaggregateablePrefixes"},
12334 [BGP_STATS_MAX_AGGREGATEABLE
] = {"Maximum aggregateable prefixes",
12335 "maximumAggregateablePrefixes"},
12336 [BGP_STATS_AGGREGATES
] = {"BGP Aggregate advertisements",
12337 "bgpAggregateAdvertisements"},
12338 [BGP_STATS_SPACE
] = {"Address space advertised",
12339 "addressSpaceAdvertised"},
12340 [BGP_STATS_ASPATH_COUNT
] = {"Advertisements with paths",
12341 "advertisementsWithPaths"},
12342 [BGP_STATS_ASPATH_MAXHOPS
] = {"Longest AS-Path (hops)",
12344 [BGP_STATS_ASPATH_MAXSIZE
] = {"Largest AS-Path (bytes)",
12346 [BGP_STATS_ASPATH_TOTHOPS
] = {"Average AS-Path length (hops)",
12347 "averageAsPathLengthHops"},
12348 [BGP_STATS_ASPATH_TOTSIZE
] = {"Average AS-Path size (bytes)",
12349 "averageAsPathSizeBytes"},
12350 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN", "highestPublicAsn"},
12351 [BGP_STATS_MAX
] = {NULL
, NULL
}
12354 struct bgp_table_stats
{
12355 struct bgp_table
*table
;
12356 unsigned long long counts
[BGP_STATS_MAX
];
12357 double total_space
;
12360 static void bgp_table_stats_rn(struct bgp_dest
*dest
, struct bgp_dest
*top
,
12361 struct bgp_table_stats
*ts
, unsigned int space
)
12363 struct bgp_dest
*pdest
= bgp_dest_parent_nolock(dest
);
12364 struct bgp_path_info
*pi
;
12365 const struct prefix
*rn_p
;
12367 if (!bgp_dest_has_bgp_path_info_data(dest
))
12370 rn_p
= bgp_dest_get_prefix(dest
);
12371 ts
->counts
[BGP_STATS_PREFIXES
]++;
12372 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
12374 /* check if the prefix is included by any other announcements */
12375 while (pdest
&& !bgp_dest_has_bgp_path_info_data(pdest
))
12376 pdest
= bgp_dest_parent_nolock(pdest
);
12378 if (pdest
== NULL
|| pdest
== top
) {
12379 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
12380 /* announced address space */
12382 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
12383 } else if (bgp_dest_has_bgp_path_info_data(pdest
))
12384 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
12387 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
12388 ts
->counts
[BGP_STATS_RIB
]++;
12390 if (CHECK_FLAG(pi
->attr
->flag
,
12391 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
12392 ts
->counts
[BGP_STATS_AGGREGATES
]++;
12394 /* as-path stats */
12395 if (pi
->attr
->aspath
) {
12396 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
12397 unsigned int size
= aspath_size(pi
->attr
->aspath
);
12398 as_t highest
= aspath_highest(pi
->attr
->aspath
);
12400 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
12402 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
12403 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
12405 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
12406 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
12408 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
12409 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
12410 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
12411 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
12416 static int bgp_table_stats_walker(struct thread
*t
)
12418 struct bgp_dest
*dest
, *ndest
;
12419 struct bgp_dest
*top
;
12420 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
12421 unsigned int space
= 0;
12423 if (!(top
= bgp_table_top(ts
->table
)))
12426 switch (ts
->table
->afi
) {
12428 space
= IPV4_MAX_BITLEN
;
12431 space
= IPV6_MAX_BITLEN
;
12434 space
= EVPN_ROUTE_PREFIXLEN
;
12440 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
12442 for (dest
= top
; dest
; dest
= bgp_route_next(dest
)) {
12443 if (ts
->table
->safi
== SAFI_MPLS_VPN
12444 || ts
->table
->safi
== SAFI_ENCAP
12445 || ts
->table
->safi
== SAFI_EVPN
) {
12446 struct bgp_table
*table
;
12448 table
= bgp_dest_get_bgp_table_info(dest
);
12452 top
= bgp_table_top(table
);
12453 for (ndest
= bgp_table_top(table
); ndest
;
12454 ndest
= bgp_route_next(ndest
))
12455 bgp_table_stats_rn(ndest
, top
, ts
, space
);
12457 bgp_table_stats_rn(dest
, top
, ts
, space
);
12464 static void bgp_table_stats_all(struct vty
*vty
, afi_t afi
, safi_t safi
,
12465 struct json_object
*json_array
)
12467 struct listnode
*node
, *nnode
;
12470 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
))
12471 bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12474 static int bgp_table_stats_single(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12475 safi_t safi
, struct json_object
*json_array
)
12477 struct bgp_table_stats ts
;
12479 int ret
= CMD_SUCCESS
;
12481 struct json_object
*json
= NULL
;
12484 json
= json_object_new_object();
12486 if (!bgp
->rib
[afi
][safi
]) {
12487 char warning_msg
[50];
12489 snprintf(warning_msg
, sizeof(warning_msg
),
12490 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi
,
12494 vty_out(vty
, "%s\n", warning_msg
);
12496 json_object_string_add(json
, "warning", warning_msg
);
12499 goto end_table_stats
;
12503 vty_out(vty
, "BGP %s RIB statistics (%s)\n",
12504 get_afi_safi_str(afi
, safi
, false), bgp
->name_pretty
);
12506 json_object_string_add(json
, "instance", bgp
->name_pretty
);
12508 /* labeled-unicast routes live in the unicast table */
12509 if (safi
== SAFI_LABELED_UNICAST
)
12510 safi
= SAFI_UNICAST
;
12512 memset(&ts
, 0, sizeof(ts
));
12513 ts
.table
= bgp
->rib
[afi
][safi
];
12514 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
12516 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
12517 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
])
12518 || (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
12522 case BGP_STATS_ASPATH_TOTHOPS
:
12523 case BGP_STATS_ASPATH_TOTSIZE
:
12526 temp_buf
, sizeof(temp_buf
), "%12.2f",
12528 ? (float)ts
.counts
[i
]
12530 [BGP_STATS_ASPATH_COUNT
]
12532 vty_out(vty
, "%-30s: %s",
12533 table_stats_strs
[i
]
12534 [TABLE_STATS_IDX_VTY
],
12537 json_object_double_add(
12539 table_stats_strs
[i
]
12540 [TABLE_STATS_IDX_JSON
],
12542 ? (double)ts
.counts
[i
]
12543 / (double)ts
.counts
12544 [BGP_STATS_ASPATH_COUNT
]
12548 case BGP_STATS_TOTPLEN
:
12551 temp_buf
, sizeof(temp_buf
), "%12.2f",
12553 ? (float)ts
.counts
[i
]
12555 [BGP_STATS_PREFIXES
]
12557 vty_out(vty
, "%-30s: %s",
12558 table_stats_strs
[i
]
12559 [TABLE_STATS_IDX_VTY
],
12562 json_object_double_add(
12564 table_stats_strs
[i
]
12565 [TABLE_STATS_IDX_JSON
],
12567 ? (double)ts
.counts
[i
]
12568 / (double)ts
.counts
12569 [BGP_STATS_PREFIXES
]
12573 case BGP_STATS_SPACE
:
12575 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
12577 vty_out(vty
, "%-30s: %s\n",
12578 table_stats_strs
[i
]
12579 [TABLE_STATS_IDX_VTY
],
12582 json_object_double_add(
12584 table_stats_strs
[i
]
12585 [TABLE_STATS_IDX_JSON
],
12586 (double)ts
.total_space
);
12588 if (afi
== AFI_IP6
) {
12590 snprintf(temp_buf
, sizeof(temp_buf
),
12593 * pow(2.0, -128 + 32));
12594 vty_out(vty
, "%30s: %s\n",
12595 "/32 equivalent %s\n",
12598 json_object_double_add(
12599 json
, "/32equivalent",
12600 (double)(ts
.total_space
12605 snprintf(temp_buf
, sizeof(temp_buf
),
12608 * pow(2.0, -128 + 48));
12609 vty_out(vty
, "%30s: %s\n",
12610 "/48 equivalent %s\n",
12613 json_object_double_add(
12614 json
, "/48equivalent",
12615 (double)(ts
.total_space
12621 snprintf(temp_buf
, sizeof(temp_buf
),
12623 ts
.total_space
* 100.
12625 vty_out(vty
, "%30s: %s\n",
12626 "% announced ", temp_buf
);
12628 json_object_double_add(
12629 json
, "%announced",
12630 (double)(ts
.total_space
* 100.
12634 snprintf(temp_buf
, sizeof(temp_buf
),
12637 * pow(2.0, -32 + 8));
12638 vty_out(vty
, "%30s: %s\n",
12639 "/8 equivalent ", temp_buf
);
12641 json_object_double_add(
12642 json
, "/8equivalent",
12643 (double)(ts
.total_space
12644 * pow(2.0, -32 + 8)));
12647 snprintf(temp_buf
, sizeof(temp_buf
),
12650 * pow(2.0, -32 + 24));
12651 vty_out(vty
, "%30s: %s\n",
12652 "/24 equivalent ", temp_buf
);
12654 json_object_double_add(
12655 json
, "/24equivalent",
12656 (double)(ts
.total_space
12657 * pow(2.0, -32 + 24)));
12663 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
12665 vty_out(vty
, "%-30s: %s",
12666 table_stats_strs
[i
]
12667 [TABLE_STATS_IDX_VTY
],
12670 json_object_int_add(
12672 table_stats_strs
[i
]
12673 [TABLE_STATS_IDX_JSON
],
12678 vty_out(vty
, "\n");
12682 json_object_array_add(json_array
, json
);
12686 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12687 safi_t safi
, struct json_object
*json_array
)
12690 bgp_table_stats_all(vty
, afi
, safi
, json_array
);
12691 return CMD_SUCCESS
;
12694 return bgp_table_stats_single(vty
, bgp
, afi
, safi
, json_array
);
12706 PCOUNT_BPATH_SELECTED
,
12707 PCOUNT_PFCNT
, /* the figure we display to users */
12711 static const char *const pcount_strs
[] = {
12712 [PCOUNT_ADJ_IN
] = "Adj-in",
12713 [PCOUNT_DAMPED
] = "Damped",
12714 [PCOUNT_REMOVED
] = "Removed",
12715 [PCOUNT_HISTORY
] = "History",
12716 [PCOUNT_STALE
] = "Stale",
12717 [PCOUNT_VALID
] = "Valid",
12718 [PCOUNT_ALL
] = "All RIB",
12719 [PCOUNT_COUNTED
] = "PfxCt counted",
12720 [PCOUNT_BPATH_SELECTED
] = "PfxCt Best Selected",
12721 [PCOUNT_PFCNT
] = "Useable",
12722 [PCOUNT_MAX
] = NULL
,
12725 struct peer_pcounts
{
12726 unsigned int count
[PCOUNT_MAX
];
12727 const struct peer
*peer
;
12728 const struct bgp_table
*table
;
12732 static void bgp_peer_count_proc(struct bgp_dest
*rn
, struct peer_pcounts
*pc
)
12734 const struct bgp_adj_in
*ain
;
12735 const struct bgp_path_info
*pi
;
12736 const struct peer
*peer
= pc
->peer
;
12738 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
12739 if (ain
->peer
== peer
)
12740 pc
->count
[PCOUNT_ADJ_IN
]++;
12742 for (pi
= bgp_dest_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
12744 if (pi
->peer
!= peer
)
12747 pc
->count
[PCOUNT_ALL
]++;
12749 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
12750 pc
->count
[PCOUNT_DAMPED
]++;
12751 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
12752 pc
->count
[PCOUNT_HISTORY
]++;
12753 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
12754 pc
->count
[PCOUNT_REMOVED
]++;
12755 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
12756 pc
->count
[PCOUNT_STALE
]++;
12757 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
12758 pc
->count
[PCOUNT_VALID
]++;
12759 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12760 pc
->count
[PCOUNT_PFCNT
]++;
12761 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
12762 pc
->count
[PCOUNT_BPATH_SELECTED
]++;
12764 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
12765 pc
->count
[PCOUNT_COUNTED
]++;
12766 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12768 EC_LIB_DEVELOPMENT
,
12769 "Attempting to count but flags say it is unusable");
12771 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
12773 EC_LIB_DEVELOPMENT
,
12774 "Not counted but flags say we should");
12779 static int bgp_peer_count_walker(struct thread
*t
)
12781 struct bgp_dest
*rn
, *rm
;
12782 const struct bgp_table
*table
;
12783 struct peer_pcounts
*pc
= THREAD_ARG(t
);
12785 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
12786 || pc
->safi
== SAFI_EVPN
) {
12787 /* Special handling for 2-level routing tables. */
12788 for (rn
= bgp_table_top(pc
->table
); rn
;
12789 rn
= bgp_route_next(rn
)) {
12790 table
= bgp_dest_get_bgp_table_info(rn
);
12792 for (rm
= bgp_table_top(table
); rm
;
12793 rm
= bgp_route_next(rm
))
12794 bgp_peer_count_proc(rm
, pc
);
12797 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
12798 bgp_peer_count_proc(rn
, pc
);
12803 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12804 safi_t safi
, bool use_json
)
12806 struct peer_pcounts pcounts
= {.peer
= peer
};
12808 json_object
*json
= NULL
;
12809 json_object
*json_loop
= NULL
;
12812 json
= json_object_new_object();
12813 json_loop
= json_object_new_object();
12816 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
12817 || !peer
->bgp
->rib
[afi
][safi
]) {
12819 json_object_string_add(
12821 "No such neighbor or address family");
12822 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12823 json_object_free(json
);
12824 json_object_free(json_loop
);
12826 vty_out(vty
, "%% No such neighbor or address family\n");
12828 return CMD_WARNING
;
12831 memset(&pcounts
, 0, sizeof(pcounts
));
12832 pcounts
.peer
= peer
;
12833 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
12834 pcounts
.safi
= safi
;
12836 /* in-place call via thread subsystem so as to record execution time
12837 * stats for the thread-walk (i.e. ensure this can't be blamed on
12838 * on just vty_read()).
12840 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
12843 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
12844 json_object_string_add(json
, "multiProtocol",
12845 get_afi_safi_str(afi
, safi
, true));
12846 json_object_int_add(json
, "pfxCounter",
12847 peer
->pcount
[afi
][safi
]);
12849 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12850 json_object_int_add(json_loop
, pcount_strs
[i
],
12853 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
12855 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12856 json_object_string_add(json
, "pfxctDriftFor",
12858 json_object_string_add(
12859 json
, "recommended",
12860 "Please report this bug, with the above command output");
12862 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12863 json
, JSON_C_TO_STRING_PRETTY
));
12864 json_object_free(json
);
12868 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
12869 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
12870 peer
->hostname
, peer
->host
,
12871 get_afi_safi_str(afi
, safi
, false));
12873 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
12874 get_afi_safi_str(afi
, safi
, false));
12877 vty_out(vty
, "PfxCt: %u\n", peer
->pcount
[afi
][safi
]);
12878 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
12880 for (i
= 0; i
< PCOUNT_MAX
; i
++)
12881 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
12884 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
12885 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
12887 "Please report this bug, with the above command output\n");
12891 return CMD_SUCCESS
;
12894 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
12895 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
12896 "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]",
12900 BGP_INSTANCE_HELP_STR
12903 "Detailed information on TCP and BGP neighbor connections\n"
12904 "Neighbor to display information about\n"
12905 "Neighbor to display information about\n"
12906 "Neighbor on BGP configured interface\n"
12907 "Display detailed prefix count information\n"
12910 afi_t afi
= AFI_IP6
;
12911 safi_t safi
= SAFI_UNICAST
;
12914 struct bgp
*bgp
= NULL
;
12915 bool uj
= use_json(argc
, argv
);
12920 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12923 return CMD_WARNING
;
12925 argv_find(argv
, argc
, "neighbors", &idx
);
12926 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
12928 return CMD_WARNING
;
12930 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
12933 #ifdef KEEP_OLD_VPN_COMMANDS
12934 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
12935 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
12936 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
12941 "Display information about all VPNv4 NLRIs\n"
12942 "Detailed information on TCP and BGP neighbor connections\n"
12943 "Neighbor to display information about\n"
12944 "Neighbor to display information about\n"
12945 "Neighbor on BGP configured interface\n"
12946 "Display detailed prefix count information\n"
12951 bool uj
= use_json(argc
, argv
);
12953 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
12955 return CMD_WARNING
;
12957 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
12960 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
12961 show_ip_bgp_vpn_all_route_prefix_cmd
,
12962 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
12967 "Display information about all VPNv4 NLRIs\n"
12968 "Network in the BGP routing table to display\n"
12969 "Network in the BGP routing table to display\n"
12973 char *network
= NULL
;
12974 struct bgp
*bgp
= bgp_get_default();
12976 vty_out(vty
, "Can't find default instance\n");
12977 return CMD_WARNING
;
12980 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
12981 network
= argv
[idx
]->arg
;
12982 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
12983 network
= argv
[idx
]->arg
;
12985 vty_out(vty
, "Unable to figure out Network\n");
12986 return CMD_WARNING
;
12989 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
12990 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12992 #endif /* KEEP_OLD_VPN_COMMANDS */
12994 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
12995 show_bgp_l2vpn_evpn_route_prefix_cmd
,
12996 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
13001 "Network in the BGP routing table to display\n"
13002 "Network in the BGP routing table to display\n"
13003 "Network in the BGP routing table to display\n"
13004 "Network in the BGP routing table to display\n"
13008 char *network
= NULL
;
13009 int prefix_check
= 0;
13011 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
13012 argv_find(argv
, argc
, "X:X::X:X", &idx
))
13013 network
= argv
[idx
]->arg
;
13014 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
13015 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
13016 network
= argv
[idx
]->arg
;
13019 vty_out(vty
, "Unable to figure out Network\n");
13020 return CMD_WARNING
;
13022 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
13023 prefix_check
, BGP_PATH_SHOW_ALL
,
13024 use_json(argc
, argv
));
13027 static void show_adj_route_header(struct vty
*vty
, struct bgp
*bgp
,
13028 struct bgp_table
*table
, int *header1
,
13029 int *header2
, json_object
*json
,
13030 json_object
*json_scode
,
13031 json_object
*json_ocode
, bool wide
)
13033 uint64_t version
= table
? table
->version
: 0;
13034 char buf
[BUFSIZ
] = {0};
13038 json_object_int_add(json
, "bgpTableVersion", version
);
13039 json_object_string_add(json
, "bgpLocalRouterId",
13041 &bgp
->router_id
, buf
,
13043 json_object_int_add(json
, "defaultLocPrf",
13044 bgp
->default_local_pref
);
13045 json_object_int_add(json
, "localAS", bgp
->as
);
13046 json_object_object_add(json
, "bgpStatusCodes",
13048 json_object_object_add(json
, "bgpOriginCodes",
13052 "BGP table version is %" PRIu64
13053 ", local router ID is %pI4, vrf id ",
13054 version
, &bgp
->router_id
);
13055 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13056 vty_out(vty
, "%s", VRFID_NONE_STR
);
13058 vty_out(vty
, "%u", bgp
->vrf_id
);
13059 vty_out(vty
, "\n");
13060 vty_out(vty
, "Default local pref %u, ",
13061 bgp
->default_local_pref
);
13062 vty_out(vty
, "local AS %u\n", bgp
->as
);
13063 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13064 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13065 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13071 vty_out(vty
, (wide
? BGP_SHOW_HEADER_WIDE
13072 : BGP_SHOW_HEADER
));
13078 show_adj_route(struct vty
*vty
, struct peer
*peer
, struct bgp_table
*table
,
13079 afi_t afi
, safi_t safi
, enum bgp_show_adj_route_type type
,
13080 const char *rmap_name
, json_object
*json
, json_object
*json_ar
,
13081 json_object
*json_scode
, json_object
*json_ocode
,
13082 uint8_t show_flags
, int *header1
, int *header2
, char *rd_str
,
13083 unsigned long *output_count
, unsigned long *filtered_count
)
13085 struct bgp_adj_in
*ain
;
13086 struct bgp_adj_out
*adj
;
13087 struct bgp_dest
*dest
;
13091 struct update_subgroup
*subgrp
;
13092 struct peer_af
*paf
;
13093 bool route_filtered
;
13094 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13095 bool wide
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13096 bool show_rd
= ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13097 || (safi
== SAFI_EVPN
))
13105 json_object_string_add(json
, "alert", "no BGP");
13106 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13107 json_object_free(json
);
13109 vty_out(vty
, "%% No bgp\n");
13113 subgrp
= peer_subgroup(peer
, afi
, safi
);
13115 if (type
== bgp_show_adj_route_advertised
&& subgrp
13116 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
13117 char buf
[BUFSIZ
] = {0};
13120 json_object_int_add(json
, "bgpTableVersion",
13122 json_object_string_add(json
, "bgpLocalRouterId",
13124 &bgp
->router_id
, buf
,
13126 json_object_int_add(json
, "defaultLocPrf",
13127 bgp
->default_local_pref
);
13128 json_object_int_add(json
, "localAS", bgp
->as
);
13129 json_object_object_add(json
, "bgpStatusCodes",
13131 json_object_object_add(json
, "bgpOriginCodes",
13133 json_object_string_add(
13134 json
, "bgpOriginatingDefaultNetwork",
13135 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13138 "BGP table version is %" PRIu64
13139 ", local router ID is %pI4, vrf id ",
13140 table
->version
, &bgp
->router_id
);
13141 if (bgp
->vrf_id
== VRF_UNKNOWN
)
13142 vty_out(vty
, "%s", VRFID_NONE_STR
);
13144 vty_out(vty
, "%u", bgp
->vrf_id
);
13145 vty_out(vty
, "\n");
13146 vty_out(vty
, "Default local pref %u, ",
13147 bgp
->default_local_pref
);
13148 vty_out(vty
, "local AS %u\n", bgp
->as
);
13149 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
13150 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
13151 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
13153 vty_out(vty
, "Originating default network %s\n\n",
13154 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
13159 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
13160 if (type
== bgp_show_adj_route_received
13161 || type
== bgp_show_adj_route_filtered
) {
13162 for (ain
= dest
->adj_in
; ain
; ain
= ain
->next
) {
13163 if (ain
->peer
!= peer
)
13166 show_adj_route_header(vty
, bgp
, table
, header1
,
13167 header2
, json
, json_scode
,
13170 if ((safi
== SAFI_MPLS_VPN
)
13171 || (safi
== SAFI_ENCAP
)
13172 || (safi
== SAFI_EVPN
)) {
13174 json_object_string_add(
13175 json_ar
, "rd", rd_str
);
13176 else if (show_rd
&& rd_str
) {
13178 "Route Distinguisher: %s\n",
13185 route_filtered
= false;
13187 /* Filter prefix using distribute list,
13188 * filter list or prefix list
13190 const struct prefix
*rn_p
=
13191 bgp_dest_get_prefix(dest
);
13192 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
13195 route_filtered
= true;
13197 /* Filter prefix using route-map */
13198 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
13199 safi
, rmap_name
, NULL
,
13202 if (type
== bgp_show_adj_route_filtered
&&
13203 !route_filtered
&& ret
!= RMAP_DENY
) {
13204 bgp_attr_undup(&attr
, ain
->attr
);
13208 if (type
== bgp_show_adj_route_received
13209 && (route_filtered
|| ret
== RMAP_DENY
))
13210 (*filtered_count
)++;
13212 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
13213 use_json
, json_ar
, wide
);
13214 bgp_attr_undup(&attr
, ain
->attr
);
13217 } else if (type
== bgp_show_adj_route_advertised
) {
13218 RB_FOREACH (adj
, bgp_adj_out_rb
, &dest
->adj_out
)
13219 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
13220 if (paf
->peer
!= peer
|| !adj
->attr
)
13223 show_adj_route_header(vty
, bgp
, table
,
13228 const struct prefix
*rn_p
=
13229 bgp_dest_get_prefix(dest
);
13232 ret
= bgp_output_modifier(
13233 peer
, rn_p
, &attr
, afi
, safi
,
13236 if (ret
!= RMAP_DENY
) {
13237 if ((safi
== SAFI_MPLS_VPN
)
13238 || (safi
== SAFI_ENCAP
)
13239 || (safi
== SAFI_EVPN
)) {
13241 json_object_string_add(
13248 "Route Distinguisher: %s\n",
13254 vty
, rn_p
, &attr
, safi
,
13259 (*filtered_count
)++;
13262 bgp_attr_undup(&attr
, adj
->attr
);
13264 } else if (type
== bgp_show_adj_route_bestpath
) {
13265 struct bgp_path_info
*pi
;
13267 show_adj_route_header(vty
, bgp
, table
, header1
, header2
,
13268 json
, json_scode
, json_ocode
,
13271 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
;
13273 if (pi
->peer
!= peer
)
13276 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
13279 route_vty_out_tmp(vty
,
13280 bgp_dest_get_prefix(dest
),
13281 pi
->attr
, safi
, use_json
,
13289 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
13290 safi_t safi
, enum bgp_show_adj_route_type type
,
13291 const char *rmap_name
, uint8_t show_flags
)
13294 struct bgp_table
*table
;
13295 json_object
*json
= NULL
;
13296 json_object
*json_scode
= NULL
;
13297 json_object
*json_ocode
= NULL
;
13298 json_object
*json_ar
= NULL
;
13299 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13301 /* Init BGP headers here so they're only displayed once
13302 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13308 * Initialize variables for each RD
13309 * All prefixes under an RD is aggregated within "json_routes"
13311 char rd_str
[BUFSIZ
] = {0};
13312 json_object
*json_routes
= NULL
;
13315 /* For 2-tier tables, prefix counts need to be
13316 * maintained across multiple runs of show_adj_route()
13318 unsigned long output_count_per_rd
;
13319 unsigned long filtered_count_per_rd
;
13320 unsigned long output_count
= 0;
13321 unsigned long filtered_count
= 0;
13324 json
= json_object_new_object();
13325 json_ar
= json_object_new_object();
13326 json_scode
= json_object_new_object();
13327 json_ocode
= json_object_new_object();
13329 json_object_string_add(json_scode
, "suppressed", "s");
13330 json_object_string_add(json_scode
, "damped", "d");
13331 json_object_string_add(json_scode
, "history", "h");
13332 json_object_string_add(json_scode
, "valid", "*");
13333 json_object_string_add(json_scode
, "best", ">");
13334 json_object_string_add(json_scode
, "multipath", "=");
13335 json_object_string_add(json_scode
, "internal", "i");
13336 json_object_string_add(json_scode
, "ribFailure", "r");
13337 json_object_string_add(json_scode
, "stale", "S");
13338 json_object_string_add(json_scode
, "removed", "R");
13340 json_object_string_add(json_ocode
, "igp", "i");
13341 json_object_string_add(json_ocode
, "egp", "e");
13342 json_object_string_add(json_ocode
, "incomplete", "?");
13345 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13347 json_object_string_add(
13349 "No such neighbor or address family");
13350 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13351 json_object_free(json
);
13353 vty_out(vty
, "%% No such neighbor or address family\n");
13355 return CMD_WARNING
;
13358 if ((type
== bgp_show_adj_route_received
13359 || type
== bgp_show_adj_route_filtered
)
13360 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
13361 PEER_FLAG_SOFT_RECONFIG
)) {
13363 json_object_string_add(
13365 "Inbound soft reconfiguration not enabled");
13366 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
13367 json_object_free(json
);
13370 "%% Inbound soft reconfiguration not enabled\n");
13372 return CMD_WARNING
;
13377 /* labeled-unicast routes live in the unicast table */
13378 if (safi
== SAFI_LABELED_UNICAST
)
13379 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
13381 table
= bgp
->rib
[afi
][safi
];
13383 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
13384 || (safi
== SAFI_EVPN
)) {
13386 struct bgp_dest
*dest
;
13388 for (dest
= bgp_table_top(table
); dest
;
13389 dest
= bgp_route_next(dest
)) {
13390 table
= bgp_dest_get_bgp_table_info(dest
);
13394 output_count_per_rd
= 0;
13395 filtered_count_per_rd
= 0;
13398 json_routes
= json_object_new_object();
13400 const struct prefix_rd
*prd
;
13401 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
13404 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
13406 show_adj_route(vty
, peer
, table
, afi
, safi
, type
,
13407 rmap_name
, json
, json_routes
, json_scode
,
13408 json_ocode
, show_flags
, &header1
,
13409 &header2
, rd_str
, &output_count_per_rd
,
13410 &filtered_count_per_rd
);
13412 /* Don't include an empty RD in the output! */
13413 if (json_routes
&& (output_count_per_rd
> 0))
13414 json_object_object_add(json_ar
, rd_str
,
13417 output_count
+= output_count_per_rd
;
13418 filtered_count
+= filtered_count_per_rd
;
13421 show_adj_route(vty
, peer
, table
, afi
, safi
, type
, rmap_name
,
13422 json
, json_ar
, json_scode
, json_ocode
,
13423 show_flags
, &header1
, &header2
, rd_str
,
13424 &output_count
, &filtered_count
);
13427 json_object_object_add(json
, "advertisedRoutes", json_ar
);
13428 json_object_int_add(json
, "totalPrefixCounter", output_count
);
13429 json_object_int_add(json
, "filteredPrefixCounter",
13432 vty_out(vty
, "%s\n",
13433 json_object_to_json_string_ext(
13434 json
, JSON_C_TO_STRING_PRETTY
));
13436 if (!output_count
&& !filtered_count
) {
13437 json_object_free(json_scode
);
13438 json_object_free(json_ocode
);
13442 json_object_free(json
);
13444 } else if (output_count
> 0) {
13445 if (filtered_count
> 0)
13447 "\nTotal number of prefixes %ld (%ld filtered)\n",
13448 output_count
, filtered_count
);
13450 vty_out(vty
, "\nTotal number of prefixes %ld\n",
13454 return CMD_SUCCESS
;
13457 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route
,
13458 show_ip_bgp_instance_neighbor_bestpath_route_cmd
,
13459 "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]",
13463 BGP_INSTANCE_HELP_STR
13465 BGP_SAFI_WITH_LABEL_HELP_STR
13466 "Detailed information on TCP and BGP neighbor connections\n"
13467 "Neighbor to display information about\n"
13468 "Neighbor to display information about\n"
13469 "Neighbor on BGP configured interface\n"
13470 "Display the routes selected by best path\n"
13472 "Increase table width for longer prefixes\n")
13474 afi_t afi
= AFI_IP6
;
13475 safi_t safi
= SAFI_UNICAST
;
13476 char *rmap_name
= NULL
;
13477 char *peerstr
= NULL
;
13478 struct bgp
*bgp
= NULL
;
13480 enum bgp_show_adj_route_type type
= bgp_show_adj_route_bestpath
;
13482 uint8_t show_flags
= 0;
13485 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13488 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13490 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13494 return CMD_WARNING
;
13496 argv_find(argv
, argc
, "neighbors", &idx
);
13497 peerstr
= argv
[++idx
]->arg
;
13499 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13501 return CMD_WARNING
;
13503 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13507 DEFPY (show_ip_bgp_instance_neighbor_advertised_route
,
13508 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
13509 "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]",
13513 BGP_INSTANCE_HELP_STR
13515 BGP_SAFI_WITH_LABEL_HELP_STR
13516 "Display the entries for all address families\n"
13517 "Detailed information on TCP and BGP neighbor connections\n"
13518 "Neighbor to display information about\n"
13519 "Neighbor to display information about\n"
13520 "Neighbor on BGP configured interface\n"
13521 "Display the routes advertised to a BGP neighbor\n"
13522 "Display the received routes from neighbor\n"
13523 "Display the filtered routes received from neighbor\n"
13524 "Route-map to modify the attributes\n"
13525 "Name of the route map\n"
13527 "Increase table width for longer prefixes\n")
13529 afi_t afi
= AFI_IP6
;
13530 safi_t safi
= SAFI_UNICAST
;
13531 char *rmap_name
= NULL
;
13532 char *peerstr
= NULL
;
13533 struct bgp
*bgp
= NULL
;
13535 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
13538 uint8_t show_flags
= 0;
13542 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13546 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
);
13547 if (argv_find(argv
, argc
, "ipv4", &idx
))
13548 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
);
13550 if (argv_find(argv
, argc
, "ipv6", &idx
))
13551 SET_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
);
13555 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
13557 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13560 return CMD_WARNING
;
13562 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13563 argv_find(argv
, argc
, "neighbors", &idx
);
13564 peerstr
= argv
[++idx
]->arg
;
13566 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13568 return CMD_WARNING
;
13570 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
13571 type
= bgp_show_adj_route_advertised
;
13572 else if (argv_find(argv
, argc
, "received-routes", &idx
))
13573 type
= bgp_show_adj_route_received
;
13574 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
13575 type
= bgp_show_adj_route_filtered
;
13577 if (argv_find(argv
, argc
, "route-map", &idx
))
13578 rmap_name
= argv
[++idx
]->arg
;
13581 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13584 vty_out(vty
, "{\n");
13586 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
13587 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
13588 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
13590 FOREACH_SAFI (safi
) {
13591 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13598 vty_out(vty
, ",\n");
13599 vty_out(vty
, "\"%s\":",
13600 get_afi_safi_str(afi
, safi
, true));
13602 vty_out(vty
, "\nFor address family: %s\n",
13603 get_afi_safi_str(afi
, safi
, false));
13605 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13609 FOREACH_AFI_SAFI (afi
, safi
) {
13610 if (!bgp_afi_safi_peer_exists(bgp
, afi
, safi
))
13617 vty_out(vty
, ",\n");
13618 vty_out(vty
, "\"%s\":",
13619 get_afi_safi_str(afi
, safi
, true));
13621 vty_out(vty
, "\nFor address family: %s\n",
13622 get_afi_safi_str(afi
, safi
, false));
13624 peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
,
13629 vty_out(vty
, "}\n");
13631 return CMD_SUCCESS
;
13634 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
13635 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
13636 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
13642 "Address Family modifier\n"
13643 "Detailed information on TCP and BGP neighbor connections\n"
13644 "Neighbor to display information about\n"
13645 "Neighbor to display information about\n"
13646 "Neighbor on BGP configured interface\n"
13647 "Display information received from a BGP neighbor\n"
13648 "Display the prefixlist filter\n"
13651 afi_t afi
= AFI_IP6
;
13652 safi_t safi
= SAFI_UNICAST
;
13653 char *peerstr
= NULL
;
13656 union sockunion su
;
13662 /* show [ip] bgp */
13663 if (argv_find(argv
, argc
, "ip", &idx
))
13665 /* [<ipv4|ipv6> [unicast]] */
13666 if (argv_find(argv
, argc
, "ipv4", &idx
))
13668 if (argv_find(argv
, argc
, "ipv6", &idx
))
13670 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13671 argv_find(argv
, argc
, "neighbors", &idx
);
13672 peerstr
= argv
[++idx
]->arg
;
13674 bool uj
= use_json(argc
, argv
);
13676 ret
= str2sockunion(peerstr
, &su
);
13678 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
13681 vty_out(vty
, "{}\n");
13684 "%% Malformed address or name: %s\n",
13686 return CMD_WARNING
;
13689 peer
= peer_lookup(NULL
, &su
);
13692 vty_out(vty
, "{}\n");
13694 vty_out(vty
, "No peer\n");
13695 return CMD_WARNING
;
13699 snprintf(name
, sizeof(name
), "%s.%d.%d", peer
->host
, afi
, safi
);
13700 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
13703 vty_out(vty
, "Address Family: %s\n",
13704 get_afi_safi_str(afi
, safi
, false));
13705 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
13708 vty_out(vty
, "{}\n");
13710 vty_out(vty
, "No functional output\n");
13713 return CMD_SUCCESS
;
13716 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
13717 afi_t afi
, safi_t safi
,
13718 enum bgp_show_type type
, bool use_json
)
13720 uint8_t show_flags
= 0;
13723 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13725 if (!peer
|| !peer
->afc
[afi
][safi
]) {
13727 json_object
*json_no
= NULL
;
13728 json_no
= json_object_new_object();
13729 json_object_string_add(
13730 json_no
, "warning",
13731 "No such neighbor or address family");
13732 vty_out(vty
, "%s\n",
13733 json_object_to_json_string(json_no
));
13734 json_object_free(json_no
);
13736 vty_out(vty
, "%% No such neighbor or address family\n");
13737 return CMD_WARNING
;
13740 /* labeled-unicast routes live in the unicast table */
13741 if (safi
== SAFI_LABELED_UNICAST
)
13742 safi
= SAFI_UNICAST
;
13744 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, show_flags
);
13747 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
13748 show_ip_bgp_flowspec_routes_detailed_cmd
,
13749 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
13753 BGP_INSTANCE_HELP_STR
13756 "Detailed information on flowspec entries\n"
13759 afi_t afi
= AFI_IP
;
13760 safi_t safi
= SAFI_UNICAST
;
13761 struct bgp
*bgp
= NULL
;
13763 bool uj
= use_json(argc
, argv
);
13764 uint8_t show_flags
= 0;
13768 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
13771 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13774 return CMD_WARNING
;
13776 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
,
13780 DEFUN (show_ip_bgp_neighbor_routes
,
13781 show_ip_bgp_neighbor_routes_cmd
,
13782 "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]",
13786 BGP_INSTANCE_HELP_STR
13788 BGP_SAFI_WITH_LABEL_HELP_STR
13789 "Detailed information on TCP and BGP neighbor connections\n"
13790 "Neighbor to display information about\n"
13791 "Neighbor to display information about\n"
13792 "Neighbor on BGP configured interface\n"
13793 "Display flap statistics of the routes learned from neighbor\n"
13794 "Display the dampened routes received from neighbor\n"
13795 "Display routes learned from neighbor\n"
13798 char *peerstr
= NULL
;
13799 struct bgp
*bgp
= NULL
;
13800 afi_t afi
= AFI_IP6
;
13801 safi_t safi
= SAFI_UNICAST
;
13803 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
13805 bool uj
= use_json(argc
, argv
);
13810 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
13813 return CMD_WARNING
;
13815 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13816 argv_find(argv
, argc
, "neighbors", &idx
);
13817 peerstr
= argv
[++idx
]->arg
;
13819 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
13821 return CMD_WARNING
;
13823 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
13824 sh_type
= bgp_show_type_flap_neighbor
;
13825 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
13826 sh_type
= bgp_show_type_damp_neighbor
;
13827 else if (argv_find(argv
, argc
, "routes", &idx
))
13828 sh_type
= bgp_show_type_neighbor
;
13830 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
13833 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
13835 struct bgp_distance
{
13836 /* Distance value for the IP source prefix. */
13839 /* Name of the access-list to be matched. */
13843 DEFUN (show_bgp_afi_vpn_rd_route
,
13844 show_bgp_afi_vpn_rd_route_cmd
,
13845 "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]",
13849 "Address Family modifier\n"
13850 "Display information for a route distinguisher\n"
13851 "Route Distinguisher\n"
13852 "Network in the BGP routing table to display\n"
13853 "Network in the BGP routing table to display\n"
13857 struct prefix_rd prd
;
13858 afi_t afi
= AFI_MAX
;
13861 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
13862 vty_out(vty
, "%% Malformed Address Family\n");
13863 return CMD_WARNING
;
13866 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
13868 vty_out(vty
, "%% Malformed Route Distinguisher\n");
13869 return CMD_WARNING
;
13872 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
13873 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
13876 static struct bgp_distance
*bgp_distance_new(void)
13878 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
13881 static void bgp_distance_free(struct bgp_distance
*bdistance
)
13883 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
13886 int bgp_distance_set(uint8_t distance
, const char *ip_str
,
13887 const char *access_list_str
, afi_t afi
, safi_t safi
,
13888 char *errmsg
, size_t errmsg_len
)
13892 struct bgp_dest
*dest
;
13893 struct bgp_distance
*bdistance
;
13895 ret
= str2prefix(ip_str
, &p
);
13897 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13898 return CMD_WARNING_CONFIG_FAILED
;
13901 /* Get BGP distance node. */
13902 dest
= bgp_node_get(bgp_distance_table
[afi
][safi
], &p
);
13903 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13905 bgp_dest_unlock_node(dest
);
13907 bdistance
= bgp_distance_new();
13908 bgp_dest_set_bgp_distance_info(dest
, bdistance
);
13911 /* Set distance value. */
13912 bdistance
->distance
= distance
;
13914 /* Reset access-list configuration. */
13915 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13916 if (access_list_str
)
13917 bdistance
->access_list
=
13918 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
13920 return CMD_SUCCESS
;
13923 int bgp_distance_unset(uint8_t distance
, const char *ip_str
,
13924 const char *access_list_str
, afi_t afi
, safi_t safi
,
13925 char *errmsg
, size_t errmsg_len
)
13929 struct bgp_dest
*dest
;
13930 struct bgp_distance
*bdistance
;
13932 ret
= str2prefix(ip_str
, &p
);
13934 snprintf(errmsg
, errmsg_len
, "Malformed prefix\n");
13935 return CMD_WARNING_CONFIG_FAILED
;
13938 dest
= bgp_node_lookup(bgp_distance_table
[afi
][safi
], &p
);
13940 snprintf(errmsg
, errmsg_len
, "Can't find specified prefix\n");
13941 return CMD_WARNING_CONFIG_FAILED
;
13944 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13946 if (bdistance
->distance
!= distance
) {
13947 snprintf(errmsg
, errmsg_len
,
13948 "Distance does not match configured\n");
13949 return CMD_WARNING_CONFIG_FAILED
;
13952 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
13953 bgp_distance_free(bdistance
);
13955 bgp_dest_set_bgp_path_info(dest
, NULL
);
13956 bgp_dest_unlock_node(dest
);
13957 bgp_dest_unlock_node(dest
);
13959 return CMD_SUCCESS
;
13962 /* Apply BGP information to distance method. */
13963 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
13964 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
13966 struct bgp_dest
*dest
;
13967 struct prefix q
= {0};
13969 struct bgp_distance
*bdistance
;
13970 struct access_list
*alist
;
13971 struct bgp_static
*bgp_static
;
13976 peer
= pinfo
->peer
;
13978 if (pinfo
->attr
->distance
)
13979 return pinfo
->attr
->distance
;
13981 /* Check source address.
13982 * Note: for aggregate route, peer can have unspec af type.
13984 if (pinfo
->sub_type
!= BGP_ROUTE_AGGREGATE
13985 && !sockunion2hostprefix(&peer
->su
, &q
))
13988 dest
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
13990 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
13991 bgp_dest_unlock_node(dest
);
13993 if (bdistance
->access_list
) {
13994 alist
= access_list_lookup(afi
, bdistance
->access_list
);
13996 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
13997 return bdistance
->distance
;
13999 return bdistance
->distance
;
14002 /* Backdoor check. */
14003 dest
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
14005 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14006 bgp_dest_unlock_node(dest
);
14008 if (bgp_static
->backdoor
) {
14009 if (bgp
->distance_local
[afi
][safi
])
14010 return bgp
->distance_local
[afi
][safi
];
14012 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14016 if (peer
->sort
== BGP_PEER_EBGP
) {
14017 if (bgp
->distance_ebgp
[afi
][safi
])
14018 return bgp
->distance_ebgp
[afi
][safi
];
14019 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
14020 } else if (peer
->sort
== BGP_PEER_IBGP
) {
14021 if (bgp
->distance_ibgp
[afi
][safi
])
14022 return bgp
->distance_ibgp
[afi
][safi
];
14023 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14025 if (bgp
->distance_local
[afi
][safi
])
14026 return bgp
->distance_local
[afi
][safi
];
14027 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
14031 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14032 * we should tell ZEBRA update the routes for a specific
14033 * AFI/SAFI to reflect changes in RIB.
14035 void bgp_announce_routes_distance_update(struct bgp
*bgp
, afi_t update_afi
,
14036 safi_t update_safi
)
14041 FOREACH_AFI_SAFI (afi
, safi
) {
14042 if (!bgp_fibupd_safi(safi
))
14045 if (afi
!= update_afi
&& safi
!= update_safi
)
14048 if (BGP_DEBUG(zebra
, ZEBRA
))
14050 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14051 __func__
, afi
, safi
);
14052 bgp_zebra_announce_table(bgp
, afi
, safi
);
14056 DEFUN_YANG(bgp_distance
, bgp_distance_cmd
,
14057 "distance bgp (1-255) (1-255) (1-255)",
14058 "Define an administrative distance\n"
14060 "Distance for routes external to the AS\n"
14061 "Distance for routes internal to the AS\n"
14062 "Distance for local routes\n")
14064 int idx_number
= 2;
14065 int idx_number_2
= 3;
14066 int idx_number_3
= 4;
14069 char xpath
[XPATH_MAXLEN
];
14071 afi
= bgp_node_afi(vty
);
14072 safi
= bgp_node_safi(vty
);
14075 xpath
, sizeof(xpath
),
14076 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14077 yang_afi_safi_value2identity(afi
, safi
),
14078 bgp_afi_safi_get_container_str(afi
, safi
));
14079 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[idx_number
]->arg
);
14081 xpath
, sizeof(xpath
),
14082 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14083 yang_afi_safi_value2identity(afi
, safi
),
14084 bgp_afi_safi_get_container_str(afi
, safi
));
14085 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14086 argv
[idx_number_2
]->arg
);
14088 xpath
, sizeof(xpath
),
14089 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14090 yang_afi_safi_value2identity(afi
, safi
),
14091 bgp_afi_safi_get_container_str(afi
, safi
));
14093 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
14094 argv
[idx_number_3
]->arg
);
14096 return nb_cli_apply_changes(vty
, NULL
);
14099 DEFUN_YANG(no_bgp_distance
, no_bgp_distance_cmd
,
14100 "no distance bgp [(1-255) (1-255) (1-255)]",
14102 "Define an administrative distance\n"
14104 "Distance for routes external to the AS\n"
14105 "Distance for routes internal to the AS\n"
14106 "Distance for local routes\n")
14110 char xpath
[XPATH_MAXLEN
];
14112 afi
= bgp_node_afi(vty
);
14113 safi
= bgp_node_safi(vty
);
14116 xpath
, sizeof(xpath
),
14117 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14118 yang_afi_safi_value2identity(afi
, safi
),
14119 bgp_afi_safi_get_container_str(afi
, safi
));
14120 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14122 xpath
, sizeof(xpath
),
14123 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14124 yang_afi_safi_value2identity(afi
, safi
),
14125 bgp_afi_safi_get_container_str(afi
, safi
));
14126 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14128 xpath
, sizeof(xpath
),
14129 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14130 yang_afi_safi_value2identity(afi
, safi
),
14131 bgp_afi_safi_get_container_str(afi
, safi
));
14133 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, NULL
);
14135 return nb_cli_apply_changes(vty
, NULL
);
14138 void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty
*vty
,
14139 struct lyd_node
*dnode
,
14140 bool show_defaults
)
14142 uint8_t distance_ebgp
, distance_ibgp
, distance_local
;
14144 distance_ebgp
= yang_dnode_get_uint8(dnode
, "./external");
14145 distance_ibgp
= yang_dnode_get_uint8(dnode
, "./internal");
14146 distance_local
= yang_dnode_get_uint8(dnode
, "./local");
14148 vty_out(vty
, " distance bgp %d %d %d\n", distance_ebgp
, distance_ibgp
,
14152 DEFPY_YANG(bgp_distance_source
,
14153 bgp_distance_source_cmd
,
14154 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
14156 "Define an administrative distance\n"
14158 "IPv4 source prefix\n"
14159 "IPv6 source prefix\n"
14160 "Access list name\n")
14164 char xpath
[XPATH_MAXLEN
];
14166 afi
= bgp_node_afi(vty
);
14167 safi
= bgp_node_safi(vty
);
14170 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, NULL
);
14171 nb_cli_enqueue_change(vty
, "./distance", NB_OP_MODIFY
,
14174 nb_cli_enqueue_change(vty
,
14175 "./access-list-policy-export",
14176 NB_OP_CREATE
, acl
);
14178 nb_cli_enqueue_change(vty
,
14179 "./access-list-policy-export",
14180 NB_OP_DESTROY
, NULL
);
14182 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
14186 xpath
, sizeof(xpath
),
14187 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14188 yang_afi_safi_value2identity(afi
, safi
),
14189 bgp_afi_safi_get_container_str(afi
, safi
), prefix_str
);
14191 return nb_cli_apply_changes(vty
, xpath
);
14194 void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14195 struct vty
*vty
, struct lyd_node
*dnode
, bool show_defaults
)
14197 vty_out(vty
, " distance %d %s %s\n",
14198 yang_dnode_get_uint8(dnode
, "./distance"),
14199 yang_dnode_get_string(dnode
, "./prefix"),
14200 (yang_dnode_exists(dnode
, "./access-list-policy-export"))
14201 ? yang_dnode_get_string(dnode
,
14202 "./access-list-policy-export")
14207 bgp_dampening
, bgp_dampening_cmd
,
14208 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14210 "BGP Specific commands\n"
14211 "Enable route-flap dampening\n"
14212 "Half-life time for the penalty\n"
14213 "Value to start reusing a route\n"
14214 "Value to start suppressing a route\n"
14215 "Maximum duration to suppress a stable route\n")
14219 char xpath
[XPATH_MAXLEN
];
14221 afi
= bgp_node_afi(vty
);
14222 safi
= bgp_node_safi(vty
);
14225 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
14227 nb_cli_enqueue_change(vty
, "./reach-decay",
14228 NB_OP_MODIFY
, halflife_str
);
14229 nb_cli_enqueue_change(vty
, "./reuse-above",
14230 NB_OP_MODIFY
, reuse_str
);
14231 nb_cli_enqueue_change(vty
, "./suppress-above",
14232 NB_OP_MODIFY
, suppress_str
);
14233 nb_cli_enqueue_change(vty
, "./unreach-decay",
14234 NB_OP_MODIFY
, max_suppress_str
);
14236 nb_cli_enqueue_change(vty
, "./reach-decay",
14237 NB_OP_MODIFY
, halflife_str
);
14240 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "false");
14244 xpath
, sizeof(xpath
),
14245 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14246 yang_afi_safi_value2identity(afi
, safi
),
14247 bgp_afi_safi_get_container_str(afi
, safi
));
14249 return nb_cli_apply_changes(vty
, xpath
);
14252 void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty
*vty
,
14253 struct lyd_node
*dnode
,
14254 bool show_defaults
)
14256 if (!yang_dnode_get_bool(dnode
, "./enable"))
14259 int half
= DEFAULT_HALF_LIFE
* 60;
14260 int reuse
= DEFAULT_REUSE
;
14261 int suppress
= DEFAULT_SUPPRESS
;
14264 half
= yang_dnode_get_uint8(dnode
, "../reach-decay");
14265 reuse
= yang_dnode_get_uint16(dnode
, "../reuse-above");
14266 suppress
= yang_dnode_get_uint16(dnode
, "../suppress-above");
14267 max
= yang_dnode_get_uint8(dnode
, "../unreach-decay");
14269 if (half
== DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14270 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14271 vty_out(vty
, " bgp dampening\n");
14272 else if (half
!= DEFAULT_HALF_LIFE
* 60 && reuse
== DEFAULT_REUSE
14273 && suppress
== DEFAULT_SUPPRESS
&& max
== half
* 4)
14274 vty_out(vty
, " bgp dampening %u\n", half
);
14276 vty_out(vty
, " bgp dampening %u %d %d %d\n", half
, reuse
,
14280 /* Display specified route of BGP table. */
14281 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
14282 const char *ip_str
, afi_t afi
, safi_t safi
,
14283 struct prefix_rd
*prd
, int prefix_check
)
14286 struct prefix match
;
14287 struct bgp_dest
*dest
;
14288 struct bgp_dest
*rm
;
14289 struct bgp_path_info
*pi
;
14290 struct bgp_path_info
*pi_temp
;
14292 struct bgp_table
*table
;
14294 /* BGP structure lookup. */
14296 bgp
= bgp_lookup_by_name(view_name
);
14298 vty_out(vty
, "%% Can't find BGP instance %s\n",
14300 return CMD_WARNING
;
14303 bgp
= bgp_get_default();
14305 vty_out(vty
, "%% No BGP process is configured\n");
14306 return CMD_WARNING
;
14310 /* Check IP address argument. */
14311 ret
= str2prefix(ip_str
, &match
);
14313 vty_out(vty
, "%% address is malformed\n");
14314 return CMD_WARNING
;
14317 match
.family
= afi2family(afi
);
14319 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
14320 || (safi
== SAFI_EVPN
)) {
14321 for (dest
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); dest
;
14322 dest
= bgp_route_next(dest
)) {
14323 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14325 if (prd
&& memcmp(dest_p
->u
.val
, prd
->val
, 8) != 0)
14327 table
= bgp_dest_get_bgp_table_info(dest
);
14330 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
14333 const struct prefix
*rm_p
= bgp_dest_get_prefix(dest
);
14336 || rm_p
->prefixlen
== match
.prefixlen
) {
14337 pi
= bgp_dest_get_bgp_path_info(rm
);
14339 if (pi
->extra
&& pi
->extra
->damp_info
) {
14340 pi_temp
= pi
->next
;
14341 bgp_damp_info_free(
14342 &pi
->extra
->damp_info
,
14343 &bgp
->damp
[afi
][safi
],
14351 bgp_dest_unlock_node(rm
);
14354 if ((dest
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
14356 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
14359 || dest_p
->prefixlen
== match
.prefixlen
) {
14360 pi
= bgp_dest_get_bgp_path_info(dest
);
14362 if (pi
->extra
&& pi
->extra
->damp_info
) {
14363 pi_temp
= pi
->next
;
14364 struct bgp_damp_info
*bdi
=
14365 pi
->extra
->damp_info
;
14366 if (bdi
->lastrecord
14367 == BGP_RECORD_UPDATE
) {
14368 bgp_aggregate_increment(
14379 bgp_damp_info_free(
14380 &pi
->extra
->damp_info
,
14381 &bgp
->damp
[afi
][safi
],
14389 bgp_dest_unlock_node(dest
);
14393 return CMD_SUCCESS
;
14396 DEFUN (clear_ip_bgp_dampening
,
14397 clear_ip_bgp_dampening_cmd
,
14398 "clear ip bgp dampening",
14402 "Clear route flap dampening information\n")
14404 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
14405 bgp_damp_info_clean(bgp
, &bgp
->damp
[AFI_IP
][SAFI_UNICAST
], AFI_IP
,
14407 return CMD_SUCCESS
;
14410 DEFUN (clear_ip_bgp_dampening_prefix
,
14411 clear_ip_bgp_dampening_prefix_cmd
,
14412 "clear ip bgp dampening A.B.C.D/M",
14416 "Clear route flap dampening information\n"
14419 int idx_ipv4_prefixlen
= 4;
14420 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
14421 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
14424 DEFUN (clear_ip_bgp_dampening_address
,
14425 clear_ip_bgp_dampening_address_cmd
,
14426 "clear ip bgp dampening A.B.C.D",
14430 "Clear route flap dampening information\n"
14431 "Network to clear damping information\n")
14434 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
14435 SAFI_UNICAST
, NULL
, 0);
14438 DEFUN (clear_ip_bgp_dampening_address_mask
,
14439 clear_ip_bgp_dampening_address_mask_cmd
,
14440 "clear ip bgp dampening A.B.C.D A.B.C.D",
14444 "Clear route flap dampening information\n"
14445 "Network to clear damping information\n"
14449 int idx_ipv4_2
= 5;
14451 char prefix_str
[BUFSIZ
];
14453 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
14454 prefix_str
, sizeof(prefix_str
));
14456 vty_out(vty
, "%% Inconsistent address and mask\n");
14457 return CMD_WARNING
;
14460 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
14464 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
14466 struct vty
*vty
= arg
;
14467 struct peer
*peer
= bucket
->data
;
14468 char buf
[SU_ADDRSTRLEN
];
14470 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
14471 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
14474 DEFUN (show_bgp_listeners
,
14475 show_bgp_listeners_cmd
,
14476 "show bgp listeners",
14479 "Display Listen Sockets and who created them\n")
14481 bgp_dump_listener_info(vty
);
14483 return CMD_SUCCESS
;
14486 DEFUN (show_bgp_peerhash
,
14487 show_bgp_peerhash_cmd
,
14488 "show bgp peerhash",
14491 "Display information about the BGP peerhash\n")
14493 struct list
*instances
= bm
->bgp
;
14494 struct listnode
*node
;
14497 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
14498 vty_out(vty
, "BGP: %s\n", bgp
->name
);
14499 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
14503 return CMD_SUCCESS
;
14506 /* also used for encap safi */
14507 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
14508 afi_t afi
, safi_t safi
)
14510 struct bgp_dest
*pdest
;
14511 struct bgp_dest
*dest
;
14512 struct bgp_table
*table
;
14513 const struct prefix
*p
;
14514 const struct prefix_rd
*prd
;
14515 struct bgp_static
*bgp_static
;
14516 mpls_label_t label
;
14517 char rdbuf
[RD_ADDRSTRLEN
];
14519 /* Network configuration. */
14520 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14521 pdest
= bgp_route_next(pdest
)) {
14522 table
= bgp_dest_get_bgp_table_info(pdest
);
14526 for (dest
= bgp_table_top(table
); dest
;
14527 dest
= bgp_route_next(dest
)) {
14528 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14529 if (bgp_static
== NULL
)
14532 p
= bgp_dest_get_prefix(dest
);
14533 prd
= (const struct prefix_rd
*)bgp_dest_get_prefix(
14536 /* "network" configuration display. */
14537 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14538 label
= decode_label(&bgp_static
->label
);
14540 vty_out(vty
, " network %pFX rd %s", p
, rdbuf
);
14541 if (safi
== SAFI_MPLS_VPN
)
14542 vty_out(vty
, " label %u", label
);
14544 if (bgp_static
->rmap
.name
)
14545 vty_out(vty
, " route-map %s",
14546 bgp_static
->rmap
.name
);
14548 if (bgp_static
->backdoor
)
14549 vty_out(vty
, " backdoor");
14551 vty_out(vty
, "\n");
14556 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
14557 afi_t afi
, safi_t safi
)
14559 struct bgp_dest
*pdest
;
14560 struct bgp_dest
*dest
;
14561 struct bgp_table
*table
;
14562 const struct prefix
*p
;
14563 const struct prefix_rd
*prd
;
14564 struct bgp_static
*bgp_static
;
14565 char buf
[PREFIX_STRLEN
* 2];
14566 char buf2
[SU_ADDRSTRLEN
];
14567 char rdbuf
[RD_ADDRSTRLEN
];
14568 char esi_buf
[ESI_BYTES
];
14570 /* Network configuration. */
14571 for (pdest
= bgp_table_top(bgp
->route
[afi
][safi
]); pdest
;
14572 pdest
= bgp_route_next(pdest
)) {
14573 table
= bgp_dest_get_bgp_table_info(pdest
);
14577 for (dest
= bgp_table_top(table
); dest
;
14578 dest
= bgp_route_next(dest
)) {
14579 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14580 if (bgp_static
== NULL
)
14583 char *macrouter
= NULL
;
14585 if (bgp_static
->router_mac
)
14586 macrouter
= prefix_mac2str(
14587 bgp_static
->router_mac
, NULL
, 0);
14588 if (bgp_static
->eth_s_id
)
14589 esi_to_str(bgp_static
->eth_s_id
,
14590 esi_buf
, sizeof(esi_buf
));
14591 p
= bgp_dest_get_prefix(dest
);
14592 prd
= (struct prefix_rd
*)bgp_dest_get_prefix(pdest
);
14594 /* "network" configuration display. */
14595 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
14596 if (p
->u
.prefix_evpn
.route_type
== 5) {
14597 char local_buf
[PREFIX_STRLEN
];
14598 uint8_t family
= is_evpn_prefix_ipaddr_v4((
14599 struct prefix_evpn
*)p
)
14603 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
14604 local_buf
, PREFIX_STRLEN
);
14605 snprintf(buf
, sizeof(buf
), "%s/%u", local_buf
,
14606 p
->u
.prefix_evpn
.prefix_addr
14607 .ip_prefix_length
);
14609 prefix2str(p
, buf
, sizeof(buf
));
14612 if (bgp_static
->gatewayIp
.family
== AF_INET
14613 || bgp_static
->gatewayIp
.family
== AF_INET6
)
14614 inet_ntop(bgp_static
->gatewayIp
.family
,
14615 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
14618 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
14620 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
14621 decode_label(&bgp_static
->label
), esi_buf
, buf2
,
14624 XFREE(MTYPE_TMP
, macrouter
);
14629 /* Configuration of static route announcement and aggregate
14631 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14634 struct bgp_dest
*dest
;
14635 const struct prefix
*p
;
14636 struct bgp_static
*bgp_static
;
14637 struct bgp_aggregate
*bgp_aggregate
;
14639 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
14640 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
14644 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
14645 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
14649 /* Network configuration. */
14650 for (dest
= bgp_table_top(bgp
->route
[afi
][safi
]); dest
;
14651 dest
= bgp_route_next(dest
)) {
14652 bgp_static
= bgp_dest_get_bgp_static_info(dest
);
14653 if (bgp_static
== NULL
)
14656 p
= bgp_dest_get_prefix(dest
);
14658 vty_out(vty
, " network %pFX", p
);
14660 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
14661 vty_out(vty
, " label-index %u",
14662 bgp_static
->label_index
);
14664 if (bgp_static
->rmap
.name
)
14665 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
14667 if (bgp_static
->backdoor
)
14668 vty_out(vty
, " backdoor");
14670 vty_out(vty
, "\n");
14673 /* Aggregate-address configuration. */
14674 for (dest
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); dest
;
14675 dest
= bgp_route_next(dest
)) {
14676 bgp_aggregate
= bgp_dest_get_bgp_aggregate_info(dest
);
14677 if (bgp_aggregate
== NULL
)
14680 p
= bgp_dest_get_prefix(dest
);
14682 vty_out(vty
, " aggregate-address %pFX", p
);
14684 if (bgp_aggregate
->as_set
)
14685 vty_out(vty
, " as-set");
14687 if (bgp_aggregate
->summary_only
)
14688 vty_out(vty
, " summary-only");
14690 if (bgp_aggregate
->rmap
.name
)
14691 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
14693 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
14694 vty_out(vty
, " origin %s",
14695 bgp_origin2str(bgp_aggregate
->origin
));
14697 if (bgp_aggregate
->match_med
)
14698 vty_out(vty
, " matching-MED-only");
14700 if (bgp_aggregate
->suppress_map_name
)
14701 vty_out(vty
, " suppress-map %s",
14702 bgp_aggregate
->suppress_map_name
);
14704 vty_out(vty
, "\n");
14708 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
14711 struct bgp_dest
*dest
;
14712 struct bgp_distance
*bdistance
;
14714 /* Distance configuration. */
14715 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
14716 && bgp
->distance_local
[afi
][safi
]
14717 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
14718 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
14719 || bgp
->distance_local
[afi
][safi
]
14720 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
14721 vty_out(vty
, " distance bgp %d %d %d\n",
14722 bgp
->distance_ebgp
[afi
][safi
],
14723 bgp
->distance_ibgp
[afi
][safi
],
14724 bgp
->distance_local
[afi
][safi
]);
14727 for (dest
= bgp_table_top(bgp_distance_table
[afi
][safi
]); dest
;
14728 dest
= bgp_route_next(dest
)) {
14729 bdistance
= bgp_dest_get_bgp_distance_info(dest
);
14730 if (bdistance
!= NULL
)
14731 vty_out(vty
, " distance %d %pBD %s\n",
14732 bdistance
->distance
, dest
,
14733 bdistance
->access_list
? bdistance
->access_list
14738 /* Allocate routing table structure and install commands. */
14739 void bgp_route_init(void)
14744 /* Init BGP distance table. */
14745 FOREACH_AFI_SAFI (afi
, safi
)
14746 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
14748 /* IPv4 BGP commands. */
14749 install_element(BGP_NODE
, &bgp_table_map_cmd
);
14750 install_element(BGP_NODE
, &bgp_network_cmd
);
14751 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
14753 install_element(BGP_NODE
, &aggregate_addressv4_cmd
);
14755 /* IPv4 unicast configuration. */
14756 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
14757 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
14758 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
14760 install_element(BGP_IPV4_NODE
, &aggregate_addressv4_cmd
);
14762 /* IPv4 multicast configuration. */
14763 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
14764 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
14765 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
14766 install_element(BGP_IPV4M_NODE
, &aggregate_addressv4_cmd
);
14768 /* IPv4 labeled-unicast configuration. */
14769 install_element(BGP_IPV4L_NODE
, &bgp_network_cmd
);
14770 install_element(BGP_IPV4L_NODE
, &aggregate_addressv4_cmd
);
14772 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
14773 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
14774 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
14775 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
14776 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
14777 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
14778 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
14779 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
14781 install_element(VIEW_NODE
,
14782 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
14783 install_element(VIEW_NODE
,
14784 &show_ip_bgp_instance_neighbor_bestpath_route_cmd
);
14785 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
14786 install_element(VIEW_NODE
,
14787 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
14788 #ifdef KEEP_OLD_VPN_COMMANDS
14789 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
14790 #endif /* KEEP_OLD_VPN_COMMANDS */
14791 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
14792 install_element(VIEW_NODE
,
14793 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
14795 /* BGP dampening clear commands */
14796 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
14797 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
14799 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
14800 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
14803 install_element(ENABLE_NODE
,
14804 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
14805 #ifdef KEEP_OLD_VPN_COMMANDS
14806 install_element(ENABLE_NODE
,
14807 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
14808 #endif /* KEEP_OLD_VPN_COMMANDS */
14810 /* New config IPv6 BGP commands. */
14811 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
14812 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
14813 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
14815 install_element(BGP_IPV6_NODE
, &aggregate_addressv6_cmd
);
14817 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
14819 /* IPv6 labeled unicast address family. */
14820 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
14821 install_element(BGP_IPV6L_NODE
, &aggregate_addressv6_cmd
);
14823 install_element(BGP_NODE
, &bgp_distance_cmd
);
14824 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
14825 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
14826 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
14827 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
14828 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
14829 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
14830 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
14831 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
14832 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
14833 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
14834 install_element(BGP_IPV6_NODE
, &bgp_distance_source_cmd
);
14835 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
14836 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
14837 install_element(BGP_IPV6M_NODE
, &bgp_distance_source_cmd
);
14839 /* BGP dampening */
14840 install_element(BGP_NODE
, &bgp_dampening_cmd
);
14841 install_element(BGP_IPV4_NODE
, &bgp_dampening_cmd
);
14842 install_element(BGP_IPV4M_NODE
, &bgp_dampening_cmd
);
14843 install_element(BGP_IPV4L_NODE
, &bgp_dampening_cmd
);
14844 install_element(BGP_IPV6_NODE
, &bgp_dampening_cmd
);
14845 install_element(BGP_IPV6M_NODE
, &bgp_dampening_cmd
);
14846 install_element(BGP_IPV6L_NODE
, &bgp_dampening_cmd
);
14848 /* Large Communities */
14849 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
14850 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
14852 /* show bgp ipv4 flowspec detailed */
14853 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
14855 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
14856 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
14859 void bgp_route_finish(void)
14864 FOREACH_AFI_SAFI (afi
, safi
) {
14865 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
14866 bgp_distance_table
[afi
][safi
] = NULL
;