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"
75 #include "bgpd/rfapi/rfapi_backend.h"
76 #include "bgpd/rfapi/vnc_import_bgp.h"
77 #include "bgpd/rfapi/vnc_export_bgp.h"
79 #include "bgpd/bgp_encap_types.h"
80 #include "bgpd/bgp_encap_tlv.h"
81 #include "bgpd/bgp_evpn.h"
82 #include "bgpd/bgp_evpn_vty.h"
83 #include "bgpd/bgp_flowspec.h"
84 #include "bgpd/bgp_flowspec_util.h"
85 #include "bgpd/bgp_pbr.h"
87 #ifndef VTYSH_EXTRACT_PL
88 #include "bgpd/bgp_route_clippy.c"
91 /* Extern from bgp_dump.c */
92 extern const char *bgp_origin_str
[];
93 extern const char *bgp_origin_long_str
[];
94 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
96 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
97 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
98 static const struct message bgp_pmsi_tnltype_str
[] = {
99 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
100 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
101 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
102 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
103 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
104 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
105 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
106 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
110 #define VRFID_NONE_STR "-"
112 DEFINE_HOOK(bgp_process
,
113 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
114 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
115 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
118 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
119 safi_t safi
, const struct prefix
*p
,
120 struct prefix_rd
*prd
)
123 struct bgp_node
*prn
= NULL
;
127 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
128 || (safi
== SAFI_EVPN
)) {
129 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
131 if (!bgp_node_has_bgp_path_info_data(prn
))
132 bgp_node_set_bgp_table_info(
133 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
135 bgp_unlock_node(prn
);
136 table
= bgp_node_get_bgp_table_info(prn
);
139 rn
= bgp_node_get(table
, p
);
141 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
142 || (safi
== SAFI_EVPN
))
148 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
149 safi_t safi
, const struct prefix
*p
,
150 struct prefix_rd
*prd
)
153 struct bgp_node
*prn
= NULL
;
158 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
159 || (safi
== SAFI_EVPN
)) {
160 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
164 if (!bgp_node_has_bgp_path_info_data(prn
)) {
165 bgp_unlock_node(prn
);
169 table
= bgp_node_get_bgp_table_info(prn
);
172 rn
= bgp_node_lookup(table
, p
);
177 /* Allocate bgp_path_info_extra */
178 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
180 struct bgp_path_info_extra
*new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
182 sizeof(struct bgp_path_info_extra
));
183 new->label
[0] = MPLS_INVALID_LABEL
;
185 new->bgp_fs_pbr
= NULL
;
186 new->bgp_fs_iprule
= NULL
;
190 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
192 struct bgp_path_info_extra
*e
;
194 if (!extra
|| !*extra
)
199 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
204 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
207 /* FIXME: since multiple e may have the same e->parent
208 * and e->parent->net is holding a refcount for each
209 * of them, we need to do some fudging here.
211 * WARNING: if bpi->net->lock drops to 0, bpi may be
212 * freed as well (because bpi->net was holding the
213 * last reference to bpi) => write after free!
217 bpi
= bgp_path_info_lock(bpi
);
218 refcount
= bpi
->net
->lock
- 1;
219 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
222 bgp_path_info_unlock(bpi
);
224 bgp_path_info_unlock(e
->parent
);
229 bgp_unlock(e
->bgp_orig
);
231 if ((*extra
)->bgp_fs_iprule
)
232 list_delete(&((*extra
)->bgp_fs_iprule
));
233 if ((*extra
)->bgp_fs_pbr
)
234 list_delete(&((*extra
)->bgp_fs_pbr
));
235 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
238 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
239 * allocated if required.
241 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
244 pi
->extra
= bgp_path_info_extra_new();
248 /* Free bgp route information. */
249 static void bgp_path_info_free(struct bgp_path_info
*path
)
251 bgp_attr_unintern(&path
->attr
);
253 bgp_unlink_nexthop(path
);
254 bgp_path_info_extra_free(&path
->extra
);
255 bgp_path_info_mpath_free(&path
->mpath
);
257 bgp_addpath_free_info_data(&path
->tx_addpath
,
258 &path
->net
->tx_addpath
);
260 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
262 XFREE(MTYPE_BGP_ROUTE
, path
);
265 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
271 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
273 assert(path
&& path
->lock
> 0);
276 if (path
->lock
== 0) {
278 zlog_debug ("%s: unlocked and freeing", __func__
);
279 zlog_backtrace (LOG_DEBUG
);
281 bgp_path_info_free(path
);
288 zlog_debug ("%s: unlocked to 1", __func__
);
289 zlog_backtrace (LOG_DEBUG
);
296 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
297 static int bgp_node_set_defer_flag(struct bgp_node
*rn
, bool delete)
300 struct bgp_path_info
*old_pi
, *nextpi
;
301 bool set_flag
= false;
302 struct bgp
*bgp
= NULL
;
303 struct bgp_table
*table
= NULL
;
307 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
308 * then the route selection is deferred
310 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
313 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
314 if (BGP_DEBUG(update
, UPDATE_OUT
))
316 "Route %pRN is in workqueue and being processed, not deferred.",
322 table
= bgp_node_table(rn
);
329 for (old_pi
= bgp_node_get_bgp_path_info(rn
);
330 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
331 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
334 /* Route selection is deferred if there is a stale path which
335 * which indicates peer is in restart mode
337 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
338 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
341 /* If the peer is graceful restart capable and peer is
342 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
345 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
346 && BGP_PEER_RESTARTING_MODE(peer
)
348 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
356 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
359 if (set_flag
&& table
) {
360 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
361 SET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
362 if (rn
->rt_node
== NULL
)
363 rn
->rt_node
= listnode_add(
364 bgp
->gr_info
[afi
][safi
].route_list
, rn
);
365 if (BGP_DEBUG(update
, UPDATE_OUT
))
366 zlog_debug("DEFER route %pRN, rn %p, node %p",
367 rn
, rn
, rn
->rt_node
);
374 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
376 struct bgp_path_info
*top
;
378 top
= bgp_node_get_bgp_path_info(rn
);
384 bgp_node_set_bgp_path_info(rn
, pi
);
386 bgp_path_info_lock(pi
);
388 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
389 bgp_node_set_defer_flag(rn
, false);
392 /* Do the actual removal of info from RIB, for use by bgp_process
393 completion callback *only* */
394 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
397 pi
->next
->prev
= pi
->prev
;
399 pi
->prev
->next
= pi
->next
;
401 bgp_node_set_bgp_path_info(rn
, pi
->next
);
403 bgp_path_info_mpath_dequeue(pi
);
404 bgp_path_info_unlock(pi
);
408 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
410 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
411 /* set of previous already took care of pcount */
412 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
415 /* undo the effects of a previous call to bgp_path_info_delete; typically
416 called when a route is deleted and then quickly re-added before the
417 deletion has been processed */
418 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
420 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
421 /* unset of previous already took care of pcount */
422 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
425 /* Adjust pcount as required */
426 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
428 struct bgp_table
*table
;
430 assert(rn
&& bgp_node_table(rn
));
431 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
433 table
= bgp_node_table(rn
);
435 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
438 if (!BGP_PATH_COUNTABLE(pi
)
439 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
441 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
443 /* slight hack, but more robust against errors. */
444 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
445 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
447 flog_err(EC_LIB_DEVELOPMENT
,
448 "Asked to decrement 0 prefix count for peer");
449 } else if (BGP_PATH_COUNTABLE(pi
)
450 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
451 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
452 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
456 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
457 struct bgp_path_info
*pi2
)
459 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
462 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
463 * This is here primarily to keep prefix-count in check.
465 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
468 SET_FLAG(pi
->flags
, flag
);
470 /* early bath if we know it's not a flag that changes countability state
472 if (!CHECK_FLAG(flag
,
473 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
476 bgp_pcount_adjust(rn
, pi
);
479 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
482 UNSET_FLAG(pi
->flags
, flag
);
484 /* early bath if we know it's not a flag that changes countability state
486 if (!CHECK_FLAG(flag
,
487 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
490 bgp_pcount_adjust(rn
, pi
);
493 /* Get MED value. If MED value is missing and "bgp bestpath
494 missing-as-worst" is specified, treat it as the worst value. */
495 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
497 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
500 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_MISSING_AS_WORST
))
507 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
509 if (pi
->addpath_rx_id
)
510 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
513 sprintf(buf
, "path %s", pi
->peer
->host
);
516 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
518 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
519 struct bgp_path_info
*exist
, int *paths_eq
,
520 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
521 char *pfx_buf
, afi_t afi
, safi_t safi
,
522 enum bgp_path_selection_reason
*reason
)
524 struct attr
*newattr
, *existattr
;
525 bgp_peer_sort_t new_sort
;
526 bgp_peer_sort_t exist_sort
;
532 uint32_t exist_weight
;
533 uint32_t newm
, existm
;
534 struct in_addr new_id
;
535 struct in_addr exist_id
;
538 int internal_as_route
;
541 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
542 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
544 uint32_t exist_mm_seq
;
551 *reason
= bgp_path_selection_none
;
553 zlog_debug("%s: new is NULL", pfx_buf
);
558 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
561 *reason
= bgp_path_selection_first
;
563 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
569 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
570 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
571 pfx_buf
, new_buf
, new->flags
, exist_buf
,
576 existattr
= exist
->attr
;
578 /* For EVPN routes, we cannot just go by local vs remote, we have to
579 * look at the MAC mobility sequence number, if present.
581 if (safi
== SAFI_EVPN
) {
582 /* This is an error condition described in RFC 7432 Section
584 * states that in this scenario "the PE MUST alert the operator"
586 * does not state what other action to take. In order to provide
588 * consistency in this scenario we are going to prefer the path
592 if (newattr
->sticky
!= existattr
->sticky
) {
594 prefix2str(bgp_node_get_prefix(new->net
),
597 * PREFIX2STR_BUFFER
);
598 bgp_path_info_path_with_addpath_rx_str(new,
600 bgp_path_info_path_with_addpath_rx_str(
604 if (newattr
->sticky
&& !existattr
->sticky
) {
605 *reason
= bgp_path_selection_evpn_sticky_mac
;
608 "%s: %s wins over %s due to sticky MAC flag",
609 pfx_buf
, new_buf
, exist_buf
);
613 if (!newattr
->sticky
&& existattr
->sticky
) {
614 *reason
= bgp_path_selection_evpn_sticky_mac
;
617 "%s: %s loses to %s due to sticky MAC flag",
618 pfx_buf
, new_buf
, exist_buf
);
623 new_mm_seq
= mac_mobility_seqnum(newattr
);
624 exist_mm_seq
= mac_mobility_seqnum(existattr
);
626 if (new_mm_seq
> exist_mm_seq
) {
627 *reason
= bgp_path_selection_evpn_seq
;
630 "%s: %s wins over %s due to MM seq %u > %u",
631 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
636 if (new_mm_seq
< exist_mm_seq
) {
637 *reason
= bgp_path_selection_evpn_seq
;
640 "%s: %s loses to %s due to MM seq %u < %u",
641 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
647 * if sequence numbers are the same path with the lowest IP
650 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
652 *reason
= bgp_path_selection_evpn_lower_ip
;
655 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
656 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
657 inet_ntoa(new->attr
->nexthop
));
661 *reason
= bgp_path_selection_evpn_lower_ip
;
664 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
665 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
666 inet_ntoa(new->attr
->nexthop
));
671 /* 1. Weight check. */
672 new_weight
= newattr
->weight
;
673 exist_weight
= existattr
->weight
;
675 if (new_weight
> exist_weight
) {
676 *reason
= bgp_path_selection_weight
;
678 zlog_debug("%s: %s wins over %s due to weight %d > %d",
679 pfx_buf
, new_buf
, exist_buf
, new_weight
,
684 if (new_weight
< exist_weight
) {
685 *reason
= bgp_path_selection_weight
;
687 zlog_debug("%s: %s loses to %s due to weight %d < %d",
688 pfx_buf
, new_buf
, exist_buf
, new_weight
,
693 /* 2. Local preference check. */
694 new_pref
= exist_pref
= bgp
->default_local_pref
;
696 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
697 new_pref
= newattr
->local_pref
;
698 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
699 exist_pref
= existattr
->local_pref
;
701 if (new_pref
> exist_pref
) {
702 *reason
= bgp_path_selection_local_pref
;
705 "%s: %s wins over %s due to localpref %d > %d",
706 pfx_buf
, new_buf
, exist_buf
, new_pref
,
711 if (new_pref
< exist_pref
) {
712 *reason
= bgp_path_selection_local_pref
;
715 "%s: %s loses to %s due to localpref %d < %d",
716 pfx_buf
, new_buf
, exist_buf
, new_pref
,
721 /* 3. Local route check. We prefer:
723 * - BGP_ROUTE_AGGREGATE
724 * - BGP_ROUTE_REDISTRIBUTE
726 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
727 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
728 *reason
= bgp_path_selection_local_route
;
731 "%s: %s wins over %s due to preferred BGP_ROUTE type",
732 pfx_buf
, new_buf
, exist_buf
);
736 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
737 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
738 *reason
= bgp_path_selection_local_route
;
741 "%s: %s loses to %s due to preferred BGP_ROUTE type",
742 pfx_buf
, new_buf
, exist_buf
);
746 /* 4. AS path length check. */
747 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_IGNORE
)) {
748 int exist_hops
= aspath_count_hops(existattr
->aspath
);
749 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
751 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ASPATH_CONFED
)) {
754 aspath_hops
= aspath_count_hops(newattr
->aspath
);
755 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
757 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
758 *reason
= bgp_path_selection_confed_as_path
;
761 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
762 pfx_buf
, new_buf
, exist_buf
,
764 (exist_hops
+ exist_confeds
));
768 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
769 *reason
= bgp_path_selection_confed_as_path
;
772 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
773 pfx_buf
, new_buf
, exist_buf
,
775 (exist_hops
+ exist_confeds
));
779 int newhops
= aspath_count_hops(newattr
->aspath
);
781 if (newhops
< exist_hops
) {
782 *reason
= bgp_path_selection_as_path
;
785 "%s: %s wins over %s due to aspath hopcount %d < %d",
786 pfx_buf
, new_buf
, exist_buf
,
787 newhops
, exist_hops
);
791 if (newhops
> exist_hops
) {
792 *reason
= bgp_path_selection_as_path
;
795 "%s: %s loses to %s due to aspath hopcount %d > %d",
796 pfx_buf
, new_buf
, exist_buf
,
797 newhops
, exist_hops
);
803 /* 5. Origin check. */
804 if (newattr
->origin
< existattr
->origin
) {
805 *reason
= bgp_path_selection_origin
;
807 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
808 pfx_buf
, new_buf
, exist_buf
,
809 bgp_origin_long_str
[newattr
->origin
],
810 bgp_origin_long_str
[existattr
->origin
]);
814 if (newattr
->origin
> existattr
->origin
) {
815 *reason
= bgp_path_selection_origin
;
817 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
818 pfx_buf
, new_buf
, exist_buf
,
819 bgp_origin_long_str
[newattr
->origin
],
820 bgp_origin_long_str
[existattr
->origin
]);
825 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
826 && aspath_count_hops(existattr
->aspath
) == 0);
827 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
828 && aspath_count_confeds(existattr
->aspath
) > 0
829 && aspath_count_hops(newattr
->aspath
) == 0
830 && aspath_count_hops(existattr
->aspath
) == 0);
832 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_ALWAYS_COMPARE_MED
)
833 || (CHECK_FLAG(bgp
->flags
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
834 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
835 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
836 || internal_as_route
) {
837 new_med
= bgp_med_value(new->attr
, bgp
);
838 exist_med
= bgp_med_value(exist
->attr
, bgp
);
840 if (new_med
< exist_med
) {
841 *reason
= bgp_path_selection_med
;
844 "%s: %s wins over %s due to MED %d < %d",
845 pfx_buf
, new_buf
, exist_buf
, new_med
,
850 if (new_med
> exist_med
) {
851 *reason
= bgp_path_selection_med
;
854 "%s: %s loses to %s due to MED %d > %d",
855 pfx_buf
, new_buf
, exist_buf
, new_med
,
861 /* 7. Peer type check. */
862 new_sort
= new->peer
->sort
;
863 exist_sort
= exist
->peer
->sort
;
865 if (new_sort
== BGP_PEER_EBGP
866 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
867 *reason
= bgp_path_selection_peer
;
870 "%s: %s wins over %s due to eBGP peer > iBGP peer",
871 pfx_buf
, new_buf
, exist_buf
);
875 if (exist_sort
== BGP_PEER_EBGP
876 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
877 *reason
= bgp_path_selection_peer
;
880 "%s: %s loses to %s due to iBGP peer < eBGP peer",
881 pfx_buf
, new_buf
, exist_buf
);
885 /* 8. IGP metric check. */
889 newm
= new->extra
->igpmetric
;
891 existm
= exist
->extra
->igpmetric
;
896 "%s: %s wins over %s due to IGP metric %d < %d",
897 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
904 "%s: %s loses to %s due to IGP metric %d > %d",
905 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
909 /* 9. Same IGP metric. Compare the cluster list length as
910 representative of IGP hops metric. Rewrite the metric value
911 pair (newm, existm) with the cluster list length. Prefer the
912 path with smaller cluster list length. */
913 if (newm
== existm
) {
914 if (peer_sort_lookup(new->peer
) == BGP_PEER_IBGP
915 && peer_sort_lookup(exist
->peer
) == BGP_PEER_IBGP
916 && (mpath_cfg
== NULL
918 mpath_cfg
->ibgp_flags
,
919 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
920 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
921 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
926 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
927 pfx_buf
, new_buf
, exist_buf
,
935 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
936 pfx_buf
, new_buf
, exist_buf
,
943 /* 10. confed-external vs. confed-internal */
944 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
945 if (new_sort
== BGP_PEER_CONFED
946 && exist_sort
== BGP_PEER_IBGP
) {
947 *reason
= bgp_path_selection_confed
;
950 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
951 pfx_buf
, new_buf
, exist_buf
);
955 if (exist_sort
== BGP_PEER_CONFED
956 && new_sort
== BGP_PEER_IBGP
) {
957 *reason
= bgp_path_selection_confed
;
960 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
961 pfx_buf
, new_buf
, exist_buf
);
966 /* 11. Maximum path check. */
967 if (newm
== existm
) {
968 /* If one path has a label but the other does not, do not treat
969 * them as equals for multipath
971 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
973 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
976 "%s: %s and %s cannot be multipath, one has a label while the other does not",
977 pfx_buf
, new_buf
, exist_buf
);
978 } else if (CHECK_FLAG(bgp
->flags
,
979 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
982 * For the two paths, all comparison steps till IGP
984 * have succeeded - including AS_PATH hop count. Since
986 * bestpath as-path multipath-relax' knob is on, we
988 * an exact match of AS_PATH. Thus, mark the paths are
990 * That will trigger both these paths to get into the
998 "%s: %s and %s are equal via multipath-relax",
999 pfx_buf
, new_buf
, exist_buf
);
1000 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1001 if (aspath_cmp(new->attr
->aspath
,
1002 exist
->attr
->aspath
)) {
1007 "%s: %s and %s are equal via matching aspaths",
1008 pfx_buf
, new_buf
, exist_buf
);
1010 } else if (new->peer
->as
== exist
->peer
->as
) {
1015 "%s: %s and %s are equal via same remote-as",
1016 pfx_buf
, new_buf
, exist_buf
);
1020 * TODO: If unequal cost ibgp multipath is enabled we can
1021 * mark the paths as equal here instead of returning
1026 "%s: %s wins over %s after IGP metric comparison",
1027 pfx_buf
, new_buf
, exist_buf
);
1030 "%s: %s loses to %s after IGP metric comparison",
1031 pfx_buf
, new_buf
, exist_buf
);
1033 *reason
= bgp_path_selection_igp_metric
;
1037 /* 12. If both paths are external, prefer the path that was received
1038 first (the oldest one). This step minimizes route-flap, since a
1039 newer path won't displace an older one, even if it was the
1040 preferred route based on the additional decision criteria below. */
1041 if (!CHECK_FLAG(bgp
->flags
, BGP_FLAG_COMPARE_ROUTER_ID
)
1042 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1043 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1044 *reason
= bgp_path_selection_older
;
1047 "%s: %s wins over %s due to oldest external",
1048 pfx_buf
, new_buf
, exist_buf
);
1052 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1053 *reason
= bgp_path_selection_older
;
1056 "%s: %s loses to %s due to oldest external",
1057 pfx_buf
, new_buf
, exist_buf
);
1062 /* 13. Router-ID comparision. */
1063 /* If one of the paths is "stale", the corresponding peer router-id will
1064 * be 0 and would always win over the other path. If originator id is
1065 * used for the comparision, it will decide which path is better.
1067 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1068 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1070 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1071 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1072 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1074 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1076 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1077 *reason
= bgp_path_selection_router_id
;
1080 "%s: %s wins over %s due to Router-ID comparison",
1081 pfx_buf
, new_buf
, exist_buf
);
1085 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1086 *reason
= bgp_path_selection_router_id
;
1089 "%s: %s loses to %s due to Router-ID comparison",
1090 pfx_buf
, new_buf
, exist_buf
);
1094 /* 14. Cluster length comparision. */
1095 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1096 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1098 if (new_cluster
< exist_cluster
) {
1099 *reason
= bgp_path_selection_cluster_length
;
1102 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1103 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1108 if (new_cluster
> exist_cluster
) {
1109 *reason
= bgp_path_selection_cluster_length
;
1112 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1113 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1118 /* 15. Neighbor address comparision. */
1119 /* Do this only if neither path is "stale" as stale paths do not have
1120 * valid peer information (as the connection may or may not be up).
1122 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1123 *reason
= bgp_path_selection_stale
;
1126 "%s: %s wins over %s due to latter path being STALE",
1127 pfx_buf
, new_buf
, exist_buf
);
1131 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1132 *reason
= bgp_path_selection_stale
;
1135 "%s: %s loses to %s due to former path being STALE",
1136 pfx_buf
, new_buf
, exist_buf
);
1140 /* locally configured routes to advertise do not have su_remote */
1141 if (new->peer
->su_remote
== NULL
) {
1142 *reason
= bgp_path_selection_local_configured
;
1145 if (exist
->peer
->su_remote
== NULL
) {
1146 *reason
= bgp_path_selection_local_configured
;
1150 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1153 *reason
= bgp_path_selection_neighbor_ip
;
1156 "%s: %s loses to %s due to Neighor IP comparison",
1157 pfx_buf
, new_buf
, exist_buf
);
1162 *reason
= bgp_path_selection_neighbor_ip
;
1165 "%s: %s wins over %s due to Neighor IP comparison",
1166 pfx_buf
, new_buf
, exist_buf
);
1170 *reason
= bgp_path_selection_default
;
1172 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1173 pfx_buf
, new_buf
, exist_buf
);
1178 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1179 * is preferred, or 0 if they are the same (usually will only occur if
1180 * multipath is enabled
1181 * This version is compatible with */
1182 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1183 struct bgp_path_info
*exist
, char *pfx_buf
,
1184 afi_t afi
, safi_t safi
,
1185 enum bgp_path_selection_reason
*reason
)
1189 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1203 static enum filter_type
bgp_input_filter(struct peer
*peer
,
1204 const struct prefix
*p
,
1205 struct attr
*attr
, afi_t afi
,
1208 struct bgp_filter
*filter
;
1210 filter
= &peer
->filter
[afi
][safi
];
1212 #define FILTER_EXIST_WARN(F, f, filter) \
1213 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1214 zlog_debug("%s: Could not find configured input %s-list %s!", \
1215 peer->host, #f, F##_IN_NAME(filter));
1217 if (DISTRIBUTE_IN_NAME(filter
)) {
1218 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1220 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1224 if (PREFIX_LIST_IN_NAME(filter
)) {
1225 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1227 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1231 if (FILTER_LIST_IN_NAME(filter
)) {
1232 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1234 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1239 return FILTER_PERMIT
;
1240 #undef FILTER_EXIST_WARN
1243 static enum filter_type
bgp_output_filter(struct peer
*peer
,
1244 const struct prefix
*p
,
1245 struct attr
*attr
, afi_t afi
,
1248 struct bgp_filter
*filter
;
1250 filter
= &peer
->filter
[afi
][safi
];
1252 #define FILTER_EXIST_WARN(F, f, filter) \
1253 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1254 zlog_debug("%s: Could not find configured output %s-list %s!", \
1255 peer->host, #f, F##_OUT_NAME(filter));
1257 if (DISTRIBUTE_OUT_NAME(filter
)) {
1258 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1260 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1264 if (PREFIX_LIST_OUT_NAME(filter
)) {
1265 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1267 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1272 if (FILTER_LIST_OUT_NAME(filter
)) {
1273 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1275 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1280 return FILTER_PERMIT
;
1281 #undef FILTER_EXIST_WARN
1284 /* If community attribute includes no_export then return 1. */
1285 static bool bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1287 if (attr
->community
) {
1288 /* NO_ADVERTISE check. */
1289 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1292 /* NO_EXPORT check. */
1293 if (peer
->sort
== BGP_PEER_EBGP
1294 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1297 /* NO_EXPORT_SUBCONFED check. */
1298 if (peer
->sort
== BGP_PEER_EBGP
1299 || peer
->sort
== BGP_PEER_CONFED
)
1300 if (community_include(attr
->community
,
1301 COMMUNITY_NO_EXPORT_SUBCONFED
))
1307 /* Route reflection loop check. */
1308 static bool bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1310 struct in_addr cluster_id
;
1312 if (attr
->cluster
) {
1313 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1314 cluster_id
= peer
->bgp
->cluster_id
;
1316 cluster_id
= peer
->bgp
->router_id
;
1318 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1324 static int bgp_input_modifier(struct peer
*peer
, const struct prefix
*p
,
1325 struct attr
*attr
, afi_t afi
, safi_t safi
,
1326 const char *rmap_name
, mpls_label_t
*label
,
1327 uint32_t num_labels
, struct bgp_node
*rn
)
1329 struct bgp_filter
*filter
;
1330 struct bgp_path_info rmap_path
= { 0 };
1331 struct bgp_path_info_extra extra
= { 0 };
1332 route_map_result_t ret
;
1333 struct route_map
*rmap
= NULL
;
1335 filter
= &peer
->filter
[afi
][safi
];
1337 /* Apply default weight value. */
1338 if (peer
->weight
[afi
][safi
])
1339 attr
->weight
= peer
->weight
[afi
][safi
];
1342 rmap
= route_map_lookup_by_name(rmap_name
);
1347 if (ROUTE_MAP_IN_NAME(filter
)) {
1348 rmap
= ROUTE_MAP_IN(filter
);
1355 /* Route map apply. */
1357 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1358 /* Duplicate current value to new strucutre for modification. */
1359 rmap_path
.peer
= peer
;
1360 rmap_path
.attr
= attr
;
1361 rmap_path
.extra
= &extra
;
1364 extra
.num_labels
= num_labels
;
1365 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1366 memcpy(extra
.label
, label
,
1367 num_labels
* sizeof(mpls_label_t
));
1369 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1371 /* Apply BGP route map to the attribute. */
1372 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1374 peer
->rmap_type
= 0;
1376 if (ret
== RMAP_DENYMATCH
)
1382 static int bgp_output_modifier(struct peer
*peer
, const struct prefix
*p
,
1383 struct attr
*attr
, afi_t afi
, safi_t safi
,
1384 const char *rmap_name
)
1386 struct bgp_path_info rmap_path
;
1387 route_map_result_t ret
;
1388 struct route_map
*rmap
= NULL
;
1392 * So if we get to this point and have no rmap_name
1393 * we want to just show the output as it currently
1399 /* Apply default weight value. */
1400 if (peer
->weight
[afi
][safi
])
1401 attr
->weight
= peer
->weight
[afi
][safi
];
1403 rmap
= route_map_lookup_by_name(rmap_name
);
1406 * If we have a route map name and we do not find
1407 * the routemap that means we have an implicit
1413 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1414 /* Route map apply. */
1415 /* Duplicate current value to new strucutre for modification. */
1416 rmap_path
.peer
= peer
;
1417 rmap_path
.attr
= attr
;
1419 rmap_type
= peer
->rmap_type
;
1420 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1422 /* Apply BGP route map to the attribute. */
1423 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1425 peer
->rmap_type
= rmap_type
;
1427 if (ret
== RMAP_DENYMATCH
)
1429 * caller has multiple error paths with bgp_attr_flush()
1436 /* If this is an EBGP peer with remove-private-AS */
1437 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1438 struct peer
*peer
, struct attr
*attr
)
1440 if (peer
->sort
== BGP_PEER_EBGP
1441 && (peer_af_flag_check(peer
, afi
, safi
,
1442 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1443 || peer_af_flag_check(peer
, afi
, safi
,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1445 || peer_af_flag_check(peer
, afi
, safi
,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1447 || peer_af_flag_check(peer
, afi
, safi
,
1448 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1449 // Take action on the entire aspath
1450 if (peer_af_flag_check(peer
, afi
, safi
,
1451 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1452 || peer_af_flag_check(peer
, afi
, safi
,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1454 if (peer_af_flag_check(
1456 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1457 attr
->aspath
= aspath_replace_private_asns(
1458 attr
->aspath
, bgp
->as
, peer
->as
);
1460 // The entire aspath consists of private ASNs so create
1462 else if (aspath_private_as_check(attr
->aspath
))
1463 attr
->aspath
= aspath_empty_get();
1465 // There are some public and some private ASNs, remove
1468 attr
->aspath
= aspath_remove_private_asns(
1469 attr
->aspath
, peer
->as
);
1472 // 'all' was not specified so the entire aspath must be private
1474 // for us to do anything
1475 else if (aspath_private_as_check(attr
->aspath
)) {
1476 if (peer_af_flag_check(
1478 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1479 attr
->aspath
= aspath_replace_private_asns(
1480 attr
->aspath
, bgp
->as
, peer
->as
);
1482 attr
->aspath
= aspath_empty_get();
1487 /* If this is an EBGP peer with as-override */
1488 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1489 struct peer
*peer
, struct attr
*attr
)
1491 if (peer
->sort
== BGP_PEER_EBGP
1492 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1493 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1494 attr
->aspath
= aspath_replace_specific_asn(
1495 attr
->aspath
, peer
->as
, bgp
->as
);
1499 void bgp_attr_add_gshut_community(struct attr
*attr
)
1501 struct community
*old
;
1502 struct community
*new;
1503 struct community
*merge
;
1504 struct community
*gshut
;
1506 old
= attr
->community
;
1507 gshut
= community_str2com("graceful-shutdown");
1512 merge
= community_merge(community_dup(old
), gshut
);
1514 if (old
->refcnt
== 0)
1515 community_free(&old
);
1517 new = community_uniq_sort(merge
);
1518 community_free(&merge
);
1520 new = community_dup(gshut
);
1523 community_free(&gshut
);
1524 attr
->community
= new;
1525 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1527 /* When we add the graceful-shutdown community we must also
1528 * lower the local-preference */
1529 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1530 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1534 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1536 if (family
== AF_INET
) {
1537 attr
->nexthop
.s_addr
= INADDR_ANY
;
1538 attr
->mp_nexthop_global_in
.s_addr
= INADDR_ANY
;
1540 if (family
== AF_INET6
)
1541 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1542 if (family
== AF_EVPN
)
1543 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1546 bool subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1547 struct update_subgroup
*subgrp
,
1548 const struct prefix
*p
, struct attr
*attr
)
1550 struct bgp_filter
*filter
;
1553 struct peer
*onlypeer
;
1555 struct attr
*piattr
;
1556 char buf
[PREFIX_STRLEN
];
1557 route_map_result_t ret
;
1562 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1564 if (DISABLE_BGP_ANNOUNCE
)
1567 afi
= SUBGRP_AFI(subgrp
);
1568 safi
= SUBGRP_SAFI(subgrp
);
1569 peer
= SUBGRP_PEER(subgrp
);
1571 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1572 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1575 filter
= &peer
->filter
[afi
][safi
];
1576 bgp
= SUBGRP_INST(subgrp
);
1577 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1581 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1582 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1583 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1586 * direct and direct_ext type routes originate internally even
1587 * though they can have peer pointers that reference other
1590 prefix2str(p
, buf
, PREFIX_STRLEN
);
1591 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1597 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1598 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1599 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1600 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1602 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1607 /* With addpath we may be asked to TX all kinds of paths so make sure
1609 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1610 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1611 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1615 /* If this is not the bestpath then check to see if there is an enabled
1617 * feature that requires us to advertise it */
1618 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1619 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1624 /* Aggregate-address suppress check. */
1625 if (pi
->extra
&& pi
->extra
->suppress
)
1626 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1631 * If we are doing VRF 2 VRF leaking via the import
1632 * statement, we want to prevent the route going
1633 * off box as that the RT and RD created are localy
1634 * significant and globaly useless.
1636 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1637 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1640 /* If it's labeled safi, make sure the route has a valid label. */
1641 if (safi
== SAFI_LABELED_UNICAST
) {
1642 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1643 if (!bgp_is_valid_label(&label
)) {
1644 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1645 zlog_debug("u%" PRIu64
":s%" PRIu64
1646 " %s/%d is filtered - no label (%p)",
1647 subgrp
->update_group
->id
, subgrp
->id
,
1648 inet_ntop(p
->family
, &p
->u
.prefix
,
1649 buf
, SU_ADDRSTRLEN
),
1650 p
->prefixlen
, &label
);
1655 /* Do not send back route to sender. */
1656 if (onlypeer
&& from
== onlypeer
) {
1660 /* Do not send the default route in the BGP table if the neighbor is
1661 * configured for default-originate */
1662 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1663 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1664 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1666 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1670 /* Transparency check. */
1671 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1672 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1677 /* If community is not disabled check the no-export and local. */
1678 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1679 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1681 "subgrpannouncecheck: community filter check fail");
1685 /* If the attribute has originator-id and it is same as remote
1687 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1688 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1689 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1691 "%s [Update:SEND] %s originator-id is same as "
1694 prefix2str(p
, buf
, sizeof(buf
)));
1698 /* ORF prefix-list filter check */
1699 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1700 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1701 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1702 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1703 if (peer
->orf_plist
[afi
][safi
]) {
1704 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1706 if (bgp_debug_update(NULL
, p
,
1707 subgrp
->update_group
, 0))
1709 "%s [Update:SEND] %s is filtered via ORF",
1717 /* Output filter check. */
1718 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1719 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1720 zlog_debug("%s [Update:SEND] %s is filtered",
1721 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1725 /* AS path loop check. */
1726 if (onlypeer
&& onlypeer
->as_path_loop_detection
1727 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1728 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1730 "%s [Update:SEND] suppress announcement to peer AS %u "
1731 "that is part of AS path.",
1732 onlypeer
->host
, onlypeer
->as
);
1736 /* If we're a CONFED we need to loop check the CONFED ID too */
1737 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1738 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1739 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1741 "%s [Update:SEND] suppress announcement to peer AS %u"
1743 peer
->host
, bgp
->confed_id
);
1748 /* Route-Reflect check. */
1749 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1754 /* IBGP reflection check. */
1755 if (reflect
&& !samepeer_safe
) {
1756 /* A route from a Client peer. */
1757 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1758 PEER_FLAG_REFLECTOR_CLIENT
)) {
1759 /* Reflect to all the Non-Client peers and also to the
1760 Client peers other than the originator. Originator
1762 is already done. So there is noting to do. */
1763 /* no bgp client-to-client reflection check. */
1764 if (CHECK_FLAG(bgp
->flags
,
1765 BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1766 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1767 PEER_FLAG_REFLECTOR_CLIENT
))
1770 /* A route from a Non-client peer. Reflect to all other
1772 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1773 PEER_FLAG_REFLECTOR_CLIENT
))
1778 /* For modify attribute, copy it to temporary structure. */
1781 /* If local-preference is not set. */
1782 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1783 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1784 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1785 attr
->local_pref
= bgp
->default_local_pref
;
1788 /* If originator-id is not set and the route is to be reflected,
1789 set the originator id */
1791 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1792 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1793 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1796 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1798 if (peer
->sort
== BGP_PEER_EBGP
1799 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1800 if (from
!= bgp
->peer_self
&& !transparent
1801 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1802 PEER_FLAG_MED_UNCHANGED
))
1804 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1807 /* Since the nexthop attribute can vary per peer, it is not explicitly
1809 * in announce check, only certain flags and length (or number of
1811 * -- for IPv6/MP_REACH) are set here in order to guide the update
1813 * code in setting the nexthop(s) on a per peer basis in
1815 * Typically, the source nexthop in the attribute is preserved but in
1817 * scenarios where we know it will always be overwritten, we reset the
1818 * nexthop to "0" in an attempt to achieve better Update packing. An
1819 * example of this is when a prefix from each of 2 IBGP peers needs to
1821 * announced to an EBGP peer (and they have the same attributes barring
1825 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1827 #define NEXTHOP_IS_V6 \
1828 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1829 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1830 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1831 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1833 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1835 * the peer (group) is configured to receive link-local nexthop
1837 * and it is available in the prefix OR we're not reflecting the route,
1838 * link-local nexthop address is valid and
1839 * the peer (group) to whom we're going to announce is on a shared
1841 * and this is either a self-originated route or the peer is EBGP.
1842 * By checking if nexthop LL address is valid we are sure that
1843 * we do not announce LL address as `::`.
1845 if (NEXTHOP_IS_V6
) {
1846 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1847 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1848 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1849 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1851 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1852 && peer
->shared_network
1853 && (from
== bgp
->peer_self
1854 || peer
->sort
== BGP_PEER_EBGP
))) {
1855 attr
->mp_nexthop_len
=
1856 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1859 /* Clear off link-local nexthop in source, whenever it is not
1861 * ensure more prefixes share the same attribute for
1864 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1865 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1866 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1869 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1870 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1872 /* Route map & unsuppress-map apply. */
1873 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1874 struct bgp_path_info rmap_path
= {0};
1875 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1876 struct attr dummy_attr
= {0};
1878 /* Fill temp path_info */
1879 prep_for_rmap_apply(&rmap_path
, &dummy_rmap_path_extra
,
1880 rn
, pi
, peer
, attr
);
1882 /* don't confuse inbound and outbound setting */
1883 RESET_FLAG(attr
->rmap_change_flags
);
1886 * The route reflector is not allowed to modify the attributes
1887 * of the reflected IBGP routes unless explicitly allowed.
1889 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1890 && !CHECK_FLAG(bgp
->flags
,
1891 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1893 rmap_path
.attr
= &dummy_attr
;
1896 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1898 if (pi
->extra
&& pi
->extra
->suppress
)
1899 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1900 RMAP_BGP
, &rmap_path
);
1902 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1903 RMAP_BGP
, &rmap_path
);
1905 peer
->rmap_type
= 0;
1907 if (ret
== RMAP_DENYMATCH
) {
1908 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1909 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1910 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1912 bgp_attr_flush(attr
);
1917 /* RFC 8212 to prevent route leaks.
1918 * This specification intends to improve this situation by requiring the
1919 * explicit configuration of both BGP Import and Export Policies for any
1920 * External BGP (EBGP) session such as customers, peers, or
1921 * confederation boundaries for all enabled address families. Through
1922 * codification of the aforementioned requirement, operators will
1923 * benefit from consistent behavior across different BGP
1926 if (peer
->bgp
->ebgp_requires_policy
1927 == DEFAULT_EBGP_POLICY_ENABLED
)
1928 if (!bgp_outbound_policy_exists(peer
, filter
))
1931 /* draft-ietf-idr-deprecate-as-set-confed-set
1932 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1933 * Eventually, This document (if approved) updates RFC 4271
1934 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1935 * and obsoletes RFC 6472.
1937 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
1938 if (aspath_check_as_sets(attr
->aspath
))
1941 /* Codification of AS 0 Processing */
1942 if (aspath_check_as_zero(attr
->aspath
))
1945 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1946 if (peer
->sort
== BGP_PEER_IBGP
1947 || peer
->sort
== BGP_PEER_CONFED
) {
1948 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1949 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1951 bgp_attr_add_gshut_community(attr
);
1955 /* After route-map has been applied, we check to see if the nexthop to
1956 * be carried in the attribute (that is used for the announcement) can
1957 * be cleared off or not. We do this in all cases where we would be
1958 * setting the nexthop to "ourselves". For IPv6, we only need to
1960 * the global nexthop here; the link-local nexthop would have been
1962 * already, and if not, it is required by the update formation code.
1963 * Also see earlier comments in this function.
1966 * If route-map has performed some operation on the nexthop or the peer
1967 * configuration says to pass it unchanged, we cannot reset the nexthop
1968 * here, so only attempt to do it if these aren't true. Note that the
1969 * route-map handler itself might have cleared the nexthop, if for
1971 * it is configured as 'peer-address'.
1973 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1974 piattr
->rmap_change_flags
)
1976 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1977 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1978 /* We can reset the nexthop, if setting (or forcing) it to
1980 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1981 PEER_FLAG_NEXTHOP_SELF
)
1982 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1983 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1985 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1986 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1987 subgroup_announce_reset_nhop(
1988 (peer_cap_enhe(peer
, afi
, safi
)
1992 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1993 /* Can also reset the nexthop if announcing to EBGP, but
1995 * no peer in the subgroup is on a shared subnet.
1996 * Note: 3rd party nexthop currently implemented for
1999 if ((p
->family
== AF_INET
) &&
2000 (!bgp_subgrp_multiaccess_check_v4(
2003 subgroup_announce_reset_nhop(
2004 (peer_cap_enhe(peer
, afi
, safi
)
2009 if ((p
->family
== AF_INET6
) &&
2010 (!bgp_subgrp_multiaccess_check_v6(
2011 piattr
->mp_nexthop_global
,
2013 subgroup_announce_reset_nhop(
2014 (peer_cap_enhe(peer
, afi
, safi
)
2021 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2023 * This flag is used for leaked vpn-vrf routes
2025 int family
= p
->family
;
2027 if (peer_cap_enhe(peer
, afi
, safi
))
2030 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2032 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2033 __func__
, family2str(family
));
2034 subgroup_announce_reset_nhop(family
, attr
);
2038 /* If IPv6/MP and nexthop does not have any override and happens
2040 * be a link-local address, reset it so that we don't pass along
2042 * source's link-local IPv6 address to recipients who may not be
2044 * the same interface.
2046 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2047 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
2048 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2054 static int bgp_route_select_timer_expire(struct thread
*thread
)
2056 struct afi_safi_info
*info
;
2061 info
= THREAD_ARG(thread
);
2066 if (BGP_DEBUG(update
, UPDATE_OUT
))
2067 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2070 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2072 XFREE(MTYPE_TMP
, info
);
2074 /* Best path selection */
2075 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2078 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
2079 struct bgp_maxpaths_cfg
*mpath_cfg
,
2080 struct bgp_path_info_pair
*result
, afi_t afi
,
2083 struct bgp_path_info
*new_select
;
2084 struct bgp_path_info
*old_select
;
2085 struct bgp_path_info
*pi
;
2086 struct bgp_path_info
*pi1
;
2087 struct bgp_path_info
*pi2
;
2088 struct bgp_path_info
*nextpi
= NULL
;
2089 int paths_eq
, do_mpath
, debug
;
2090 struct list mp_list
;
2091 char pfx_buf
[PREFIX2STR_BUFFER
];
2092 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2094 bgp_mp_list_init(&mp_list
);
2096 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2098 debug
= bgp_debug_bestpath(rn
);
2101 prefix2str(bgp_node_get_prefix(rn
), pfx_buf
, sizeof(pfx_buf
));
2103 rn
->reason
= bgp_path_selection_none
;
2104 /* bgp deterministic-med */
2106 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)) {
2108 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2109 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2111 bgp_path_info_unset_flag(rn
, pi1
,
2112 BGP_PATH_DMED_SELECTED
);
2114 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2116 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2118 if (BGP_PATH_HOLDDOWN(pi1
))
2120 if (pi1
->peer
!= bgp
->peer_self
)
2121 if (pi1
->peer
->status
!= Established
)
2126 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2127 if (CHECK_FLAG(pi2
->flags
,
2128 BGP_PATH_DMED_CHECK
))
2130 if (BGP_PATH_HOLDDOWN(pi2
))
2132 if (pi2
->peer
!= bgp
->peer_self
2135 PEER_STATUS_NSF_WAIT
))
2136 if (pi2
->peer
->status
2140 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2142 && !aspath_cmp_left_confed(
2147 if (bgp_path_info_cmp(
2148 bgp
, pi2
, new_select
,
2149 &paths_eq
, mpath_cfg
, debug
,
2152 bgp_path_info_unset_flag(
2154 BGP_PATH_DMED_SELECTED
);
2158 bgp_path_info_set_flag(
2159 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2162 bgp_path_info_set_flag(rn
, new_select
,
2163 BGP_PATH_DMED_CHECK
);
2164 bgp_path_info_set_flag(rn
, new_select
,
2165 BGP_PATH_DMED_SELECTED
);
2168 bgp_path_info_path_with_addpath_rx_str(
2169 new_select
, path_buf
);
2170 zlog_debug("%s: %s is the bestpath from AS %u",
2172 aspath_get_first_as(
2173 new_select
->attr
->aspath
));
2178 /* Check old selected route and new selected route. */
2181 for (pi
= bgp_node_get_bgp_path_info(rn
);
2182 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2183 enum bgp_path_selection_reason reason
;
2185 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2188 if (BGP_PATH_HOLDDOWN(pi
)) {
2189 /* reap REMOVED routes, if needs be
2190 * selected route must stay for a while longer though
2192 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2193 && (pi
!= old_select
))
2194 bgp_path_info_reap(rn
, pi
);
2197 zlog_debug("%s: pi %p in holddown", __func__
,
2203 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2204 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2205 if (pi
->peer
->status
!= Established
) {
2209 "%s: pi %p non self peer %s not estab state",
2210 __func__
, pi
, pi
->peer
->host
);
2215 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DETERMINISTIC_MED
)
2216 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2217 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2219 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2223 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2225 reason
= rn
->reason
;
2226 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2227 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2228 if (new_select
== NULL
&&
2229 reason
!= bgp_path_selection_none
)
2230 rn
->reason
= reason
;
2235 /* Now that we know which path is the bestpath see if any of the other
2237 * qualify as multipaths
2241 bgp_path_info_path_with_addpath_rx_str(new_select
,
2244 sprintf(path_buf
, "NONE");
2246 "%s: After path selection, newbest is %s oldbest was %s",
2248 old_select
? old_select
->peer
->host
: "NONE");
2251 if (do_mpath
&& new_select
) {
2252 for (pi
= bgp_node_get_bgp_path_info(rn
);
2253 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2256 bgp_path_info_path_with_addpath_rx_str(
2259 if (pi
== new_select
) {
2262 "%s: %s is the bestpath, add to the multipath list",
2264 bgp_mp_list_add(&mp_list
, pi
);
2268 if (BGP_PATH_HOLDDOWN(pi
))
2271 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2272 && !CHECK_FLAG(pi
->peer
->sflags
,
2273 PEER_STATUS_NSF_WAIT
))
2274 if (pi
->peer
->status
!= Established
)
2277 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2280 "%s: %s has the same nexthop as the bestpath, skip it",
2285 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2286 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2292 "%s: %s is equivalent to the bestpath, add to the multipath list",
2294 bgp_mp_list_add(&mp_list
, pi
);
2299 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2301 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2302 bgp_mp_list_clear(&mp_list
);
2304 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2306 result
->old
= old_select
;
2307 result
->new = new_select
;
2313 * A new route/change in bestpath of an existing route. Evaluate the path
2314 * for advertisement to the subgroup.
2316 void subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2317 struct bgp_path_info
*selected
,
2318 struct bgp_node
*rn
,
2319 uint32_t addpath_tx_id
)
2321 const struct prefix
*p
;
2322 struct peer
*onlypeer
;
2327 p
= bgp_node_get_prefix(rn
);
2328 afi
= SUBGRP_AFI(subgrp
);
2329 safi
= SUBGRP_SAFI(subgrp
);
2330 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2333 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2334 char buf_prefix
[PREFIX_STRLEN
];
2335 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2336 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2340 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2341 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2342 PEER_STATUS_ORF_WAIT_REFRESH
))
2345 memset(&attr
, 0, sizeof(struct attr
));
2346 /* It's initialized in bgp_announce_check() */
2348 /* Announcement to the subgroup. If the route is filtered withdraw it.
2351 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2352 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2354 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2358 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2360 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2365 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2366 * This is called at the end of route processing.
2368 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2370 struct bgp_path_info
*pi
;
2372 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2373 if (BGP_PATH_HOLDDOWN(pi
))
2375 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2376 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2381 * Has the route changed from the RIB's perspective? This is invoked only
2382 * if the route selection returns the same best route as earlier - to
2383 * determine if we need to update zebra or not.
2385 bool bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2386 struct bgp_path_info
*selected
)
2388 struct bgp_path_info
*mpinfo
;
2390 /* If this is multipath, check all selected paths for any nexthop
2391 * change or attribute change. Some attribute changes (e.g., community)
2392 * aren't of relevance to the RIB, but we'll update zebra to ensure
2393 * we handle the case of BGP nexthop change. This is the behavior
2394 * when the best path has an attribute change anyway.
2396 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2397 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2401 * If this is multipath, check all selected paths for any nexthop change
2403 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2404 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2405 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2406 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2410 /* Nothing has changed from the RIB's perspective. */
2414 struct bgp_process_queue
{
2416 STAILQ_HEAD(, bgp_node
) pqueue
;
2417 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2419 unsigned int queued
;
2423 * old_select = The old best path
2424 * new_select = the new best path
2426 * if (!old_select && new_select)
2427 * We are sending new information on.
2429 * if (old_select && new_select) {
2430 * if (new_select != old_select)
2431 * We have a new best path send a change
2433 * We've received a update with new attributes that needs
2437 * if (old_select && !new_select)
2438 * We have no eligible route that we can announce or the rn
2441 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2442 afi_t afi
, safi_t safi
)
2444 struct bgp_path_info
*new_select
;
2445 struct bgp_path_info
*old_select
;
2446 struct bgp_path_info_pair old_and_new
;
2449 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2451 debug
= bgp_debug_bestpath(rn
);
2454 "%s: bgp delete in progress, ignoring event, p=%pRN",
2458 /* Is it end of initial update? (after startup) */
2460 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2461 sizeof(bgp
->update_delay_zebra_resume_time
));
2463 bgp
->main_zebra_update_hold
= 0;
2464 FOREACH_AFI_SAFI (afi
, safi
) {
2465 if (bgp_fibupd_safi(safi
))
2466 bgp_zebra_announce_table(bgp
, afi
, safi
);
2468 bgp
->main_peers_update_hold
= 0;
2470 bgp_start_routeadv(bgp
);
2474 const struct prefix
*p
= bgp_node_get_prefix(rn
);
2476 debug
= bgp_debug_bestpath(rn
);
2478 zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__
, rn
,
2479 afi2str(afi
), safi2str(safi
));
2481 /* The best path calculation for the route is deferred if
2482 * BGP_NODE_SELECT_DEFER is set
2484 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2485 if (BGP_DEBUG(update
, UPDATE_OUT
))
2486 zlog_debug("SELECT_DEFER flag set for route %p", rn
);
2490 /* Best path selection. */
2491 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2493 old_select
= old_and_new
.old
;
2494 new_select
= old_and_new
.new;
2496 /* Do we need to allocate or free labels?
2497 * Right now, since we only deal with per-prefix labels, it is not
2498 * necessary to do this upon changes to best path. Exceptions:
2499 * - label index has changed -> recalculate resulting label
2500 * - path_info sub_type changed -> switch to/from implicit-null
2501 * - no valid label (due to removed static label binding) -> get new one
2503 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2506 || bgp_label_index_differs(new_select
, old_select
)
2507 || new_select
->sub_type
!= old_select
->sub_type
2508 || !bgp_is_valid_label(&rn
->local_label
)) {
2509 /* Enforced penultimate hop popping:
2510 * implicit-null for local routes, aggregate
2511 * and redistributed routes
2513 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2514 || new_select
->sub_type
2515 == BGP_ROUTE_AGGREGATE
2516 || new_select
->sub_type
2517 == BGP_ROUTE_REDISTRIBUTE
) {
2520 BGP_NODE_REGISTERED_FOR_LABEL
))
2521 bgp_unregister_for_label(rn
);
2522 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2524 bgp_set_valid_label(&rn
->local_label
);
2526 bgp_register_for_label(rn
, new_select
);
2528 } else if (CHECK_FLAG(rn
->flags
,
2529 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2530 bgp_unregister_for_label(rn
);
2532 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2533 bgp_unregister_for_label(rn
);
2538 "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
2539 __func__
, rn
, afi2str(afi
), safi2str(safi
),
2540 old_select
, new_select
);
2542 /* If best route remains the same and this is not due to user-initiated
2543 * clear, see exactly what needs to be done.
2545 if (old_select
&& old_select
== new_select
2546 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2547 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2548 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2549 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2551 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2552 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2554 if (bgp_fibupd_safi(safi
)
2555 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2557 if (new_select
->type
== ZEBRA_ROUTE_BGP
2558 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2559 || new_select
->sub_type
2560 == BGP_ROUTE_IMPORTED
))
2562 bgp_zebra_announce(rn
, p
, old_select
,
2566 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2567 bgp_zebra_clear_route_change_flags(rn
);
2569 /* If there is a change of interest to peers, reannounce the
2571 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2572 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2573 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2575 /* unicast routes must also be annouced to
2576 * labeled-unicast update-groups */
2577 if (safi
== SAFI_UNICAST
)
2578 group_announce_route(bgp
, afi
,
2579 SAFI_LABELED_UNICAST
, rn
,
2582 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2583 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2586 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2590 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2592 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2594 /* bestpath has changed; bump version */
2595 if (old_select
|| new_select
) {
2596 bgp_bump_version(rn
);
2598 if (!bgp
->t_rmap_def_originate_eval
) {
2602 update_group_refresh_default_originate_route_map
,
2603 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2604 &bgp
->t_rmap_def_originate_eval
);
2609 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2612 zlog_debug("%s: setting SELECTED flag", __func__
);
2613 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2614 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2615 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2619 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2620 if (old_select
!= new_select
) {
2622 vnc_import_bgp_exterior_del_route(bgp
, p
,
2624 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2627 vnc_import_bgp_exterior_add_route(bgp
, p
,
2629 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2635 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2637 /* unicast routes must also be annouced to labeled-unicast update-groups
2639 if (safi
== SAFI_UNICAST
)
2640 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2644 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2645 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2646 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2647 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2648 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2649 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2651 /* if this is an evpn imported type-5 prefix,
2652 * we need to withdraw the route first to clear
2653 * the nh neigh and the RMAC entry.
2656 is_route_parent_evpn(old_select
))
2657 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2659 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2661 /* Withdraw the route from the kernel. */
2662 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2663 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2664 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2665 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2667 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2671 /* advertise/withdraw type-5 routes */
2672 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2673 const struct prefix
*p
= bgp_node_get_prefix(rn
);
2675 if (advertise_type5_routes(bgp
, afi
) &&
2677 is_route_injectable_into_evpn(new_select
)) {
2679 /* apply the route-map */
2680 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2681 route_map_result_t ret
;
2682 struct bgp_path_info rmap_path
;
2683 struct bgp_path_info_extra rmap_path_extra
;
2684 struct attr dummy_attr
;
2686 dummy_attr
= *new_select
->attr
;
2688 /* Fill temp path_info */
2689 prep_for_rmap_apply(
2690 &rmap_path
, &rmap_path_extra
,
2691 rn
, new_select
, new_select
->peer
,
2694 RESET_FLAG(dummy_attr
.rmap_change_flags
);
2696 ret
= route_map_apply(
2697 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2698 p
, RMAP_BGP
, &rmap_path
);
2699 if (ret
== RMAP_DENYMATCH
) {
2700 bgp_attr_flush(&dummy_attr
);
2701 bgp_evpn_withdraw_type5_route(
2704 bgp_evpn_advertise_type5_route(
2705 bgp
, p
, &dummy_attr
,
2708 bgp_evpn_advertise_type5_route(bgp
, p
,
2713 } else if (advertise_type5_routes(bgp
, afi
) &&
2715 is_route_injectable_into_evpn(old_select
))
2716 bgp_evpn_withdraw_type5_route(bgp
, p
, afi
, safi
);
2719 /* Clear any route change flags. */
2720 bgp_zebra_clear_route_change_flags(rn
);
2722 /* Reap old select bgp_path_info, if it has been removed */
2723 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2724 bgp_path_info_reap(rn
, old_select
);
2726 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2730 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2731 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2733 struct bgp_node
*rn
;
2735 struct afi_safi_info
*thread_info
;
2736 struct listnode
*node
= NULL
, *nnode
= NULL
;
2738 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2739 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2741 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2742 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2743 get_afi_safi_str(afi
, safi
, false),
2744 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2747 /* Process the route list */
2748 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2750 rn
= listgetdata(node
);
2752 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2755 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2756 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
2757 bgp_process_main_one(bgp
, rn
, afi
, safi
);
2759 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2765 /* Send EOR message when all routes are processed */
2766 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2767 bgp_send_delayed_eor(bgp
);
2768 /* Send route processing complete message to RIB */
2769 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2770 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2774 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2776 thread_info
->afi
= afi
;
2777 thread_info
->safi
= safi
;
2778 thread_info
->bgp
= bgp
;
2780 /* If there are more routes to be processed, start the
2783 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2784 BGP_ROUTE_SELECT_DELAY
,
2785 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2789 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2791 struct bgp_process_queue
*pqnode
= data
;
2792 struct bgp
*bgp
= pqnode
->bgp
;
2793 struct bgp_table
*table
;
2794 struct bgp_node
*rn
;
2797 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2798 bgp_process_main_one(bgp
, NULL
, 0, 0);
2799 /* should always have dedicated wq call */
2800 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2804 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2805 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2806 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2807 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2808 table
= bgp_node_table(rn
);
2809 /* note, new RNs may be added as part of processing */
2810 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2812 bgp_unlock_node(rn
);
2813 bgp_table_unlock(table
);
2819 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2821 struct bgp_process_queue
*pqnode
= data
;
2823 bgp_unlock(pqnode
->bgp
);
2825 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2828 void bgp_process_queue_init(void)
2830 if (!bm
->process_main_queue
)
2831 bm
->process_main_queue
=
2832 work_queue_new(bm
->master
, "process_main_queue");
2834 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2835 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2836 bm
->process_main_queue
->spec
.max_retries
= 0;
2837 bm
->process_main_queue
->spec
.hold
= 50;
2838 /* Use a higher yield value of 50ms for main queue processing */
2839 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2842 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2844 struct bgp_process_queue
*pqnode
;
2846 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2847 sizeof(struct bgp_process_queue
));
2849 /* unlocked in bgp_processq_del */
2850 pqnode
->bgp
= bgp_lock(bgp
);
2851 STAILQ_INIT(&pqnode
->pqueue
);
2856 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2858 #define ARBITRARY_PROCESS_QLEN 10000
2859 struct work_queue
*wq
= bm
->process_main_queue
;
2860 struct bgp_process_queue
*pqnode
;
2861 int pqnode_reuse
= 0;
2863 /* already scheduled for processing? */
2864 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2867 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2870 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2871 if (BGP_DEBUG(update
, UPDATE_OUT
))
2872 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2880 /* Add route nodes to an existing work queue item until reaching the
2881 limit only if is from the same BGP view and it's not an EOIU marker
2883 if (work_queue_item_count(wq
)) {
2884 struct work_queue_item
*item
= work_queue_last_item(wq
);
2885 pqnode
= item
->data
;
2887 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2888 || pqnode
->bgp
!= bgp
2889 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2890 pqnode
= bgp_processq_alloc(bgp
);
2894 pqnode
= bgp_processq_alloc(bgp
);
2895 /* all unlocked in bgp_process_wq */
2896 bgp_table_lock(bgp_node_table(rn
));
2898 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2901 /* can't be enqueued twice */
2902 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2903 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2907 work_queue_add(wq
, pqnode
);
2912 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2914 struct bgp_process_queue
*pqnode
;
2916 if (bm
->process_main_queue
== NULL
)
2919 pqnode
= bgp_processq_alloc(bgp
);
2921 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2922 work_queue_add(bm
->process_main_queue
, pqnode
);
2925 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2929 peer
= THREAD_ARG(thread
);
2930 peer
->t_pmax_restart
= NULL
;
2932 if (bgp_debug_neighbor_events(peer
))
2934 "%s Maximum-prefix restart timer expired, restore peering",
2937 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2938 zlog_debug("%s: %s peer_clear failed", __func__
, peer
->host
);
2943 bool bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2947 iana_safi_t pkt_safi
;
2949 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2952 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2953 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2954 PEER_STATUS_PREFIX_LIMIT
)
2959 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2960 " exceed, limit %" PRIu32
,
2961 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2962 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2963 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2965 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2966 PEER_FLAG_MAX_PREFIX_WARNING
))
2969 /* Convert AFI, SAFI to values for packet. */
2970 pkt_afi
= afi_int2iana(afi
);
2971 pkt_safi
= safi_int2iana(safi
);
2975 ndata
[0] = (pkt_afi
>> 8);
2977 ndata
[2] = pkt_safi
;
2978 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2979 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2980 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2981 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2983 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2984 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2985 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2989 /* Dynamic peers will just close their connection. */
2990 if (peer_dynamic_neighbor(peer
))
2993 /* restart timer start */
2994 if (peer
->pmax_restart
[afi
][safi
]) {
2995 peer
->v_pmax_restart
=
2996 peer
->pmax_restart
[afi
][safi
] * 60;
2998 if (bgp_debug_neighbor_events(peer
))
3000 "%s Maximum-prefix restart timer started for %d secs",
3001 peer
->host
, peer
->v_pmax_restart
);
3003 BGP_TIMER_ON(peer
->t_pmax_restart
,
3004 bgp_maximum_prefix_restart_timer
,
3005 peer
->v_pmax_restart
);
3010 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3011 PEER_STATUS_PREFIX_LIMIT
);
3013 if (peer
->pcount
[afi
][safi
]
3014 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3015 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3016 PEER_STATUS_PREFIX_THRESHOLD
)
3021 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3023 get_afi_safi_str(afi
, safi
, false), peer
->host
,
3024 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
3025 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3026 PEER_STATUS_PREFIX_THRESHOLD
);
3028 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3029 PEER_STATUS_PREFIX_THRESHOLD
);
3033 /* Unconditionally remove the route from the RIB, without taking
3034 * damping into consideration (eg, because the session went down)
3036 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3037 struct peer
*peer
, afi_t afi
, safi_t safi
)
3040 struct bgp
*bgp
= NULL
;
3041 bool delete_route
= false;
3043 bgp_aggregate_decrement(peer
->bgp
, bgp_node_get_prefix(rn
),
3046 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3047 bgp_path_info_delete(rn
, pi
); /* keep historical info */
3049 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3052 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3053 delete_route
= true;
3054 else if (bgp_node_set_defer_flag(rn
, true) < 0)
3055 delete_route
= true;
3057 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
3058 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
3059 bgp
= pi
->peer
->bgp
;
3061 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3062 list_delete_node(bgp
->gr_info
[afi
][safi
]
3071 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
3072 bgp_process(peer
->bgp
, rn
, afi
, safi
);
3075 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3076 struct peer
*peer
, afi_t afi
, safi_t safi
,
3077 struct prefix_rd
*prd
)
3079 const struct prefix
*p
= bgp_node_get_prefix(rn
);
3081 /* apply dampening, if result is suppressed, we'll be retaining
3082 * the bgp_path_info in the RIB for historical reference.
3084 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3085 && peer
->sort
== BGP_PEER_EBGP
)
3086 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
3087 == BGP_DAMP_SUPPRESSED
) {
3088 bgp_aggregate_decrement(peer
->bgp
, p
, pi
, afi
,
3094 if (safi
== SAFI_MPLS_VPN
) {
3095 struct bgp_node
*prn
= NULL
;
3096 struct bgp_table
*table
= NULL
;
3098 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3099 (struct prefix
*)prd
);
3100 if (bgp_node_has_bgp_path_info_data(prn
)) {
3101 table
= bgp_node_get_bgp_table_info(prn
);
3103 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3104 peer
->bgp
, prd
, table
, p
, pi
);
3106 bgp_unlock_node(prn
);
3108 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3109 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3111 vnc_import_bgp_del_route(peer
->bgp
, p
, pi
);
3112 vnc_import_bgp_exterior_del_route(peer
->bgp
, p
, pi
);
3117 /* If this is an EVPN route, process for un-import. */
3118 if (safi
== SAFI_EVPN
)
3119 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, p
, pi
);
3121 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3124 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3125 struct peer
*peer
, struct attr
*attr
,
3126 struct bgp_node
*rn
)
3128 struct bgp_path_info
*new;
3130 /* Make new BGP info. */
3131 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3133 new->instance
= instance
;
3134 new->sub_type
= sub_type
;
3137 new->uptime
= bgp_clock();
3142 static void overlay_index_update(struct attr
*attr
,
3143 struct eth_segment_id
*eth_s_id
,
3144 union gw_addr
*gw_ip
)
3149 if (eth_s_id
== NULL
) {
3150 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
3151 sizeof(struct eth_segment_id
));
3153 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
3154 sizeof(struct eth_segment_id
));
3156 if (gw_ip
== NULL
) {
3157 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3159 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3160 sizeof(union gw_addr
));
3164 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3165 struct eth_segment_id
*eth_s_id
,
3166 union gw_addr
*gw_ip
)
3168 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
3169 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3171 struct eth_segment_id esi
;
3175 if (afi
!= AFI_L2VPN
)
3178 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
3179 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3181 if (gw_ip
== NULL
) {
3182 memset(&temp
, 0, sizeof(temp
));
3183 path_gw_ip_remote
= &temp
.ip
;
3185 path_gw_ip_remote
= gw_ip
;
3187 if (eth_s_id
== NULL
) {
3188 memset(&temp
, 0, sizeof(temp
));
3189 path_eth_s_id_remote
= &temp
.esi
;
3191 path_eth_s_id_remote
= eth_s_id
;
3193 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
3196 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
3197 sizeof(struct eth_segment_id
));
3200 /* Check if received nexthop is valid or not. */
3201 static bool bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3202 uint8_t type
, uint8_t stype
,
3203 struct attr
*attr
, struct bgp_node
*rn
)
3207 /* Only validated for unicast and multicast currently. */
3208 /* Also valid for EVPN where the nexthop is an IP address. */
3209 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3212 /* If NEXT_HOP is present, validate it. */
3213 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3214 if (attr
->nexthop
.s_addr
== INADDR_ANY
3215 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3216 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
, rn
))
3220 /* If MP_NEXTHOP is present, validate it. */
3221 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3222 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3223 * it is not an IPv6 link-local address.
3225 if (attr
->mp_nexthop_len
) {
3226 switch (attr
->mp_nexthop_len
) {
3227 case BGP_ATTR_NHLEN_IPV4
:
3228 case BGP_ATTR_NHLEN_VPNV4
:
3229 ret
= (attr
->mp_nexthop_global_in
.s_addr
== INADDR_ANY
3231 ntohl(attr
->mp_nexthop_global_in
.s_addr
))
3232 || bgp_nexthop_self(bgp
, afi
, type
, stype
, attr
,
3236 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3237 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3238 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3239 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3240 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3241 || IN6_IS_ADDR_MULTICAST(
3242 &attr
->mp_nexthop_global
)
3243 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3256 int bgp_update(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
3257 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3258 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3259 uint32_t num_labels
, int soft_reconfig
,
3260 struct bgp_route_evpn
*evpn
)
3263 int aspath_loop_count
= 0;
3264 struct bgp_node
*rn
;
3266 struct attr new_attr
;
3267 struct attr
*attr_new
;
3268 struct bgp_path_info
*pi
;
3269 struct bgp_path_info
*new;
3270 struct bgp_path_info_extra
*extra
;
3272 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3274 int do_loop_check
= 1;
3275 int has_valid_label
= 0;
3277 uint8_t pi_type
= 0;
3278 uint8_t pi_sub_type
= 0;
3281 int vnc_implicit_withdraw
= 0;
3285 memset(&new_attr
, 0, sizeof(struct attr
));
3286 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3287 new_attr
.label
= MPLS_INVALID_LABEL
;
3290 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3291 /* TODO: Check to see if we can get rid of "is_valid_label" */
3292 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3293 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3295 has_valid_label
= bgp_is_valid_label(label
);
3297 /* When peer's soft reconfiguration enabled. Record input packet in
3300 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3301 && peer
!= bgp
->peer_self
)
3302 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3304 /* Check previously received route. */
3305 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3306 if (pi
->peer
== peer
&& pi
->type
== type
3307 && pi
->sub_type
== sub_type
3308 && pi
->addpath_rx_id
== addpath_id
)
3311 /* AS path local-as loop check. */
3312 if (peer
->change_local_as
) {
3313 if (peer
->allowas_in
[afi
][safi
])
3314 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3315 else if (!CHECK_FLAG(peer
->flags
,
3316 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3317 aspath_loop_count
= 1;
3319 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3320 > aspath_loop_count
) {
3321 peer
->stat_pfx_aspath_loop
++;
3322 reason
= "as-path contains our own AS;";
3327 /* If the peer is configured for "allowas-in origin" and the last ASN in
3329 * as-path is our ASN then we do not need to call aspath_loop_check
3331 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3332 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3335 /* AS path loop check. */
3336 if (do_loop_check
) {
3337 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3338 > peer
->allowas_in
[afi
][safi
]
3339 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3340 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3341 > peer
->allowas_in
[afi
][safi
])) {
3342 peer
->stat_pfx_aspath_loop
++;
3343 reason
= "as-path contains our own AS;";
3348 /* Route reflector originator ID check. */
3349 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3350 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3351 peer
->stat_pfx_originator_loop
++;
3352 reason
= "originator is us;";
3356 /* Route reflector cluster ID check. */
3357 if (bgp_cluster_filter(peer
, attr
)) {
3358 peer
->stat_pfx_cluster_loop
++;
3359 reason
= "reflected from the same cluster;";
3363 /* Apply incoming filter. */
3364 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3365 peer
->stat_pfx_filter
++;
3370 /* RFC 8212 to prevent route leaks.
3371 * This specification intends to improve this situation by requiring the
3372 * explicit configuration of both BGP Import and Export Policies for any
3373 * External BGP (EBGP) session such as customers, peers, or
3374 * confederation boundaries for all enabled address families. Through
3375 * codification of the aforementioned requirement, operators will
3376 * benefit from consistent behavior across different BGP
3379 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3380 if (!bgp_inbound_policy_exists(peer
,
3381 &peer
->filter
[afi
][safi
])) {
3382 reason
= "inbound policy missing";
3386 /* draft-ietf-idr-deprecate-as-set-confed-set
3387 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3388 * Eventually, This document (if approved) updates RFC 4271
3389 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3390 * and obsoletes RFC 6472.
3392 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3393 if (aspath_check_as_sets(attr
->aspath
)) {
3395 "as-path contains AS_SET or AS_CONFED_SET type;";
3401 /* Apply incoming route-map.
3402 * NB: new_attr may now contain newly allocated values from route-map
3404 * commands, so we need bgp_attr_flush in the error paths, until we
3406 * the attr (which takes over the memory references) */
3407 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3408 label
, num_labels
, rn
) == RMAP_DENY
) {
3409 peer
->stat_pfx_filter
++;
3410 reason
= "route-map;";
3411 bgp_attr_flush(&new_attr
);
3415 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3416 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3417 /* remove from RIB previous entry */
3418 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3421 if (peer
->sort
== BGP_PEER_EBGP
) {
3423 /* If we receive the graceful-shutdown community from an eBGP
3424 * peer we must lower local-preference */
3425 if (new_attr
.community
3426 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3427 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3428 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3430 /* If graceful-shutdown is configured then add the GSHUT
3431 * community to all paths received from eBGP peers */
3432 } else if (CHECK_FLAG(peer
->bgp
->flags
,
3433 BGP_FLAG_GRACEFUL_SHUTDOWN
))
3434 bgp_attr_add_gshut_community(&new_attr
);
3439 pi_sub_type
= pi
->sub_type
;
3442 /* next hop check. */
3443 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3444 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3445 pi_sub_type
, &new_attr
, rn
)) {
3446 peer
->stat_pfx_nh_invalid
++;
3447 reason
= "martian or self next-hop;";
3448 bgp_attr_flush(&new_attr
);
3452 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3453 peer
->stat_pfx_nh_invalid
++;
3454 reason
= "self mac;";
3458 attr_new
= bgp_attr_intern(&new_attr
);
3460 /* If the update is implicit withdraw. */
3462 pi
->uptime
= bgp_clock();
3463 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3465 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3467 /* Same attribute comes in. */
3468 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3469 && attrhash_cmp(pi
->attr
, attr_new
)
3470 && (!has_valid_label
3471 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3472 num_labels
* sizeof(mpls_label_t
))
3474 && (overlay_index_equal(
3475 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3476 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3477 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3478 BGP_CONFIG_DAMPENING
)
3479 && peer
->sort
== BGP_PEER_EBGP
3480 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3481 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3482 bgp_debug_rdpfxpath2str(
3483 afi
, safi
, prd
, p
, label
,
3484 num_labels
, addpath_id
? 1 : 0,
3485 addpath_id
, pfx_buf
,
3487 zlog_debug("%s rcvd %s", peer
->host
,
3491 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3492 != BGP_DAMP_SUPPRESSED
) {
3493 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3495 bgp_process(bgp
, rn
, afi
, safi
);
3497 } else /* Duplicate - odd */
3499 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3500 if (!peer
->rcvd_attr_printed
) {
3502 "%s rcvd UPDATE w/ attr: %s",
3504 peer
->rcvd_attr_str
);
3505 peer
->rcvd_attr_printed
= 1;
3508 bgp_debug_rdpfxpath2str(
3509 afi
, safi
, prd
, p
, label
,
3510 num_labels
, addpath_id
? 1 : 0,
3511 addpath_id
, pfx_buf
,
3514 "%s rcvd %s...duplicate ignored",
3515 peer
->host
, pfx_buf
);
3518 /* graceful restart STALE flag unset. */
3519 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3520 bgp_path_info_unset_flag(
3521 rn
, pi
, BGP_PATH_STALE
);
3522 bgp_node_set_defer_flag(rn
, false);
3523 bgp_process(bgp
, rn
, afi
, safi
);
3527 bgp_unlock_node(rn
);
3528 bgp_attr_unintern(&attr_new
);
3533 /* Withdraw/Announce before we fully processed the withdraw */
3534 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3535 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3536 bgp_debug_rdpfxpath2str(
3537 afi
, safi
, prd
, p
, label
, num_labels
,
3538 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3541 "%s rcvd %s, flapped quicker than processing",
3542 peer
->host
, pfx_buf
);
3545 bgp_path_info_restore(rn
, pi
);
3548 /* Received Logging. */
3549 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3550 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3551 num_labels
, addpath_id
? 1 : 0,
3552 addpath_id
, pfx_buf
,
3554 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3557 /* graceful restart STALE flag unset. */
3558 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3559 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3560 bgp_node_set_defer_flag(rn
, false);
3563 /* The attribute is changed. */
3564 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3566 /* implicit withdraw, decrement aggregate and pcount here.
3567 * only if update is accepted, they'll increment below.
3569 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3571 /* Update bgp route dampening information. */
3572 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3573 && peer
->sort
== BGP_PEER_EBGP
) {
3574 /* This is implicit withdraw so we should update
3577 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3578 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3581 if (safi
== SAFI_MPLS_VPN
) {
3582 struct bgp_node
*prn
= NULL
;
3583 struct bgp_table
*table
= NULL
;
3585 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3586 (struct prefix
*)prd
);
3587 if (bgp_node_has_bgp_path_info_data(prn
)) {
3588 table
= bgp_node_get_bgp_table_info(prn
);
3590 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3591 bgp
, prd
, table
, p
, pi
);
3593 bgp_unlock_node(prn
);
3595 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3596 && (safi
== SAFI_UNICAST
)) {
3597 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3599 * Implicit withdraw case.
3601 ++vnc_implicit_withdraw
;
3602 vnc_import_bgp_del_route(bgp
, p
, pi
);
3603 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3608 /* Special handling for EVPN update of an existing route. If the
3609 * extended community attribute has changed, we need to
3611 * the route using its existing extended community. It will be
3612 * subsequently processed for import with the new extended
3615 if (safi
== SAFI_EVPN
&& !same_attr
) {
3617 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3619 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3622 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3623 attr_new
->ecommunity
);
3625 if (bgp_debug_update(peer
, p
, NULL
, 1))
3627 "Change in EXT-COMM, existing %s new %s",
3629 pi
->attr
->ecommunity
),
3631 attr_new
->ecommunity
));
3632 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3638 /* Update to new attribute. */
3639 bgp_attr_unintern(&pi
->attr
);
3640 pi
->attr
= attr_new
;
3642 /* Update MPLS label */
3643 if (has_valid_label
) {
3644 extra
= bgp_path_info_extra_get(pi
);
3645 if (extra
->label
!= label
) {
3646 memcpy(&extra
->label
, label
,
3647 num_labels
* sizeof(mpls_label_t
));
3648 extra
->num_labels
= num_labels
;
3650 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3651 bgp_set_valid_label(&extra
->label
[0]);
3654 /* Update SRv6 SID */
3655 if (attr
->srv6_l3vpn
) {
3656 extra
= bgp_path_info_extra_get(pi
);
3657 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3658 sid_copy(&extra
->sid
[0],
3659 &attr
->srv6_l3vpn
->sid
);
3660 extra
->num_sids
= 1;
3662 } else if (attr
->srv6_vpn
) {
3663 extra
= bgp_path_info_extra_get(pi
);
3664 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3665 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3666 extra
->num_sids
= 1;
3671 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3672 && (safi
== SAFI_UNICAST
)) {
3673 if (vnc_implicit_withdraw
) {
3675 * Add back the route with its new attributes
3677 * The route is still selected, until the route
3679 * queued by bgp_process actually runs. We have
3681 * update to the VNC side immediately to avoid
3683 * configuration changes (e.g., route-map
3685 * trigger re-importation of the entire RIB.
3687 vnc_import_bgp_add_route(bgp
, p
, pi
);
3688 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3692 /* Update Overlay Index */
3693 if (afi
== AFI_L2VPN
) {
3694 overlay_index_update(
3695 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3696 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3699 /* Update bgp route dampening information. */
3700 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3701 && peer
->sort
== BGP_PEER_EBGP
) {
3702 /* Now we do normal update dampening. */
3703 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3704 if (ret
== BGP_DAMP_SUPPRESSED
) {
3705 bgp_unlock_node(rn
);
3710 /* Nexthop reachability check - for unicast and
3711 * labeled-unicast.. */
3712 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3713 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3714 || (safi
== SAFI_EVPN
&&
3715 bgp_evpn_is_prefix_nht_supported(p
))) {
3716 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3717 && peer
->ttl
== BGP_DEFAULT_TTL
3718 && !CHECK_FLAG(peer
->flags
,
3719 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3720 && !CHECK_FLAG(bgp
->flags
,
3721 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3726 struct bgp
*bgp_nexthop
= bgp
;
3728 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3729 bgp_nexthop
= pi
->extra
->bgp_orig
;
3731 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3733 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3734 pi
, NULL
, connected
)
3735 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3736 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3738 if (BGP_DEBUG(nht
, NHT
)) {
3739 char buf1
[INET6_ADDRSTRLEN
];
3741 (const void *)&attr_new
3743 buf1
, INET6_ADDRSTRLEN
);
3744 zlog_debug("%s(%s): NH unresolved",
3747 bgp_path_info_unset_flag(rn
, pi
,
3751 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3754 if (safi
== SAFI_MPLS_VPN
) {
3755 struct bgp_node
*prn
= NULL
;
3756 struct bgp_table
*table
= NULL
;
3758 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3759 (struct prefix
*)prd
);
3760 if (bgp_node_has_bgp_path_info_data(prn
)) {
3761 table
= bgp_node_get_bgp_table_info(prn
);
3763 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3764 bgp
, prd
, table
, p
, pi
);
3766 bgp_unlock_node(prn
);
3770 /* If this is an EVPN route and some attribute has changed,
3772 * route for import. If the extended community has changed, we
3774 * have done the un-import earlier and the import would result
3776 * route getting injected into appropriate L2 VNIs. If it is
3778 * some other attribute change, the import will result in
3780 * the attributes for the route in the VNI(s).
3782 if (safi
== SAFI_EVPN
&& !same_attr
&&
3783 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3784 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3786 /* Process change. */
3787 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3789 bgp_process(bgp
, rn
, afi
, safi
);
3790 bgp_unlock_node(rn
);
3792 if (SAFI_UNICAST
== safi
3793 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3794 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3796 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3798 if ((SAFI_MPLS_VPN
== safi
)
3799 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3801 vpn_leak_to_vrf_update(bgp
, pi
);
3805 if (SAFI_MPLS_VPN
== safi
) {
3806 mpls_label_t label_decoded
= decode_label(label
);
3808 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3809 type
, sub_type
, &label_decoded
);
3811 if (SAFI_ENCAP
== safi
) {
3812 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3813 type
, sub_type
, NULL
);
3818 } // End of implicit withdraw
3820 /* Received Logging. */
3821 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3822 if (!peer
->rcvd_attr_printed
) {
3823 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3824 peer
->rcvd_attr_str
);
3825 peer
->rcvd_attr_printed
= 1;
3828 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3829 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3831 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3834 /* Make new BGP info. */
3835 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3837 /* Update MPLS label */
3838 if (has_valid_label
) {
3839 extra
= bgp_path_info_extra_get(new);
3840 if (extra
->label
!= label
) {
3841 memcpy(&extra
->label
, label
,
3842 num_labels
* sizeof(mpls_label_t
));
3843 extra
->num_labels
= num_labels
;
3845 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3846 bgp_set_valid_label(&extra
->label
[0]);
3849 /* Update SRv6 SID */
3850 if (safi
== SAFI_MPLS_VPN
) {
3851 extra
= bgp_path_info_extra_get(new);
3852 if (attr
->srv6_l3vpn
) {
3853 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
3854 extra
->num_sids
= 1;
3855 } else if (attr
->srv6_vpn
) {
3856 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3857 extra
->num_sids
= 1;
3861 /* Update Overlay Index */
3862 if (afi
== AFI_L2VPN
) {
3863 overlay_index_update(new->attr
,
3864 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3865 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3867 /* Nexthop reachability check. */
3868 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3869 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3870 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3871 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3872 && peer
->ttl
== BGP_DEFAULT_TTL
3873 && !CHECK_FLAG(peer
->flags
,
3874 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3875 && !CHECK_FLAG(bgp
->flags
,
3876 BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3881 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3883 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3885 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3886 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3888 if (BGP_DEBUG(nht
, NHT
)) {
3889 char buf1
[INET6_ADDRSTRLEN
];
3891 (const void *)&attr_new
->nexthop
,
3892 buf1
, INET6_ADDRSTRLEN
);
3893 zlog_debug("%s(%s): NH unresolved", __func__
,
3896 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3899 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3902 new->addpath_rx_id
= addpath_id
;
3904 /* Increment prefix */
3905 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3907 /* Register new BGP information. */
3908 bgp_path_info_add(rn
, new);
3910 /* route_node_get lock */
3911 bgp_unlock_node(rn
);
3914 if (safi
== SAFI_MPLS_VPN
) {
3915 struct bgp_node
*prn
= NULL
;
3916 struct bgp_table
*table
= NULL
;
3918 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3919 if (bgp_node_has_bgp_path_info_data(prn
)) {
3920 table
= bgp_node_get_bgp_table_info(prn
);
3922 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3923 bgp
, prd
, table
, p
, new);
3925 bgp_unlock_node(prn
);
3929 /* If maximum prefix count is configured and current prefix
3931 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3934 /* If this is an EVPN route, process for import. */
3935 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3936 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3938 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3940 /* Process change. */
3941 bgp_process(bgp
, rn
, afi
, safi
);
3943 if (SAFI_UNICAST
== safi
3944 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3945 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3946 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3948 if ((SAFI_MPLS_VPN
== safi
)
3949 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3951 vpn_leak_to_vrf_update(bgp
, new);
3954 if (SAFI_MPLS_VPN
== safi
) {
3955 mpls_label_t label_decoded
= decode_label(label
);
3957 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3958 sub_type
, &label_decoded
);
3960 if (SAFI_ENCAP
== safi
) {
3961 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3968 /* This BGP update is filtered. Log the reason then update BGP
3971 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3973 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3974 if (!peer
->rcvd_attr_printed
) {
3975 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3976 peer
->rcvd_attr_str
);
3977 peer
->rcvd_attr_printed
= 1;
3980 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3981 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3983 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3984 peer
->host
, pfx_buf
, reason
);
3988 /* If this is an EVPN route, un-import it as it is now filtered.
3990 if (safi
== SAFI_EVPN
)
3991 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3993 if (SAFI_UNICAST
== safi
3994 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3995 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3997 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3999 if ((SAFI_MPLS_VPN
== safi
)
4000 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4002 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4005 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4008 bgp_unlock_node(rn
);
4012 * Filtered update is treated as an implicit withdrawal (see
4014 * a few lines above)
4016 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4017 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4025 int bgp_withdraw(struct peer
*peer
, const struct prefix
*p
, uint32_t addpath_id
,
4026 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4027 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4028 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4031 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4032 struct bgp_node
*rn
;
4033 struct bgp_path_info
*pi
;
4036 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4037 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4045 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4047 /* If peer is soft reconfiguration enabled. Record input packet for
4048 * further calculation.
4050 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4051 * routes that are filtered. This tanks out Quagga RS pretty badly due
4053 * the iteration over all RS clients.
4054 * Since we need to remove the entry from adj_in anyway, do that first
4056 * if there was no entry, we don't need to do anything more.
4058 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4059 && peer
!= bgp
->peer_self
)
4060 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
4061 peer
->stat_pfx_dup_withdraw
++;
4063 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4064 bgp_debug_rdpfxpath2str(
4065 afi
, safi
, prd
, p
, label
, num_labels
,
4066 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4069 "%s withdrawing route %s not in adj-in",
4070 peer
->host
, pfx_buf
);
4072 bgp_unlock_node(rn
);
4076 /* Lookup withdrawn route. */
4077 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4078 if (pi
->peer
== peer
&& pi
->type
== type
4079 && pi
->sub_type
== sub_type
4080 && pi
->addpath_rx_id
== addpath_id
)
4084 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4085 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4086 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4088 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4092 /* Withdraw specified route from routing table. */
4093 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4094 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
4095 if (SAFI_UNICAST
== safi
4096 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4097 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4098 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4100 if ((SAFI_MPLS_VPN
== safi
)
4101 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4103 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4105 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4106 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4107 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4109 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4112 /* Unlock bgp_node_get() lock. */
4113 bgp_unlock_node(rn
);
4118 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4121 struct update_subgroup
*subgrp
;
4122 subgrp
= peer_subgroup(peer
, afi
, safi
);
4123 subgroup_default_originate(subgrp
, withdraw
);
4128 * bgp_stop_announce_route_timer
4130 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4132 if (!paf
->t_announce_route
)
4135 THREAD_TIMER_OFF(paf
->t_announce_route
);
4139 * bgp_announce_route_timer_expired
4141 * Callback that is invoked when the route announcement timer for a
4144 static int bgp_announce_route_timer_expired(struct thread
*t
)
4146 struct peer_af
*paf
;
4149 paf
= THREAD_ARG(t
);
4152 if (peer
->status
!= Established
)
4155 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4158 peer_af_announce_route(paf
, 1);
4163 * bgp_announce_route
4165 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4167 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4169 struct peer_af
*paf
;
4170 struct update_subgroup
*subgrp
;
4172 paf
= peer_af_find(peer
, afi
, safi
);
4175 subgrp
= PAF_SUBGRP(paf
);
4178 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4179 * or a refresh has already been triggered.
4181 if (!subgrp
|| paf
->t_announce_route
)
4185 * Start a timer to stagger/delay the announce. This serves
4186 * two purposes - announcement can potentially be combined for
4187 * multiple peers and the announcement doesn't happen in the
4190 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4191 (subgrp
->peer_count
== 1)
4192 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4193 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4194 &paf
->t_announce_route
);
4198 * Announce routes from all AF tables to a peer.
4200 * This should ONLY be called when there is a need to refresh the
4201 * routes to the peer based on a policy change for this peer alone
4202 * or a route refresh request received from the peer.
4203 * The operation will result in splitting the peer from its existing
4204 * subgroups and putting it in new subgroups.
4206 void bgp_announce_route_all(struct peer
*peer
)
4211 FOREACH_AFI_SAFI (afi
, safi
)
4212 bgp_announce_route(peer
, afi
, safi
);
4215 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4216 struct bgp_table
*table
,
4217 struct prefix_rd
*prd
)
4220 struct bgp_node
*rn
;
4221 struct bgp_adj_in
*ain
;
4224 table
= peer
->bgp
->rib
[afi
][safi
];
4226 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4227 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
4228 if (ain
->peer
!= peer
)
4231 struct bgp_path_info
*pi
;
4232 uint32_t num_labels
= 0;
4233 mpls_label_t
*label_pnt
= NULL
;
4234 struct bgp_route_evpn evpn
;
4236 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4238 if (pi
->peer
== peer
)
4241 if (pi
&& pi
->extra
)
4242 num_labels
= pi
->extra
->num_labels
;
4244 label_pnt
= &pi
->extra
->label
[0];
4246 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4249 memset(&evpn
, 0, sizeof(evpn
));
4251 ret
= bgp_update(peer
, bgp_node_get_prefix(rn
),
4252 ain
->addpath_rx_id
, ain
->attr
,
4253 afi
, safi
, ZEBRA_ROUTE_BGP
,
4254 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4255 num_labels
, 1, &evpn
);
4258 bgp_unlock_node(rn
);
4264 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4266 struct bgp_node
*rn
;
4267 struct bgp_table
*table
;
4269 if (peer
->status
!= Established
)
4272 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4273 && (safi
!= SAFI_EVPN
))
4274 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4276 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4277 rn
= bgp_route_next(rn
)) {
4278 table
= bgp_node_get_bgp_table_info(rn
);
4283 const struct prefix
*p
= bgp_node_get_prefix(rn
);
4284 struct prefix_rd prd
;
4286 prd
.family
= AF_UNSPEC
;
4288 memcpy(&prd
.val
, p
->u
.val
, 8);
4290 bgp_soft_reconfig_table(peer
, afi
, safi
, table
, &prd
);
4295 struct bgp_clear_node_queue
{
4296 struct bgp_node
*rn
;
4299 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4301 struct bgp_clear_node_queue
*cnq
= data
;
4302 struct bgp_node
*rn
= cnq
->rn
;
4303 struct peer
*peer
= wq
->spec
.data
;
4304 struct bgp_path_info
*pi
;
4306 afi_t afi
= bgp_node_table(rn
)->afi
;
4307 safi_t safi
= bgp_node_table(rn
)->safi
;
4312 /* It is possible that we have multiple paths for a prefix from a peer
4313 * if that peer is using AddPath.
4315 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4316 if (pi
->peer
!= peer
)
4319 /* graceful restart STALE flag set. */
4320 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4321 && peer
->nsf
[afi
][safi
]
4322 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4323 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4324 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4326 /* If this is an EVPN route, process for
4328 if (safi
== SAFI_EVPN
)
4329 bgp_evpn_unimport_route(bgp
, afi
, safi
,
4330 bgp_node_get_prefix(rn
),
4332 /* Handle withdraw for VRF route-leaking and L3VPN */
4333 if (SAFI_UNICAST
== safi
4334 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4335 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4336 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4339 if (SAFI_MPLS_VPN
== safi
&&
4340 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4341 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4344 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4350 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4352 struct bgp_clear_node_queue
*cnq
= data
;
4353 struct bgp_node
*rn
= cnq
->rn
;
4354 struct bgp_table
*table
= bgp_node_table(rn
);
4356 bgp_unlock_node(rn
);
4357 bgp_table_unlock(table
);
4358 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4361 static void bgp_clear_node_complete(struct work_queue
*wq
)
4363 struct peer
*peer
= wq
->spec
.data
;
4365 /* Tickle FSM to start moving again */
4366 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4368 peer_unlock(peer
); /* bgp_clear_route */
4371 static void bgp_clear_node_queue_init(struct peer
*peer
)
4373 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4375 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4376 #undef CLEAR_QUEUE_NAME_LEN
4378 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4379 peer
->clear_node_queue
->spec
.hold
= 10;
4380 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4381 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4382 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4383 peer
->clear_node_queue
->spec
.max_retries
= 0;
4385 /* we only 'lock' this peer reference when the queue is actually active
4387 peer
->clear_node_queue
->spec
.data
= peer
;
4390 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4391 struct bgp_table
*table
)
4393 struct bgp_node
*rn
;
4394 int force
= bm
->process_main_queue
? 0 : 1;
4397 table
= peer
->bgp
->rib
[afi
][safi
];
4399 /* If still no table => afi/safi isn't configured at all or smth. */
4403 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4404 struct bgp_path_info
*pi
, *next
;
4405 struct bgp_adj_in
*ain
;
4406 struct bgp_adj_in
*ain_next
;
4408 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4409 * queued for every clearing peer, regardless of whether it is
4410 * relevant to the peer at hand.
4412 * Overview: There are 3 different indices which need to be
4413 * scrubbed, potentially, when a peer is removed:
4415 * 1 peer's routes visible via the RIB (ie accepted routes)
4416 * 2 peer's routes visible by the (optional) peer's adj-in index
4417 * 3 other routes visible by the peer's adj-out index
4419 * 3 there is no hurry in scrubbing, once the struct peer is
4420 * removed from bgp->peer, we could just GC such deleted peer's
4421 * adj-outs at our leisure.
4423 * 1 and 2 must be 'scrubbed' in some way, at least made
4424 * invisible via RIB index before peer session is allowed to be
4425 * brought back up. So one needs to know when such a 'search' is
4430 * - there'd be a single global queue or a single RIB walker
4431 * - rather than tracking which route_nodes still need to be
4432 * examined on a peer basis, we'd track which peers still
4435 * Given that our per-peer prefix-counts now should be reliable,
4436 * this may actually be achievable. It doesn't seem to be a huge
4437 * problem at this time,
4439 * It is possible that we have multiple paths for a prefix from
4441 * if that peer is using AddPath.
4445 ain_next
= ain
->next
;
4447 if (ain
->peer
== peer
) {
4448 bgp_adj_in_remove(rn
, ain
);
4449 bgp_unlock_node(rn
);
4455 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4457 if (pi
->peer
!= peer
)
4461 bgp_path_info_reap(rn
, pi
);
4463 struct bgp_clear_node_queue
*cnq
;
4465 /* both unlocked in bgp_clear_node_queue_del */
4466 bgp_table_lock(bgp_node_table(rn
));
4469 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4470 sizeof(struct bgp_clear_node_queue
));
4472 work_queue_add(peer
->clear_node_queue
, cnq
);
4480 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4482 struct bgp_node
*rn
;
4483 struct bgp_table
*table
;
4485 if (peer
->clear_node_queue
== NULL
)
4486 bgp_clear_node_queue_init(peer
);
4488 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4489 * Idle until it receives a Clearing_Completed event. This protects
4490 * against peers which flap faster than we can we clear, which could
4493 * a) race with routes from the new session being installed before
4494 * clear_route_node visits the node (to delete the route of that
4496 * b) resource exhaustion, clear_route_node likely leads to an entry
4497 * on the process_main queue. Fast-flapping could cause that queue
4501 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4502 * the unlock will happen upon work-queue completion; other wise, the
4503 * unlock happens at the end of this function.
4505 if (!peer
->clear_node_queue
->thread
)
4508 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4509 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4511 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4512 rn
= bgp_route_next(rn
)) {
4513 table
= bgp_node_get_bgp_table_info(rn
);
4517 bgp_clear_route_table(peer
, afi
, safi
, table
);
4520 /* unlock if no nodes got added to the clear-node-queue. */
4521 if (!peer
->clear_node_queue
->thread
)
4525 void bgp_clear_route_all(struct peer
*peer
)
4530 FOREACH_AFI_SAFI (afi
, safi
)
4531 bgp_clear_route(peer
, afi
, safi
);
4534 rfapiProcessPeerDown(peer
);
4538 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4540 struct bgp_table
*table
;
4541 struct bgp_node
*rn
;
4542 struct bgp_adj_in
*ain
;
4543 struct bgp_adj_in
*ain_next
;
4545 table
= peer
->bgp
->rib
[afi
][safi
];
4547 /* It is possible that we have multiple paths for a prefix from a peer
4548 * if that peer is using AddPath.
4550 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4554 ain_next
= ain
->next
;
4556 if (ain
->peer
== peer
) {
4557 bgp_adj_in_remove(rn
, ain
);
4558 bgp_unlock_node(rn
);
4566 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4568 struct bgp_node
*rn
;
4569 struct bgp_path_info
*pi
;
4570 struct bgp_table
*table
;
4572 if (safi
== SAFI_MPLS_VPN
) {
4573 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4574 rn
= bgp_route_next(rn
)) {
4575 struct bgp_node
*rm
;
4577 /* look for neighbor in tables */
4578 table
= bgp_node_get_bgp_table_info(rn
);
4582 for (rm
= bgp_table_top(table
); rm
;
4583 rm
= bgp_route_next(rm
))
4584 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4586 if (pi
->peer
!= peer
)
4588 if (!CHECK_FLAG(pi
->flags
,
4592 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4597 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4598 rn
= bgp_route_next(rn
))
4599 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4601 if (pi
->peer
!= peer
)
4603 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4605 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4611 bool bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4613 if (peer
->sort
== BGP_PEER_IBGP
)
4616 if (peer
->sort
== BGP_PEER_EBGP
4617 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4618 || FILTER_LIST_OUT_NAME(filter
)
4619 || DISTRIBUTE_OUT_NAME(filter
)))
4624 bool bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4626 if (peer
->sort
== BGP_PEER_IBGP
)
4629 if (peer
->sort
== BGP_PEER_EBGP
4630 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4631 || FILTER_LIST_IN_NAME(filter
)
4632 || DISTRIBUTE_IN_NAME(filter
)))
4637 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4640 struct bgp_node
*rn
;
4641 struct bgp_path_info
*pi
;
4642 struct bgp_path_info
*next
;
4644 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4645 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4646 const struct prefix
*p
= bgp_node_get_prefix(rn
);
4650 /* Unimport EVPN routes from VRFs */
4651 if (safi
== SAFI_EVPN
)
4652 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4655 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4656 && pi
->type
== ZEBRA_ROUTE_BGP
4657 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4658 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4659 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4661 if (bgp_fibupd_safi(safi
))
4662 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
4663 bgp_path_info_reap(rn
, pi
);
4668 /* Delete all kernel routes. */
4669 void bgp_cleanup_routes(struct bgp
*bgp
)
4672 struct bgp_node
*rn
;
4673 struct bgp_table
*table
;
4675 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4676 if (afi
== AFI_L2VPN
)
4678 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4681 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4683 if (afi
!= AFI_L2VPN
) {
4685 safi
= SAFI_MPLS_VPN
;
4686 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4687 rn
= bgp_route_next(rn
)) {
4688 table
= bgp_node_get_bgp_table_info(rn
);
4689 if (table
!= NULL
) {
4690 bgp_cleanup_table(bgp
, table
, safi
);
4691 bgp_table_finish(&table
);
4692 bgp_node_set_bgp_table_info(rn
, NULL
);
4693 bgp_unlock_node(rn
);
4697 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4698 rn
= bgp_route_next(rn
)) {
4699 table
= bgp_node_get_bgp_table_info(rn
);
4700 if (table
!= NULL
) {
4701 bgp_cleanup_table(bgp
, table
, safi
);
4702 bgp_table_finish(&table
);
4703 bgp_node_set_bgp_table_info(rn
, NULL
);
4704 bgp_unlock_node(rn
);
4709 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4710 rn
= bgp_route_next(rn
)) {
4711 table
= bgp_node_get_bgp_table_info(rn
);
4712 if (table
!= NULL
) {
4713 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4714 bgp_table_finish(&table
);
4715 bgp_node_set_bgp_table_info(rn
, NULL
);
4716 bgp_unlock_node(rn
);
4721 void bgp_reset(void)
4724 bgp_zclient_reset();
4725 access_list_reset();
4726 prefix_list_reset();
4729 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4731 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4732 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4733 PEER_CAP_ADDPATH_AF_TX_RCV
));
4736 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4738 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4739 struct bgp_nlri
*packet
)
4748 int addpath_encoded
;
4749 uint32_t addpath_id
;
4752 lim
= pnt
+ packet
->length
;
4754 safi
= packet
->safi
;
4756 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4758 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4759 syntactic validity. If the field is syntactically incorrect,
4760 then the Error Subcode is set to Invalid Network Field. */
4761 for (; pnt
< lim
; pnt
+= psize
) {
4762 /* Clear prefix structure. */
4763 memset(&p
, 0, sizeof(struct prefix
));
4765 if (addpath_encoded
) {
4767 /* When packet overflow occurs return immediately. */
4768 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4769 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4771 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4772 addpath_id
= ntohl(addpath_id
);
4773 pnt
+= BGP_ADDPATH_ID_LEN
;
4776 /* Fetch prefix length. */
4777 p
.prefixlen
= *pnt
++;
4778 /* afi/safi validity already verified by caller,
4779 * bgp_update_receive */
4780 p
.family
= afi2family(afi
);
4782 /* Prefix length check. */
4783 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4786 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4787 peer
->host
, p
.prefixlen
, packet
->afi
);
4788 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4791 /* Packet size overflow check. */
4792 psize
= PSIZE(p
.prefixlen
);
4794 /* When packet overflow occur return immediately. */
4795 if (pnt
+ psize
> lim
) {
4798 "%s [Error] Update packet error (prefix length %d overflows packet)",
4799 peer
->host
, p
.prefixlen
);
4800 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4803 /* Defensive coding, double-check the psize fits in a struct
4805 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4808 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4809 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4810 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4813 /* Fetch prefix from NLRI packet. */
4814 memcpy(p
.u
.val
, pnt
, psize
);
4816 /* Check address. */
4817 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4818 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4819 /* From RFC4271 Section 6.3:
4821 * If a prefix in the NLRI field is semantically
4823 * (e.g., an unexpected multicast IP address),
4825 * be logged locally, and the prefix SHOULD be
4830 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4831 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4836 /* Check address. */
4837 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4838 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4843 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4845 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4850 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4855 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4857 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4864 /* Normal process. */
4866 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4867 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4868 NULL
, NULL
, 0, 0, NULL
);
4870 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4871 safi
, ZEBRA_ROUTE_BGP
,
4872 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4875 /* Do not send BGP notification twice when maximum-prefix count
4877 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4878 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4880 /* Address family configuration mismatch. */
4882 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4885 /* Packet length consistency check. */
4889 "%s [Error] Update packet error (prefix length mismatch with total length)",
4891 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4894 return BGP_NLRI_PARSE_OK
;
4897 static struct bgp_static
*bgp_static_new(void)
4899 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4902 static void bgp_static_free(struct bgp_static
*bgp_static
)
4904 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4905 route_map_counter_decrement(bgp_static
->rmap
.map
);
4907 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4908 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4911 void bgp_static_update(struct bgp
*bgp
, const struct prefix
*p
,
4912 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4914 struct bgp_node
*rn
;
4915 struct bgp_path_info
*pi
;
4916 struct bgp_path_info
*new;
4917 struct bgp_path_info rmap_path
;
4919 struct attr
*attr_new
;
4920 route_map_result_t ret
;
4922 int vnc_implicit_withdraw
= 0;
4927 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4929 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4931 attr
.nexthop
= bgp_static
->igpnexthop
;
4932 attr
.med
= bgp_static
->igpmetric
;
4933 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4935 if (bgp_static
->atomic
)
4936 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4938 /* Store label index, if required. */
4939 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4940 attr
.label_index
= bgp_static
->label_index
;
4941 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4944 /* Apply route-map. */
4945 if (bgp_static
->rmap
.name
) {
4946 struct attr attr_tmp
= attr
;
4948 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4949 rmap_path
.peer
= bgp
->peer_self
;
4950 rmap_path
.attr
= &attr_tmp
;
4952 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4954 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4957 bgp
->peer_self
->rmap_type
= 0;
4959 if (ret
== RMAP_DENYMATCH
) {
4960 /* Free uninterned attribute. */
4961 bgp_attr_flush(&attr_tmp
);
4963 /* Unintern original. */
4964 aspath_unintern(&attr
.aspath
);
4965 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4969 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4970 bgp_attr_add_gshut_community(&attr_tmp
);
4972 attr_new
= bgp_attr_intern(&attr_tmp
);
4975 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4976 bgp_attr_add_gshut_community(&attr
);
4978 attr_new
= bgp_attr_intern(&attr
);
4981 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4982 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4983 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4987 if (attrhash_cmp(pi
->attr
, attr_new
)
4988 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4989 && !CHECK_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4990 bgp_unlock_node(rn
);
4991 bgp_attr_unintern(&attr_new
);
4992 aspath_unintern(&attr
.aspath
);
4995 /* The attribute is changed. */
4996 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4998 /* Rewrite BGP route information. */
4999 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5000 bgp_path_info_restore(rn
, pi
);
5002 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5004 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5005 && (safi
== SAFI_UNICAST
)) {
5006 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5008 * Implicit withdraw case.
5009 * We have to do this before pi is
5012 ++vnc_implicit_withdraw
;
5013 vnc_import_bgp_del_route(bgp
, p
, pi
);
5014 vnc_import_bgp_exterior_del_route(
5019 bgp_attr_unintern(&pi
->attr
);
5020 pi
->attr
= attr_new
;
5021 pi
->uptime
= bgp_clock();
5023 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5024 && (safi
== SAFI_UNICAST
)) {
5025 if (vnc_implicit_withdraw
) {
5026 vnc_import_bgp_add_route(bgp
, p
, pi
);
5027 vnc_import_bgp_exterior_add_route(
5033 /* Nexthop reachability check. */
5034 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5035 && (safi
== SAFI_UNICAST
5036 || safi
== SAFI_LABELED_UNICAST
)) {
5038 struct bgp
*bgp_nexthop
= bgp
;
5040 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5041 bgp_nexthop
= pi
->extra
->bgp_orig
;
5043 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5045 bgp_path_info_set_flag(rn
, pi
,
5048 if (BGP_DEBUG(nht
, NHT
)) {
5049 char buf1
[INET6_ADDRSTRLEN
];
5050 inet_ntop(p
->family
,
5054 "%s(%s): Route not in table, not advertising",
5057 bgp_path_info_unset_flag(
5058 rn
, pi
, BGP_PATH_VALID
);
5061 /* Delete the NHT structure if any, if we're
5063 * enabling/disabling import check. We
5064 * deregister the route
5065 * from NHT to avoid overloading NHT and the
5066 * process interaction
5068 bgp_unlink_nexthop(pi
);
5069 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
5071 /* Process change. */
5072 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5073 bgp_process(bgp
, rn
, afi
, safi
);
5075 if (SAFI_UNICAST
== safi
5076 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5078 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5079 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5083 bgp_unlock_node(rn
);
5084 aspath_unintern(&attr
.aspath
);
5089 /* Make new BGP info. */
5090 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5092 /* Nexthop reachability check. */
5093 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_IMPORT_CHECK
)
5094 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5095 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5096 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5098 if (BGP_DEBUG(nht
, NHT
)) {
5099 char buf1
[INET6_ADDRSTRLEN
];
5100 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5103 "%s(%s): Route not in table, not advertising",
5106 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
5109 /* Delete the NHT structure if any, if we're toggling between
5110 * enabling/disabling import check. We deregister the route
5111 * from NHT to avoid overloading NHT and the process interaction
5113 bgp_unlink_nexthop(new);
5115 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5118 /* Aggregate address increment. */
5119 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5121 /* Register new BGP information. */
5122 bgp_path_info_add(rn
, new);
5124 /* route_node_get lock */
5125 bgp_unlock_node(rn
);
5127 /* Process change. */
5128 bgp_process(bgp
, rn
, afi
, safi
);
5130 if (SAFI_UNICAST
== safi
5131 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5132 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5133 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5136 /* Unintern original. */
5137 aspath_unintern(&attr
.aspath
);
5140 void bgp_static_withdraw(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
5143 struct bgp_node
*rn
;
5144 struct bgp_path_info
*pi
;
5146 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5148 /* Check selected route and self inserted route. */
5149 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5150 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5151 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5154 /* Withdraw static BGP route from routing table. */
5156 if (SAFI_UNICAST
== safi
5157 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5158 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5159 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5161 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5162 bgp_unlink_nexthop(pi
);
5163 bgp_path_info_delete(rn
, pi
);
5164 bgp_process(bgp
, rn
, afi
, safi
);
5167 /* Unlock bgp_node_lookup. */
5168 bgp_unlock_node(rn
);
5172 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5174 static void bgp_static_withdraw_safi(struct bgp
*bgp
, const struct prefix
*p
,
5175 afi_t afi
, safi_t safi
,
5176 struct prefix_rd
*prd
)
5178 struct bgp_node
*rn
;
5179 struct bgp_path_info
*pi
;
5181 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5183 /* Check selected route and self inserted route. */
5184 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5185 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5186 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5189 /* Withdraw static BGP route from routing table. */
5192 rfapiProcessWithdraw(
5193 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5194 1); /* Kill, since it is an administrative change */
5196 if (SAFI_MPLS_VPN
== safi
5197 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5198 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5200 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5201 bgp_path_info_delete(rn
, pi
);
5202 bgp_process(bgp
, rn
, afi
, safi
);
5205 /* Unlock bgp_node_lookup. */
5206 bgp_unlock_node(rn
);
5209 static void bgp_static_update_safi(struct bgp
*bgp
, const struct prefix
*p
,
5210 struct bgp_static
*bgp_static
, afi_t afi
,
5213 struct bgp_node
*rn
;
5214 struct bgp_path_info
*new;
5215 struct attr
*attr_new
;
5216 struct attr attr
= {0};
5217 struct bgp_path_info
*pi
;
5219 mpls_label_t label
= 0;
5221 uint32_t num_labels
= 0;
5226 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5228 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5231 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5233 attr
.nexthop
= bgp_static
->igpnexthop
;
5234 attr
.med
= bgp_static
->igpmetric
;
5235 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5237 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5238 || (safi
== SAFI_ENCAP
)) {
5239 if (afi
== AFI_IP
) {
5240 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5241 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5244 if (afi
== AFI_L2VPN
) {
5245 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5247 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5248 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5249 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5250 sizeof(struct in6_addr
));
5251 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5252 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5253 struct bgp_encap_type_vxlan bet
;
5254 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5255 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5256 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5258 if (bgp_static
->router_mac
) {
5259 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5262 /* Apply route-map. */
5263 if (bgp_static
->rmap
.name
) {
5264 struct attr attr_tmp
= attr
;
5265 struct bgp_path_info rmap_path
;
5266 route_map_result_t ret
;
5268 rmap_path
.peer
= bgp
->peer_self
;
5269 rmap_path
.attr
= &attr_tmp
;
5271 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5273 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5276 bgp
->peer_self
->rmap_type
= 0;
5278 if (ret
== RMAP_DENYMATCH
) {
5279 /* Free uninterned attribute. */
5280 bgp_attr_flush(&attr_tmp
);
5282 /* Unintern original. */
5283 aspath_unintern(&attr
.aspath
);
5284 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5289 attr_new
= bgp_attr_intern(&attr_tmp
);
5291 attr_new
= bgp_attr_intern(&attr
);
5294 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5295 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5296 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5300 memset(&add
, 0, sizeof(union gw_addr
));
5301 if (attrhash_cmp(pi
->attr
, attr_new
)
5302 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5303 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5304 bgp_unlock_node(rn
);
5305 bgp_attr_unintern(&attr_new
);
5306 aspath_unintern(&attr
.aspath
);
5309 /* The attribute is changed. */
5310 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5312 /* Rewrite BGP route information. */
5313 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5314 bgp_path_info_restore(rn
, pi
);
5316 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5317 bgp_attr_unintern(&pi
->attr
);
5318 pi
->attr
= attr_new
;
5319 pi
->uptime
= bgp_clock();
5322 label
= decode_label(&pi
->extra
->label
[0]);
5325 /* Process change. */
5326 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5327 bgp_process(bgp
, rn
, afi
, safi
);
5329 if (SAFI_MPLS_VPN
== safi
5330 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5331 vpn_leak_to_vrf_update(bgp
, pi
);
5334 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5335 pi
->attr
, afi
, safi
, pi
->type
,
5336 pi
->sub_type
, &label
);
5338 bgp_unlock_node(rn
);
5339 aspath_unintern(&attr
.aspath
);
5345 /* Make new BGP info. */
5346 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5348 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5349 new->extra
= bgp_path_info_extra_new();
5351 new->extra
->label
[0] = bgp_static
->label
;
5352 new->extra
->num_labels
= num_labels
;
5355 label
= decode_label(&bgp_static
->label
);
5358 /* Aggregate address increment. */
5359 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5361 /* Register new BGP information. */
5362 bgp_path_info_add(rn
, new);
5363 /* route_node_get lock */
5364 bgp_unlock_node(rn
);
5366 /* Process change. */
5367 bgp_process(bgp
, rn
, afi
, safi
);
5369 if (SAFI_MPLS_VPN
== safi
5370 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5371 vpn_leak_to_vrf_update(bgp
, new);
5374 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5375 safi
, new->type
, new->sub_type
, &label
);
5378 /* Unintern original. */
5379 aspath_unintern(&attr
.aspath
);
5382 /* Configure static BGP network. When user don't run zebra, static
5383 route should be installed as valid. */
5384 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5385 const char *ip_str
, afi_t afi
, safi_t safi
,
5386 const char *rmap
, int backdoor
, uint32_t label_index
)
5388 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5391 struct bgp_static
*bgp_static
;
5392 struct bgp_node
*rn
;
5393 uint8_t need_update
= 0;
5395 /* Convert IP prefix string to struct prefix. */
5396 ret
= str2prefix(ip_str
, &p
);
5398 vty_out(vty
, "%% Malformed prefix\n");
5399 return CMD_WARNING_CONFIG_FAILED
;
5401 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5402 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5403 return CMD_WARNING_CONFIG_FAILED
;
5410 /* Set BGP static route configuration. */
5411 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5414 vty_out(vty
, "%% Can't find static route specified\n");
5415 return CMD_WARNING_CONFIG_FAILED
;
5418 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5420 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5421 && (label_index
!= bgp_static
->label_index
)) {
5423 "%% label-index doesn't match static route\n");
5424 return CMD_WARNING_CONFIG_FAILED
;
5427 if ((rmap
&& bgp_static
->rmap
.name
)
5428 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5430 "%% route-map name doesn't match static route\n");
5431 return CMD_WARNING_CONFIG_FAILED
;
5434 /* Update BGP RIB. */
5435 if (!bgp_static
->backdoor
)
5436 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5438 /* Clear configuration. */
5439 bgp_static_free(bgp_static
);
5440 bgp_node_set_bgp_static_info(rn
, NULL
);
5441 bgp_unlock_node(rn
);
5442 bgp_unlock_node(rn
);
5445 /* Set BGP static route configuration. */
5446 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5448 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5450 /* Configuration change. */
5451 /* Label index cannot be changed. */
5452 if (bgp_static
->label_index
!= label_index
) {
5453 vty_out(vty
, "%% cannot change label-index\n");
5454 return CMD_WARNING_CONFIG_FAILED
;
5457 /* Check previous routes are installed into BGP. */
5458 if (bgp_static
->valid
5459 && bgp_static
->backdoor
!= backdoor
)
5462 bgp_static
->backdoor
= backdoor
;
5465 XFREE(MTYPE_ROUTE_MAP_NAME
,
5466 bgp_static
->rmap
.name
);
5467 route_map_counter_decrement(
5468 bgp_static
->rmap
.map
);
5469 bgp_static
->rmap
.name
=
5470 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5471 bgp_static
->rmap
.map
=
5472 route_map_lookup_by_name(rmap
);
5473 route_map_counter_increment(
5474 bgp_static
->rmap
.map
);
5476 XFREE(MTYPE_ROUTE_MAP_NAME
,
5477 bgp_static
->rmap
.name
);
5478 route_map_counter_decrement(
5479 bgp_static
->rmap
.map
);
5480 bgp_static
->rmap
.map
= NULL
;
5481 bgp_static
->valid
= 0;
5483 bgp_unlock_node(rn
);
5485 /* New configuration. */
5486 bgp_static
= bgp_static_new();
5487 bgp_static
->backdoor
= backdoor
;
5488 bgp_static
->valid
= 0;
5489 bgp_static
->igpmetric
= 0;
5490 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5491 bgp_static
->label_index
= label_index
;
5494 XFREE(MTYPE_ROUTE_MAP_NAME
,
5495 bgp_static
->rmap
.name
);
5496 route_map_counter_decrement(
5497 bgp_static
->rmap
.map
);
5498 bgp_static
->rmap
.name
=
5499 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5500 bgp_static
->rmap
.map
=
5501 route_map_lookup_by_name(rmap
);
5502 route_map_counter_increment(
5503 bgp_static
->rmap
.map
);
5505 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5508 bgp_static
->valid
= 1;
5510 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5512 if (!bgp_static
->backdoor
)
5513 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5519 void bgp_static_add(struct bgp
*bgp
)
5523 struct bgp_node
*rn
;
5524 struct bgp_node
*rm
;
5525 struct bgp_table
*table
;
5526 struct bgp_static
*bgp_static
;
5528 FOREACH_AFI_SAFI (afi
, safi
)
5529 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5530 rn
= bgp_route_next(rn
)) {
5531 if (!bgp_node_has_bgp_path_info_data(rn
))
5534 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5535 || (safi
== SAFI_EVPN
)) {
5536 table
= bgp_node_get_bgp_table_info(rn
);
5538 for (rm
= bgp_table_top(table
); rm
;
5539 rm
= bgp_route_next(rm
)) {
5541 bgp_node_get_bgp_static_info(
5543 bgp_static_update_safi(bgp
,
5544 bgp_node_get_prefix(rm
),
5550 bgp
, bgp_node_get_prefix(rn
),
5551 bgp_node_get_bgp_static_info(rn
), afi
,
5557 /* Called from bgp_delete(). Delete all static routes from the BGP
5559 void bgp_static_delete(struct bgp
*bgp
)
5563 struct bgp_node
*rn
;
5564 struct bgp_node
*rm
;
5565 struct bgp_table
*table
;
5566 struct bgp_static
*bgp_static
;
5568 FOREACH_AFI_SAFI (afi
, safi
)
5569 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5570 rn
= bgp_route_next(rn
)) {
5571 if (!bgp_node_has_bgp_path_info_data(rn
))
5574 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5575 || (safi
== SAFI_EVPN
)) {
5576 table
= bgp_node_get_bgp_table_info(rn
);
5578 for (rm
= bgp_table_top(table
); rm
;
5579 rm
= bgp_route_next(rm
)) {
5581 bgp_node_get_bgp_static_info(
5586 bgp_static_withdraw_safi(
5587 bgp
, bgp_node_get_prefix(rm
),
5589 (struct prefix_rd
*)
5590 bgp_node_get_prefix(
5592 bgp_static_free(bgp_static
);
5593 bgp_node_set_bgp_static_info(rn
, NULL
);
5594 bgp_unlock_node(rn
);
5597 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5598 bgp_static_withdraw(bgp
,
5599 bgp_node_get_prefix(rn
),
5601 bgp_static_free(bgp_static
);
5602 bgp_node_set_bgp_static_info(rn
, NULL
);
5603 bgp_unlock_node(rn
);
5608 void bgp_static_redo_import_check(struct bgp
*bgp
)
5612 struct bgp_node
*rn
;
5613 struct bgp_node
*rm
;
5614 struct bgp_table
*table
;
5615 struct bgp_static
*bgp_static
;
5617 /* Use this flag to force reprocessing of the route */
5618 SET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5619 FOREACH_AFI_SAFI (afi
, safi
) {
5620 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5621 rn
= bgp_route_next(rn
)) {
5622 if (!bgp_node_has_bgp_path_info_data(rn
))
5625 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5626 || (safi
== SAFI_EVPN
)) {
5627 table
= bgp_node_get_bgp_table_info(rn
);
5629 for (rm
= bgp_table_top(table
); rm
;
5630 rm
= bgp_route_next(rm
)) {
5632 bgp_node_get_bgp_static_info(
5634 bgp_static_update_safi(bgp
,
5635 bgp_node_get_prefix(rm
),
5640 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5641 bgp_static_update(bgp
, bgp_node_get_prefix(rn
),
5647 UNSET_FLAG(bgp
->flags
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5650 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5653 struct bgp_table
*table
;
5654 struct bgp_node
*rn
;
5655 struct bgp_path_info
*pi
;
5657 /* Do not install the aggregate route if BGP is in the
5658 * process of termination.
5660 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
5661 || (bgp
->peer_self
== NULL
))
5664 table
= bgp
->rib
[afi
][safi
];
5665 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5666 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5667 if (pi
->peer
== bgp
->peer_self
5668 && ((pi
->type
== ZEBRA_ROUTE_BGP
5669 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5670 || (pi
->type
!= ZEBRA_ROUTE_BGP
5672 == BGP_ROUTE_REDISTRIBUTE
))) {
5673 bgp_aggregate_decrement(bgp
,
5674 bgp_node_get_prefix(rn
),
5676 bgp_unlink_nexthop(pi
);
5677 bgp_path_info_delete(rn
, pi
);
5678 bgp_process(bgp
, rn
, afi
, safi
);
5685 * Purge all networks and redistributed routes from routing table.
5686 * Invoked upon the instance going down.
5688 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5693 FOREACH_AFI_SAFI (afi
, safi
)
5694 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5699 * Currently this is used to set static routes for VPN and ENCAP.
5700 * I think it can probably be factored with bgp_static_set.
5702 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5703 const char *ip_str
, const char *rd_str
,
5704 const char *label_str
, const char *rmap_str
,
5705 int evpn_type
, const char *esi
, const char *gwip
,
5706 const char *ethtag
, const char *routermac
)
5708 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5711 struct prefix_rd prd
;
5712 struct bgp_node
*prn
;
5713 struct bgp_node
*rn
;
5714 struct bgp_table
*table
;
5715 struct bgp_static
*bgp_static
;
5716 mpls_label_t label
= MPLS_INVALID_LABEL
;
5717 struct prefix gw_ip
;
5719 /* validate ip prefix */
5720 ret
= str2prefix(ip_str
, &p
);
5722 vty_out(vty
, "%% Malformed prefix\n");
5723 return CMD_WARNING_CONFIG_FAILED
;
5726 if ((afi
== AFI_L2VPN
)
5727 && (bgp_build_evpn_prefix(evpn_type
,
5728 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5729 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5730 return CMD_WARNING_CONFIG_FAILED
;
5733 ret
= str2prefix_rd(rd_str
, &prd
);
5735 vty_out(vty
, "%% Malformed rd\n");
5736 return CMD_WARNING_CONFIG_FAILED
;
5740 unsigned long label_val
;
5741 label_val
= strtoul(label_str
, NULL
, 10);
5742 encode_label(label_val
, &label
);
5745 if (safi
== SAFI_EVPN
) {
5746 if (esi
&& str2esi(esi
, NULL
) == 0) {
5747 vty_out(vty
, "%% Malformed ESI\n");
5748 return CMD_WARNING_CONFIG_FAILED
;
5750 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5751 vty_out(vty
, "%% Malformed Router MAC\n");
5752 return CMD_WARNING_CONFIG_FAILED
;
5755 memset(&gw_ip
, 0, sizeof(struct prefix
));
5756 ret
= str2prefix(gwip
, &gw_ip
);
5758 vty_out(vty
, "%% Malformed GatewayIp\n");
5759 return CMD_WARNING_CONFIG_FAILED
;
5761 if ((gw_ip
.family
== AF_INET
5762 && is_evpn_prefix_ipaddr_v6(
5763 (struct prefix_evpn
*)&p
))
5764 || (gw_ip
.family
== AF_INET6
5765 && is_evpn_prefix_ipaddr_v4(
5766 (struct prefix_evpn
*)&p
))) {
5768 "%% GatewayIp family differs with IP prefix\n");
5769 return CMD_WARNING_CONFIG_FAILED
;
5773 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5774 if (!bgp_node_has_bgp_path_info_data(prn
))
5775 bgp_node_set_bgp_table_info(prn
,
5776 bgp_table_init(bgp
, afi
, safi
));
5777 table
= bgp_node_get_bgp_table_info(prn
);
5779 rn
= bgp_node_get(table
, &p
);
5781 if (bgp_node_has_bgp_path_info_data(rn
)) {
5782 vty_out(vty
, "%% Same network configuration exists\n");
5783 bgp_unlock_node(rn
);
5785 /* New configuration. */
5786 bgp_static
= bgp_static_new();
5787 bgp_static
->backdoor
= 0;
5788 bgp_static
->valid
= 0;
5789 bgp_static
->igpmetric
= 0;
5790 bgp_static
->igpnexthop
.s_addr
= INADDR_ANY
;
5791 bgp_static
->label
= label
;
5792 bgp_static
->prd
= prd
;
5795 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5796 route_map_counter_decrement(bgp_static
->rmap
.map
);
5797 bgp_static
->rmap
.name
=
5798 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5799 bgp_static
->rmap
.map
=
5800 route_map_lookup_by_name(rmap_str
);
5801 route_map_counter_increment(bgp_static
->rmap
.map
);
5804 if (safi
== SAFI_EVPN
) {
5806 bgp_static
->eth_s_id
=
5808 sizeof(struct eth_segment_id
));
5809 str2esi(esi
, bgp_static
->eth_s_id
);
5812 bgp_static
->router_mac
=
5813 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5814 (void)prefix_str2mac(routermac
,
5815 bgp_static
->router_mac
);
5818 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5820 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5822 bgp_static
->valid
= 1;
5823 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5829 /* Configure static BGP network. */
5830 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5831 const char *ip_str
, const char *rd_str
,
5832 const char *label_str
, int evpn_type
, const char *esi
,
5833 const char *gwip
, const char *ethtag
)
5835 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5838 struct prefix_rd prd
;
5839 struct bgp_node
*prn
;
5840 struct bgp_node
*rn
;
5841 struct bgp_table
*table
;
5842 struct bgp_static
*bgp_static
;
5843 mpls_label_t label
= MPLS_INVALID_LABEL
;
5845 /* Convert IP prefix string to struct prefix. */
5846 ret
= str2prefix(ip_str
, &p
);
5848 vty_out(vty
, "%% Malformed prefix\n");
5849 return CMD_WARNING_CONFIG_FAILED
;
5852 if ((afi
== AFI_L2VPN
)
5853 && (bgp_build_evpn_prefix(evpn_type
,
5854 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5855 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5856 return CMD_WARNING_CONFIG_FAILED
;
5858 ret
= str2prefix_rd(rd_str
, &prd
);
5860 vty_out(vty
, "%% Malformed rd\n");
5861 return CMD_WARNING_CONFIG_FAILED
;
5865 unsigned long label_val
;
5866 label_val
= strtoul(label_str
, NULL
, 10);
5867 encode_label(label_val
, &label
);
5870 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5871 if (!bgp_node_has_bgp_path_info_data(prn
))
5872 bgp_node_set_bgp_table_info(prn
,
5873 bgp_table_init(bgp
, afi
, safi
));
5875 bgp_unlock_node(prn
);
5876 table
= bgp_node_get_bgp_table_info(prn
);
5878 rn
= bgp_node_lookup(table
, &p
);
5881 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5883 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5884 bgp_static_free(bgp_static
);
5885 bgp_node_set_bgp_static_info(rn
, NULL
);
5886 bgp_unlock_node(rn
);
5887 bgp_unlock_node(rn
);
5889 vty_out(vty
, "%% Can't find the route\n");
5894 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5895 const char *rmap_name
)
5897 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5898 struct bgp_rmap
*rmap
;
5900 rmap
= &bgp
->table_map
[afi
][safi
];
5902 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5903 route_map_counter_decrement(rmap
->map
);
5904 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5905 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5906 route_map_counter_increment(rmap
->map
);
5908 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5909 route_map_counter_decrement(rmap
->map
);
5913 if (bgp_fibupd_safi(safi
))
5914 bgp_zebra_announce_table(bgp
, afi
, safi
);
5919 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5920 const char *rmap_name
)
5922 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5923 struct bgp_rmap
*rmap
;
5925 rmap
= &bgp
->table_map
[afi
][safi
];
5926 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5927 route_map_counter_decrement(rmap
->map
);
5930 if (bgp_fibupd_safi(safi
))
5931 bgp_zebra_announce_table(bgp
, afi
, safi
);
5936 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5939 if (bgp
->table_map
[afi
][safi
].name
) {
5940 vty_out(vty
, " table-map %s\n",
5941 bgp
->table_map
[afi
][safi
].name
);
5945 DEFUN (bgp_table_map
,
5948 "BGP table to RIB route download filter\n"
5949 "Name of the route map\n")
5952 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5953 argv
[idx_word
]->arg
);
5955 DEFUN (no_bgp_table_map
,
5956 no_bgp_table_map_cmd
,
5957 "no table-map WORD",
5959 "BGP table to RIB route download filter\n"
5960 "Name of the route map\n")
5963 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5964 argv
[idx_word
]->arg
);
5970 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5971 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5972 backdoor$backdoor}]",
5974 "Specify a network to announce via BGP\n"
5979 "Route-map to modify the attributes\n"
5980 "Name of the route map\n"
5981 "Label index to associate with the prefix\n"
5982 "Label index value\n"
5983 "Specify a BGP backdoor route\n")
5985 char addr_prefix_str
[BUFSIZ
];
5990 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5993 vty_out(vty
, "%% Inconsistent address and mask\n");
5994 return CMD_WARNING_CONFIG_FAILED
;
5998 return bgp_static_set(
5999 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
6000 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
6001 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6004 DEFPY(ipv6_bgp_network
,
6005 ipv6_bgp_network_cmd
,
6006 "[no] network X:X::X:X/M$prefix \
6007 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6009 "Specify a network to announce via BGP\n"
6011 "Route-map to modify the attributes\n"
6012 "Name of the route map\n"
6013 "Label index to associate with the prefix\n"
6014 "Label index value\n")
6016 return bgp_static_set(
6017 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6018 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6021 static struct bgp_aggregate
*bgp_aggregate_new(void)
6023 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6026 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6028 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6029 route_map_counter_decrement(aggregate
->rmap
.map
);
6030 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6033 static bool bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6034 struct aspath
*aspath
,
6035 struct community
*comm
,
6036 struct ecommunity
*ecomm
,
6037 struct lcommunity
*lcomm
)
6039 static struct aspath
*ae
= NULL
;
6042 ae
= aspath_empty();
6047 if (origin
!= pi
->attr
->origin
)
6050 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6053 if (!community_cmp(pi
->attr
->community
, comm
))
6056 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6059 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6062 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6068 static void bgp_aggregate_install(
6069 struct bgp
*bgp
, afi_t afi
, safi_t safi
, const struct prefix
*p
,
6070 uint8_t origin
, struct aspath
*aspath
, struct community
*community
,
6071 struct ecommunity
*ecommunity
, struct lcommunity
*lcommunity
,
6072 uint8_t atomic_aggregate
, struct bgp_aggregate
*aggregate
)
6074 struct bgp_node
*rn
;
6075 struct bgp_table
*table
;
6076 struct bgp_path_info
*pi
, *orig
, *new;
6079 table
= bgp
->rib
[afi
][safi
];
6081 rn
= bgp_node_get(table
, p
);
6083 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6084 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6085 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6088 if (aggregate
->count
> 0) {
6090 * If the aggregate information has not changed
6091 * no need to re-install it again.
6093 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6094 ecommunity
, lcommunity
)) {
6095 bgp_unlock_node(rn
);
6098 aspath_free(aspath
);
6100 community_free(&community
);
6102 ecommunity_free(&ecommunity
);
6104 lcommunity_free(&lcommunity
);
6110 * Mark the old as unusable
6113 bgp_path_info_delete(rn
, pi
);
6115 attr
= bgp_attr_aggregate_intern(
6116 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6117 aggregate
, atomic_aggregate
, p
);
6120 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6124 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6125 bgp
->peer_self
, attr
, rn
);
6127 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6129 bgp_path_info_add(rn
, new);
6130 bgp_process(bgp
, rn
, afi
, safi
);
6132 for (pi
= orig
; pi
; pi
= pi
->next
)
6133 if (pi
->peer
== bgp
->peer_self
6134 && pi
->type
== ZEBRA_ROUTE_BGP
6135 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6138 /* Withdraw static BGP route from routing table. */
6140 bgp_path_info_delete(rn
, pi
);
6141 bgp_process(bgp
, rn
, afi
, safi
);
6145 bgp_unlock_node(rn
);
6148 /* Update an aggregate as routes are added/removed from the BGP table */
6149 void bgp_aggregate_route(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6150 safi_t safi
, struct bgp_aggregate
*aggregate
)
6152 struct bgp_table
*table
;
6153 struct bgp_node
*top
;
6154 struct bgp_node
*rn
;
6156 struct aspath
*aspath
= NULL
;
6157 struct community
*community
= NULL
;
6158 struct ecommunity
*ecommunity
= NULL
;
6159 struct lcommunity
*lcommunity
= NULL
;
6160 struct bgp_path_info
*pi
;
6161 unsigned long match
= 0;
6162 uint8_t atomic_aggregate
= 0;
6164 /* If the bgp instance is being deleted or self peer is deleted
6165 * then do not create aggregate route
6167 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_DELETE_IN_PROGRESS
)
6168 || (bgp
->peer_self
== NULL
))
6171 /* ORIGIN attribute: If at least one route among routes that are
6172 aggregated has ORIGIN with the value INCOMPLETE, then the
6173 aggregated route must have the ORIGIN attribute with the value
6174 INCOMPLETE. Otherwise, if at least one route among routes that
6175 are aggregated has ORIGIN with the value EGP, then the aggregated
6176 route must have the origin attribute with the value EGP. In all
6177 other case the value of the ORIGIN attribute of the aggregated
6178 route is INTERNAL. */
6179 origin
= BGP_ORIGIN_IGP
;
6181 table
= bgp
->rib
[afi
][safi
];
6183 top
= bgp_node_get(table
, p
);
6184 for (rn
= bgp_node_get(table
, p
); rn
;
6185 rn
= bgp_route_next_until(rn
, top
)) {
6186 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
6188 if (rn_p
->prefixlen
<= p
->prefixlen
)
6193 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6194 if (BGP_PATH_HOLDDOWN(pi
))
6198 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6199 atomic_aggregate
= 1;
6201 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6205 * summary-only aggregate route suppress
6206 * aggregated route announcements.
6208 if (aggregate
->summary_only
) {
6209 (bgp_path_info_extra_get(pi
))->suppress
++;
6210 bgp_path_info_set_flag(rn
, pi
,
6211 BGP_PATH_ATTR_CHANGED
);
6218 * If at least one route among routes that are
6219 * aggregated has ORIGIN with the value INCOMPLETE,
6220 * then the aggregated route MUST have the ORIGIN
6221 * attribute with the value INCOMPLETE. Otherwise, if
6222 * at least one route among routes that are aggregated
6223 * has ORIGIN with the value EGP, then the aggregated
6224 * route MUST have the ORIGIN attribute with the value
6227 switch (pi
->attr
->origin
) {
6228 case BGP_ORIGIN_INCOMPLETE
:
6229 aggregate
->incomplete_origin_count
++;
6231 case BGP_ORIGIN_EGP
:
6232 aggregate
->egp_origin_count
++;
6240 if (!aggregate
->as_set
)
6244 * as-set aggregate route generate origin, as path,
6245 * and community aggregation.
6247 /* Compute aggregate route's as-path.
6249 bgp_compute_aggregate_aspath_hash(aggregate
,
6252 /* Compute aggregate route's community.
6254 if (pi
->attr
->community
)
6255 bgp_compute_aggregate_community_hash(
6257 pi
->attr
->community
);
6259 /* Compute aggregate route's extended community.
6261 if (pi
->attr
->ecommunity
)
6262 bgp_compute_aggregate_ecommunity_hash(
6264 pi
->attr
->ecommunity
);
6266 /* Compute aggregate route's large community.
6268 if (pi
->attr
->lcommunity
)
6269 bgp_compute_aggregate_lcommunity_hash(
6271 pi
->attr
->lcommunity
);
6274 bgp_process(bgp
, rn
, afi
, safi
);
6276 if (aggregate
->as_set
) {
6277 bgp_compute_aggregate_aspath_val(aggregate
);
6278 bgp_compute_aggregate_community_val(aggregate
);
6279 bgp_compute_aggregate_ecommunity_val(aggregate
);
6280 bgp_compute_aggregate_lcommunity_val(aggregate
);
6284 bgp_unlock_node(top
);
6287 if (aggregate
->incomplete_origin_count
> 0)
6288 origin
= BGP_ORIGIN_INCOMPLETE
;
6289 else if (aggregate
->egp_origin_count
> 0)
6290 origin
= BGP_ORIGIN_EGP
;
6292 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6293 origin
= aggregate
->origin
;
6295 if (aggregate
->as_set
) {
6296 if (aggregate
->aspath
)
6297 /* Retrieve aggregate route's as-path.
6299 aspath
= aspath_dup(aggregate
->aspath
);
6301 if (aggregate
->community
)
6302 /* Retrieve aggregate route's community.
6304 community
= community_dup(aggregate
->community
);
6306 if (aggregate
->ecommunity
)
6307 /* Retrieve aggregate route's ecommunity.
6309 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6311 if (aggregate
->lcommunity
)
6312 /* Retrieve aggregate route's lcommunity.
6314 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6317 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6318 ecommunity
, lcommunity
, atomic_aggregate
,
6322 void bgp_aggregate_delete(struct bgp
*bgp
, const struct prefix
*p
, afi_t afi
,
6323 safi_t safi
, struct bgp_aggregate
*aggregate
)
6325 struct bgp_table
*table
;
6326 struct bgp_node
*top
;
6327 struct bgp_node
*rn
;
6328 struct bgp_path_info
*pi
;
6329 unsigned long match
;
6331 table
= bgp
->rib
[afi
][safi
];
6333 /* If routes exists below this node, generate aggregate routes. */
6334 top
= bgp_node_get(table
, p
);
6335 for (rn
= bgp_node_get(table
, p
); rn
;
6336 rn
= bgp_route_next_until(rn
, top
)) {
6337 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
6339 if (rn_p
->prefixlen
<= p
->prefixlen
)
6343 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6344 if (BGP_PATH_HOLDDOWN(pi
))
6347 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6350 if (aggregate
->summary_only
&& pi
->extra
) {
6351 pi
->extra
->suppress
--;
6353 if (pi
->extra
->suppress
== 0) {
6354 bgp_path_info_set_flag(
6355 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6361 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6362 aggregate
->incomplete_origin_count
--;
6363 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6364 aggregate
->egp_origin_count
--;
6366 if (aggregate
->as_set
) {
6367 /* Remove as-path from aggregate.
6369 bgp_remove_aspath_from_aggregate_hash(
6373 if (pi
->attr
->community
)
6374 /* Remove community from aggregate.
6376 bgp_remove_comm_from_aggregate_hash(
6378 pi
->attr
->community
);
6380 if (pi
->attr
->ecommunity
)
6381 /* Remove ecommunity from aggregate.
6383 bgp_remove_ecomm_from_aggregate_hash(
6385 pi
->attr
->ecommunity
);
6387 if (pi
->attr
->lcommunity
)
6388 /* Remove lcommunity from aggregate.
6390 bgp_remove_lcomm_from_aggregate_hash(
6392 pi
->attr
->lcommunity
);
6397 /* If this node was suppressed, process the change. */
6399 bgp_process(bgp
, rn
, afi
, safi
);
6401 if (aggregate
->as_set
) {
6402 aspath_free(aggregate
->aspath
);
6403 aggregate
->aspath
= NULL
;
6404 if (aggregate
->community
)
6405 community_free(&aggregate
->community
);
6406 if (aggregate
->ecommunity
)
6407 ecommunity_free(&aggregate
->ecommunity
);
6408 if (aggregate
->lcommunity
)
6409 lcommunity_free(&aggregate
->lcommunity
);
6412 bgp_unlock_node(top
);
6415 static void bgp_add_route_to_aggregate(struct bgp
*bgp
,
6416 const struct prefix
*aggr_p
,
6417 struct bgp_path_info
*pinew
, afi_t afi
,
6419 struct bgp_aggregate
*aggregate
)
6422 struct aspath
*aspath
= NULL
;
6423 uint8_t atomic_aggregate
= 0;
6424 struct community
*community
= NULL
;
6425 struct ecommunity
*ecommunity
= NULL
;
6426 struct lcommunity
*lcommunity
= NULL
;
6428 /* ORIGIN attribute: If at least one route among routes that are
6429 * aggregated has ORIGIN with the value INCOMPLETE, then the
6430 * aggregated route must have the ORIGIN attribute with the value
6431 * INCOMPLETE. Otherwise, if at least one route among routes that
6432 * are aggregated has ORIGIN with the value EGP, then the aggregated
6433 * route must have the origin attribute with the value EGP. In all
6434 * other case the value of the ORIGIN attribute of the aggregated
6435 * route is INTERNAL.
6437 origin
= BGP_ORIGIN_IGP
;
6441 if (aggregate
->summary_only
)
6442 (bgp_path_info_extra_get(pinew
))->suppress
++;
6444 switch (pinew
->attr
->origin
) {
6445 case BGP_ORIGIN_INCOMPLETE
:
6446 aggregate
->incomplete_origin_count
++;
6448 case BGP_ORIGIN_EGP
:
6449 aggregate
->egp_origin_count
++;
6457 if (aggregate
->incomplete_origin_count
> 0)
6458 origin
= BGP_ORIGIN_INCOMPLETE
;
6459 else if (aggregate
->egp_origin_count
> 0)
6460 origin
= BGP_ORIGIN_EGP
;
6462 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6463 origin
= aggregate
->origin
;
6465 if (aggregate
->as_set
) {
6466 /* Compute aggregate route's as-path.
6468 bgp_compute_aggregate_aspath(aggregate
,
6469 pinew
->attr
->aspath
);
6471 /* Compute aggregate route's community.
6473 if (pinew
->attr
->community
)
6474 bgp_compute_aggregate_community(
6476 pinew
->attr
->community
);
6478 /* Compute aggregate route's extended community.
6480 if (pinew
->attr
->ecommunity
)
6481 bgp_compute_aggregate_ecommunity(
6483 pinew
->attr
->ecommunity
);
6485 /* Compute aggregate route's large community.
6487 if (pinew
->attr
->lcommunity
)
6488 bgp_compute_aggregate_lcommunity(
6490 pinew
->attr
->lcommunity
);
6492 /* Retrieve aggregate route's as-path.
6494 if (aggregate
->aspath
)
6495 aspath
= aspath_dup(aggregate
->aspath
);
6497 /* Retrieve aggregate route's community.
6499 if (aggregate
->community
)
6500 community
= community_dup(aggregate
->community
);
6502 /* Retrieve aggregate route's ecommunity.
6504 if (aggregate
->ecommunity
)
6505 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6507 /* Retrieve aggregate route's lcommunity.
6509 if (aggregate
->lcommunity
)
6510 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6513 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6514 aspath
, community
, ecommunity
,
6515 lcommunity
, atomic_aggregate
, aggregate
);
6518 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6520 struct bgp_path_info
*pi
,
6521 struct bgp_aggregate
*aggregate
,
6522 const struct prefix
*aggr_p
)
6525 struct aspath
*aspath
= NULL
;
6526 uint8_t atomic_aggregate
= 0;
6527 struct community
*community
= NULL
;
6528 struct ecommunity
*ecommunity
= NULL
;
6529 struct lcommunity
*lcommunity
= NULL
;
6530 unsigned long match
= 0;
6532 if (BGP_PATH_HOLDDOWN(pi
))
6535 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6538 if (aggregate
->summary_only
6540 && pi
->extra
->suppress
> 0) {
6541 pi
->extra
->suppress
--;
6543 if (pi
->extra
->suppress
== 0) {
6544 bgp_path_info_set_flag(pi
->net
, pi
,
6545 BGP_PATH_ATTR_CHANGED
);
6550 if (aggregate
->count
> 0)
6553 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6554 aggregate
->incomplete_origin_count
--;
6555 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6556 aggregate
->egp_origin_count
--;
6558 if (aggregate
->as_set
) {
6559 /* Remove as-path from aggregate.
6561 bgp_remove_aspath_from_aggregate(aggregate
,
6564 if (pi
->attr
->community
)
6565 /* Remove community from aggregate.
6567 bgp_remove_community_from_aggregate(
6569 pi
->attr
->community
);
6571 if (pi
->attr
->ecommunity
)
6572 /* Remove ecommunity from aggregate.
6574 bgp_remove_ecommunity_from_aggregate(
6576 pi
->attr
->ecommunity
);
6578 if (pi
->attr
->lcommunity
)
6579 /* Remove lcommunity from aggregate.
6581 bgp_remove_lcommunity_from_aggregate(
6583 pi
->attr
->lcommunity
);
6586 /* If this node was suppressed, process the change. */
6588 bgp_process(bgp
, pi
->net
, afi
, safi
);
6590 origin
= BGP_ORIGIN_IGP
;
6591 if (aggregate
->incomplete_origin_count
> 0)
6592 origin
= BGP_ORIGIN_INCOMPLETE
;
6593 else if (aggregate
->egp_origin_count
> 0)
6594 origin
= BGP_ORIGIN_EGP
;
6596 if (aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
6597 origin
= aggregate
->origin
;
6599 if (aggregate
->as_set
) {
6600 /* Retrieve aggregate route's as-path.
6602 if (aggregate
->aspath
)
6603 aspath
= aspath_dup(aggregate
->aspath
);
6605 /* Retrieve aggregate route's community.
6607 if (aggregate
->community
)
6608 community
= community_dup(aggregate
->community
);
6610 /* Retrieve aggregate route's ecommunity.
6612 if (aggregate
->ecommunity
)
6613 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6615 /* Retrieve aggregate route's lcommunity.
6617 if (aggregate
->lcommunity
)
6618 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6621 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6622 aspath
, community
, ecommunity
,
6623 lcommunity
, atomic_aggregate
, aggregate
);
6626 void bgp_aggregate_increment(struct bgp
*bgp
, const struct prefix
*p
,
6627 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6629 struct bgp_node
*child
;
6630 struct bgp_node
*rn
;
6631 struct bgp_aggregate
*aggregate
;
6632 struct bgp_table
*table
;
6634 table
= bgp
->aggregate
[afi
][safi
];
6636 /* No aggregates configured. */
6637 if (bgp_table_top_nolock(table
) == NULL
)
6640 if (p
->prefixlen
== 0)
6643 if (BGP_PATH_HOLDDOWN(pi
))
6646 child
= bgp_node_get(table
, p
);
6648 /* Aggregate address configuration check. */
6649 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6650 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
6652 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6653 if (aggregate
!= NULL
&& rn_p
->prefixlen
< p
->prefixlen
) {
6654 bgp_add_route_to_aggregate(bgp
, rn_p
, pi
, afi
, safi
,
6658 bgp_unlock_node(child
);
6661 void bgp_aggregate_decrement(struct bgp
*bgp
, const struct prefix
*p
,
6662 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6664 struct bgp_node
*child
;
6665 struct bgp_node
*rn
;
6666 struct bgp_aggregate
*aggregate
;
6667 struct bgp_table
*table
;
6669 table
= bgp
->aggregate
[afi
][safi
];
6671 /* No aggregates configured. */
6672 if (bgp_table_top_nolock(table
) == NULL
)
6675 if (p
->prefixlen
== 0)
6678 child
= bgp_node_get(table
, p
);
6680 /* Aggregate address configuration check. */
6681 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6682 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
6684 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6685 if (aggregate
!= NULL
&& rn_p
->prefixlen
< p
->prefixlen
) {
6686 bgp_remove_route_from_aggregate(bgp
, afi
, safi
, del
,
6690 bgp_unlock_node(child
);
6693 /* Aggregate route attribute. */
6694 #define AGGREGATE_SUMMARY_ONLY 1
6695 #define AGGREGATE_AS_SET 1
6696 #define AGGREGATE_AS_UNSET 0
6698 static const char *bgp_origin2str(uint8_t origin
)
6701 case BGP_ORIGIN_IGP
:
6703 case BGP_ORIGIN_EGP
:
6705 case BGP_ORIGIN_INCOMPLETE
:
6706 return "incomplete";
6711 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6712 afi_t afi
, safi_t safi
)
6714 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6717 struct bgp_node
*rn
;
6718 struct bgp_aggregate
*aggregate
;
6720 /* Convert string to prefix structure. */
6721 ret
= str2prefix(prefix_str
, &p
);
6723 vty_out(vty
, "Malformed prefix\n");
6724 return CMD_WARNING_CONFIG_FAILED
;
6728 /* Old configuration check. */
6729 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6732 "%% There is no aggregate-address configuration.\n");
6733 return CMD_WARNING_CONFIG_FAILED
;
6736 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6737 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6738 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6739 NULL
, NULL
, 0, aggregate
);
6741 /* Unlock aggregate address configuration. */
6742 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6744 if (aggregate
->community
)
6745 community_free(&aggregate
->community
);
6747 if (aggregate
->community_hash
) {
6748 /* Delete all communities in the hash.
6750 hash_clean(aggregate
->community_hash
,
6751 bgp_aggr_community_remove
);
6752 /* Free up the community_hash.
6754 hash_free(aggregate
->community_hash
);
6757 if (aggregate
->ecommunity
)
6758 ecommunity_free(&aggregate
->ecommunity
);
6760 if (aggregate
->ecommunity_hash
) {
6761 /* Delete all ecommunities in the hash.
6763 hash_clean(aggregate
->ecommunity_hash
,
6764 bgp_aggr_ecommunity_remove
);
6765 /* Free up the ecommunity_hash.
6767 hash_free(aggregate
->ecommunity_hash
);
6770 if (aggregate
->lcommunity
)
6771 lcommunity_free(&aggregate
->lcommunity
);
6773 if (aggregate
->lcommunity_hash
) {
6774 /* Delete all lcommunities in the hash.
6776 hash_clean(aggregate
->lcommunity_hash
,
6777 bgp_aggr_lcommunity_remove
);
6778 /* Free up the lcommunity_hash.
6780 hash_free(aggregate
->lcommunity_hash
);
6783 if (aggregate
->aspath
)
6784 aspath_free(aggregate
->aspath
);
6786 if (aggregate
->aspath_hash
) {
6787 /* Delete all as-paths in the hash.
6789 hash_clean(aggregate
->aspath_hash
,
6790 bgp_aggr_aspath_remove
);
6791 /* Free up the aspath_hash.
6793 hash_free(aggregate
->aspath_hash
);
6796 bgp_aggregate_free(aggregate
);
6797 bgp_unlock_node(rn
);
6798 bgp_unlock_node(rn
);
6803 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6804 safi_t safi
, const char *rmap
,
6805 uint8_t summary_only
, uint8_t as_set
,
6808 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6811 struct bgp_node
*rn
;
6812 struct bgp_aggregate
*aggregate
;
6813 uint8_t as_set_new
= as_set
;
6815 /* Convert string to prefix structure. */
6816 ret
= str2prefix(prefix_str
, &p
);
6818 vty_out(vty
, "Malformed prefix\n");
6819 return CMD_WARNING_CONFIG_FAILED
;
6823 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6824 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6825 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6827 return CMD_WARNING_CONFIG_FAILED
;
6830 /* Old configuration check. */
6831 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6832 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6835 vty_out(vty
, "There is already same aggregate network.\n");
6836 /* try to remove the old entry */
6837 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6839 vty_out(vty
, "Error deleting aggregate.\n");
6840 bgp_unlock_node(rn
);
6841 return CMD_WARNING_CONFIG_FAILED
;
6845 /* Make aggregate address structure. */
6846 aggregate
= bgp_aggregate_new();
6847 aggregate
->summary_only
= summary_only
;
6849 /* Network operators MUST NOT locally generate any new
6850 * announcements containing AS_SET or AS_CONFED_SET. If they have
6851 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6852 * SHOULD withdraw those routes and re-announce routes for the
6853 * aggregate or component prefixes (i.e., the more-specific routes
6854 * subsumed by the previously aggregated route) without AS_SET
6855 * or AS_CONFED_SET in the updates.
6857 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6858 if (as_set
== AGGREGATE_AS_SET
) {
6859 as_set_new
= AGGREGATE_AS_UNSET
;
6861 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
6864 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6868 aggregate
->as_set
= as_set_new
;
6869 aggregate
->safi
= safi
;
6870 /* Override ORIGIN attribute if defined.
6871 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
6872 * to IGP which is not what rfc4271 says.
6873 * This enables the same behavior, optionally.
6875 aggregate
->origin
= origin
;
6878 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6879 route_map_counter_decrement(aggregate
->rmap
.map
);
6880 aggregate
->rmap
.name
=
6881 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6882 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6883 route_map_counter_increment(aggregate
->rmap
.map
);
6885 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6887 /* Aggregate address insert into BGP routing table. */
6888 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6893 DEFUN (aggregate_address
,
6894 aggregate_address_cmd
,
6895 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
6896 "Configure BGP aggregate entries\n"
6897 "Aggregate prefix\n"
6898 "Generate AS set path information\n"
6899 "Filter more specific routes from updates\n"
6900 "Filter more specific routes from updates\n"
6901 "Generate AS set path information\n"
6902 "Apply route map to aggregate network\n"
6903 "Name of route map\n"
6907 "Unknown heritage\n")
6910 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6911 char *prefix
= argv
[idx
]->arg
;
6913 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
6914 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6915 : AGGREGATE_AS_UNSET
;
6917 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6918 ? AGGREGATE_SUMMARY_ONLY
6922 argv_find(argv
, argc
, "WORD", &idx
);
6924 rmap
= argv
[idx
]->arg
;
6927 if (argv_find(argv
, argc
, "origin", &idx
)) {
6928 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
6929 origin
= BGP_ORIGIN_IGP
;
6930 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
6931 origin
= BGP_ORIGIN_EGP
;
6932 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
6933 origin
= BGP_ORIGIN_INCOMPLETE
;
6936 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
), rmap
,
6937 summary_only
, as_set
, origin
);
6940 DEFUN (aggregate_address_mask
,
6941 aggregate_address_mask_cmd
,
6942 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
6943 "Configure BGP aggregate entries\n"
6944 "Aggregate address\n"
6946 "Generate AS set path information\n"
6947 "Filter more specific routes from updates\n"
6948 "Filter more specific routes from updates\n"
6949 "Generate AS set path information\n"
6950 "Apply route map to aggregate network\n"
6951 "Name of route map\n"
6955 "Unknown heritage\n")
6958 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6959 char *prefix
= argv
[idx
]->arg
;
6960 char *mask
= argv
[idx
+ 1]->arg
;
6963 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
6964 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6965 : AGGREGATE_AS_UNSET
;
6967 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6968 ? AGGREGATE_SUMMARY_ONLY
6971 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6973 rmap
= argv
[idx
]->arg
;
6975 char prefix_str
[BUFSIZ
];
6976 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6979 vty_out(vty
, "%% Inconsistent address and mask\n");
6980 return CMD_WARNING_CONFIG_FAILED
;
6984 if (argv_find(argv
, argc
, "origin", &idx
)) {
6985 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
6986 origin
= BGP_ORIGIN_IGP
;
6987 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
6988 origin
= BGP_ORIGIN_EGP
;
6989 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
6990 origin
= BGP_ORIGIN_INCOMPLETE
;
6993 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6994 rmap
, summary_only
, as_set
, origin
);
6997 DEFUN (no_aggregate_address
,
6998 no_aggregate_address_cmd
,
6999 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7001 "Configure BGP aggregate entries\n"
7002 "Aggregate prefix\n"
7003 "Generate AS set path information\n"
7004 "Filter more specific routes from updates\n"
7005 "Filter more specific routes from updates\n"
7006 "Generate AS set path information\n"
7007 "Apply route map to aggregate network\n"
7008 "Name of route map\n"
7012 "Unknown heritage\n")
7015 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
7016 char *prefix
= argv
[idx
]->arg
;
7017 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
7020 DEFUN (no_aggregate_address_mask
,
7021 no_aggregate_address_mask_cmd
,
7022 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7024 "Configure BGP aggregate entries\n"
7025 "Aggregate address\n"
7027 "Generate AS set path information\n"
7028 "Filter more specific routes from updates\n"
7029 "Filter more specific routes from updates\n"
7030 "Generate AS set path information\n"
7031 "Apply route map to aggregate network\n"
7032 "Name of route map\n"
7036 "Unknown heritage\n")
7039 argv_find(argv
, argc
, "A.B.C.D", &idx
);
7040 char *prefix
= argv
[idx
]->arg
;
7041 char *mask
= argv
[idx
+ 1]->arg
;
7043 char prefix_str
[BUFSIZ
];
7044 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
7047 vty_out(vty
, "%% Inconsistent address and mask\n");
7048 return CMD_WARNING_CONFIG_FAILED
;
7051 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
7054 DEFUN (ipv6_aggregate_address
,
7055 ipv6_aggregate_address_cmd
,
7056 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7057 "Configure BGP aggregate entries\n"
7058 "Aggregate prefix\n"
7059 "Generate AS set path information\n"
7060 "Filter more specific routes from updates\n"
7061 "Filter more specific routes from updates\n"
7062 "Generate AS set path information\n"
7063 "Apply route map to aggregate network\n"
7064 "Name of route map\n"
7068 "Unknown heritage\n")
7071 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7072 char *prefix
= argv
[idx
]->arg
;
7075 uint8_t origin
= BGP_ORIGIN_UNSPECIFIED
;
7076 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
7077 : AGGREGATE_AS_UNSET
;
7080 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
7081 ? AGGREGATE_SUMMARY_ONLY
7084 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
7086 rmap
= argv
[idx
]->arg
;
7089 if (argv_find(argv
, argc
, "origin", &idx
)) {
7090 if (strncmp(argv
[idx
+ 1]->arg
, "igp", 2) == 0)
7091 origin
= BGP_ORIGIN_IGP
;
7092 if (strncmp(argv
[idx
+ 1]->arg
, "egp", 1) == 0)
7093 origin
= BGP_ORIGIN_EGP
;
7094 if (strncmp(argv
[idx
+ 1]->arg
, "incomplete", 2) == 0)
7095 origin
= BGP_ORIGIN_INCOMPLETE
;
7098 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
7099 sum_only
, as_set
, origin
);
7102 DEFUN (no_ipv6_aggregate_address
,
7103 no_ipv6_aggregate_address_cmd
,
7104 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
7106 "Configure BGP aggregate entries\n"
7107 "Aggregate prefix\n"
7108 "Generate AS set path information\n"
7109 "Filter more specific routes from updates\n"
7110 "Filter more specific routes from updates\n"
7111 "Generate AS set path information\n"
7112 "Apply route map to aggregate network\n"
7113 "Name of route map\n"
7117 "Unknown heritage\n")
7120 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7121 char *prefix
= argv
[idx
]->arg
;
7122 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7125 /* Redistribute route treatment. */
7126 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7127 const union g_addr
*nexthop
, ifindex_t ifindex
,
7128 enum nexthop_types_t nhtype
, uint32_t metric
,
7129 uint8_t type
, unsigned short instance
,
7132 struct bgp_path_info
*new;
7133 struct bgp_path_info
*bpi
;
7134 struct bgp_path_info rmap_path
;
7135 struct bgp_node
*bn
;
7137 struct attr
*new_attr
;
7139 route_map_result_t ret
;
7140 struct bgp_redist
*red
;
7142 /* Make default attribute. */
7143 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7145 * This must not be NULL to satisfy Coverity SA
7147 assert(attr
.aspath
);
7150 case NEXTHOP_TYPE_IFINDEX
:
7152 case NEXTHOP_TYPE_IPV4
:
7153 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7154 attr
.nexthop
= nexthop
->ipv4
;
7156 case NEXTHOP_TYPE_IPV6
:
7157 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7158 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7159 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7161 case NEXTHOP_TYPE_BLACKHOLE
:
7162 switch (p
->family
) {
7164 attr
.nexthop
.s_addr
= INADDR_ANY
;
7167 memset(&attr
.mp_nexthop_global
, 0,
7168 sizeof(attr
.mp_nexthop_global
));
7169 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7174 attr
.nh_ifindex
= ifindex
;
7177 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7180 afi
= family2afi(p
->family
);
7182 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7184 struct attr attr_new
;
7186 /* Copy attribute for modification. */
7189 if (red
->redist_metric_flag
)
7190 attr_new
.med
= red
->redist_metric
;
7192 /* Apply route-map. */
7193 if (red
->rmap
.name
) {
7194 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7195 rmap_path
.peer
= bgp
->peer_self
;
7196 rmap_path
.attr
= &attr_new
;
7198 SET_FLAG(bgp
->peer_self
->rmap_type
,
7199 PEER_RMAP_TYPE_REDISTRIBUTE
);
7201 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7204 bgp
->peer_self
->rmap_type
= 0;
7206 if (ret
== RMAP_DENYMATCH
) {
7207 /* Free uninterned attribute. */
7208 bgp_attr_flush(&attr_new
);
7210 /* Unintern original. */
7211 aspath_unintern(&attr
.aspath
);
7212 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7217 if (CHECK_FLAG(bgp
->flags
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7218 bgp_attr_add_gshut_community(&attr_new
);
7220 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7221 SAFI_UNICAST
, p
, NULL
);
7223 new_attr
= bgp_attr_intern(&attr_new
);
7225 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
7227 if (bpi
->peer
== bgp
->peer_self
7228 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7232 /* Ensure the (source route) type is updated. */
7234 if (attrhash_cmp(bpi
->attr
, new_attr
)
7235 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7236 bgp_attr_unintern(&new_attr
);
7237 aspath_unintern(&attr
.aspath
);
7238 bgp_unlock_node(bn
);
7241 /* The attribute is changed. */
7242 bgp_path_info_set_flag(bn
, bpi
,
7243 BGP_PATH_ATTR_CHANGED
);
7245 /* Rewrite BGP route information. */
7246 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7247 bgp_path_info_restore(bn
, bpi
);
7249 bgp_aggregate_decrement(
7250 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7251 bgp_attr_unintern(&bpi
->attr
);
7252 bpi
->attr
= new_attr
;
7253 bpi
->uptime
= bgp_clock();
7255 /* Process change. */
7256 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7258 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7259 bgp_unlock_node(bn
);
7260 aspath_unintern(&attr
.aspath
);
7262 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7264 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7266 vpn_leak_from_vrf_update(
7267 bgp_get_default(), bgp
, bpi
);
7273 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7274 bgp
->peer_self
, new_attr
, bn
);
7275 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7277 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7278 bgp_path_info_add(bn
, new);
7279 bgp_unlock_node(bn
);
7280 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7282 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7283 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7285 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7289 /* Unintern original. */
7290 aspath_unintern(&attr
.aspath
);
7293 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7294 unsigned short instance
)
7297 struct bgp_node
*rn
;
7298 struct bgp_path_info
*pi
;
7299 struct bgp_redist
*red
;
7301 afi
= family2afi(p
->family
);
7303 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7305 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7306 SAFI_UNICAST
, p
, NULL
);
7308 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7309 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7313 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7314 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7316 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7319 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7320 bgp_path_info_delete(rn
, pi
);
7321 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7323 bgp_unlock_node(rn
);
7327 /* Withdraw specified route type's route. */
7328 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7329 unsigned short instance
)
7331 struct bgp_node
*rn
;
7332 struct bgp_path_info
*pi
;
7333 struct bgp_table
*table
;
7335 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7337 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7338 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7339 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7340 && pi
->instance
== instance
)
7344 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7345 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7347 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7350 bgp_aggregate_decrement(bgp
, bgp_node_get_prefix(rn
),
7351 pi
, afi
, SAFI_UNICAST
);
7352 bgp_path_info_delete(rn
, pi
);
7353 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7358 /* Static function to display route. */
7359 static void route_vty_out_route(const struct prefix
*p
, struct vty
*vty
,
7366 if (p
->family
== AF_INET
) {
7370 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7373 json_object_string_add(json
, "prefix",
7374 inet_ntop(p
->family
,
7377 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7378 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7379 json_object_string_add(json
, "network", buf2
);
7381 } else if (p
->family
== AF_ETHERNET
) {
7382 prefix2str(p
, buf
, PREFIX_STRLEN
);
7383 len
= vty_out(vty
, "%s", buf
);
7384 } else if (p
->family
== AF_EVPN
) {
7388 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7391 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7392 } else if (p
->family
== AF_FLOWSPEC
) {
7393 route_vty_out_flowspec(vty
, p
, NULL
,
7395 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7396 NLRI_STRING_FORMAT_MIN
, json
);
7401 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7404 json_object_string_add(json
, "prefix",
7405 inet_ntop(p
->family
,
7408 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7409 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7410 json_object_string_add(json
, "network", buf2
);
7417 vty_out(vty
, "\n%*s", 20, " ");
7419 vty_out(vty
, "%*s", len
, " ");
7423 enum bgp_display_type
{
7427 /* Print the short form route status for a bgp_path_info */
7428 static void route_vty_short_status_out(struct vty
*vty
,
7429 struct bgp_path_info
*path
,
7430 json_object
*json_path
)
7434 /* Route status display. */
7435 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7436 json_object_boolean_true_add(json_path
, "removed");
7438 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7439 json_object_boolean_true_add(json_path
, "stale");
7441 if (path
->extra
&& path
->extra
->suppress
)
7442 json_object_boolean_true_add(json_path
, "suppressed");
7444 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7445 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7446 json_object_boolean_true_add(json_path
, "valid");
7449 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7450 json_object_boolean_true_add(json_path
, "history");
7452 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7453 json_object_boolean_true_add(json_path
, "damped");
7455 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7456 json_object_boolean_true_add(json_path
, "bestpath");
7458 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7459 json_object_boolean_true_add(json_path
, "multipath");
7461 /* Internal route. */
7462 if ((path
->peer
->as
)
7463 && (path
->peer
->as
== path
->peer
->local_as
))
7464 json_object_string_add(json_path
, "pathFrom",
7467 json_object_string_add(json_path
, "pathFrom",
7473 /* Route status display. */
7474 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7476 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7478 else if (path
->extra
&& path
->extra
->suppress
)
7480 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7481 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7487 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7489 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7491 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7493 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7498 /* Internal route. */
7499 if (path
->peer
&& (path
->peer
->as
)
7500 && (path
->peer
->as
== path
->peer
->local_as
))
7506 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7509 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)
7510 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7511 return peer
->hostname
;
7515 /* called from terminal list command */
7516 void route_vty_out(struct vty
*vty
, const struct prefix
*p
,
7517 struct bgp_path_info
*path
, int display
, safi_t safi
,
7518 json_object
*json_paths
)
7520 struct attr
*attr
= path
->attr
;
7521 json_object
*json_path
= NULL
;
7522 json_object
*json_nexthops
= NULL
;
7523 json_object
*json_nexthop_global
= NULL
;
7524 json_object
*json_nexthop_ll
= NULL
;
7525 json_object
*json_ext_community
= NULL
;
7526 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7528 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7529 bool nexthop_othervrf
= false;
7530 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7531 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7532 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7535 json_path
= json_object_new_object();
7537 /* short status lead text */
7538 route_vty_short_status_out(vty
, path
, json_path
);
7541 /* print prefix and mask */
7543 route_vty_out_route(p
, vty
, json_path
);
7545 vty_out(vty
, "%*s", 17, " ");
7547 route_vty_out_route(p
, vty
, json_path
);
7551 * If vrf id of nexthop is different from that of prefix,
7552 * set up printable string to append
7554 if (path
->extra
&& path
->extra
->bgp_orig
) {
7555 const char *self
= "";
7560 nexthop_othervrf
= true;
7561 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7563 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7564 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7565 "@%s%s", VRFID_NONE_STR
, self
);
7567 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7568 path
->extra
->bgp_orig
->vrf_id
, self
);
7570 if (path
->extra
->bgp_orig
->inst_type
7571 != BGP_INSTANCE_TYPE_DEFAULT
)
7573 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7575 const char *self
= "";
7580 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7584 * For ENCAP and EVPN routes, nexthop address family is not
7585 * neccessarily the same as the prefix address family.
7586 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7587 * EVPN routes are also exchanged with a MP nexthop. Currently,
7589 * is only IPv4, the value will be present in either
7591 * attr->mp_nexthop_global_in
7593 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7596 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7600 sprintf(nexthop
, "%s",
7601 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7605 sprintf(nexthop
, "%s",
7606 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7610 sprintf(nexthop
, "?");
7615 json_nexthop_global
= json_object_new_object();
7617 json_object_string_add(json_nexthop_global
, "ip",
7620 if (nexthop_hostname
)
7621 json_object_string_add(json_nexthop_global
,
7625 json_object_string_add(json_nexthop_global
, "afi",
7626 (af
== AF_INET
) ? "ipv4"
7628 json_object_boolean_true_add(json_nexthop_global
,
7631 vty_out(vty
, "%s%s",
7632 nexthop_hostname
? nexthop_hostname
: nexthop
,
7634 } else if (safi
== SAFI_EVPN
) {
7636 json_nexthop_global
= json_object_new_object();
7638 json_object_string_add(json_nexthop_global
, "ip",
7639 inet_ntoa(attr
->nexthop
));
7641 if (nexthop_hostname
)
7642 json_object_string_add(json_nexthop_global
,
7646 json_object_string_add(json_nexthop_global
, "afi",
7648 json_object_boolean_true_add(json_nexthop_global
,
7651 vty_out(vty
, "%-16s%s",
7652 nexthop_hostname
? nexthop_hostname
7653 : inet_ntoa(attr
->nexthop
),
7655 } else if (safi
== SAFI_FLOWSPEC
) {
7656 if (attr
->nexthop
.s_addr
!= INADDR_ANY
) {
7658 json_nexthop_global
= json_object_new_object();
7660 json_object_string_add(json_nexthop_global
,
7662 json_object_string_add(
7663 json_nexthop_global
, "ip",
7664 inet_ntoa(attr
->nexthop
));
7666 if (nexthop_hostname
)
7667 json_object_string_add(
7668 json_nexthop_global
, "hostname",
7671 json_object_boolean_true_add(
7672 json_nexthop_global
,
7675 vty_out(vty
, "%-16s",
7678 : inet_ntoa(attr
->nexthop
));
7681 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7683 json_nexthop_global
= json_object_new_object();
7685 json_object_string_add(json_nexthop_global
, "ip",
7686 inet_ntoa(attr
->nexthop
));
7688 if (nexthop_hostname
)
7689 json_object_string_add(json_nexthop_global
,
7693 json_object_string_add(json_nexthop_global
, "afi",
7695 json_object_boolean_true_add(json_nexthop_global
,
7700 snprintf(buf
, sizeof(buf
), "%s%s",
7701 nexthop_hostname
? nexthop_hostname
7702 : inet_ntoa(attr
->nexthop
),
7704 vty_out(vty
, "%-16s", buf
);
7709 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7714 json_nexthop_global
= json_object_new_object();
7715 json_object_string_add(
7716 json_nexthop_global
, "ip",
7717 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7720 if (nexthop_hostname
)
7721 json_object_string_add(json_nexthop_global
,
7725 json_object_string_add(json_nexthop_global
, "afi",
7727 json_object_string_add(json_nexthop_global
, "scope",
7730 /* We display both LL & GL if both have been
7732 if ((attr
->mp_nexthop_len
7733 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7734 || (path
->peer
->conf_if
)) {
7735 json_nexthop_ll
= json_object_new_object();
7736 json_object_string_add(
7737 json_nexthop_ll
, "ip",
7739 &attr
->mp_nexthop_local
, buf
,
7742 if (nexthop_hostname
)
7743 json_object_string_add(
7744 json_nexthop_ll
, "hostname",
7747 json_object_string_add(json_nexthop_ll
, "afi",
7749 json_object_string_add(json_nexthop_ll
, "scope",
7752 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7753 &attr
->mp_nexthop_local
)
7755 && !attr
->mp_nexthop_prefer_global
)
7756 json_object_boolean_true_add(
7757 json_nexthop_ll
, "used");
7759 json_object_boolean_true_add(
7760 json_nexthop_global
, "used");
7762 json_object_boolean_true_add(
7763 json_nexthop_global
, "used");
7765 /* Display LL if LL/Global both in table unless
7766 * prefer-global is set */
7767 if (((attr
->mp_nexthop_len
7768 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7769 && !attr
->mp_nexthop_prefer_global
)
7770 || (path
->peer
->conf_if
)) {
7771 if (path
->peer
->conf_if
) {
7772 len
= vty_out(vty
, "%s",
7773 path
->peer
->conf_if
);
7774 len
= 16 - len
; /* len of IPv6
7780 vty_out(vty
, "\n%*s", 36, " ");
7782 vty_out(vty
, "%*s", len
, " ");
7790 &attr
->mp_nexthop_local
,
7796 vty_out(vty
, "\n%*s", 36, " ");
7798 vty_out(vty
, "%*s", len
, " ");
7807 &attr
->mp_nexthop_global
,
7813 vty_out(vty
, "\n%*s", 36, " ");
7815 vty_out(vty
, "%*s", len
, " ");
7821 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7825 * Adding "metric" field to match with corresponding
7826 * CLI. "med" will be deprecated in future.
7828 json_object_int_add(json_path
, "med", attr
->med
);
7829 json_object_int_add(json_path
, "metric", attr
->med
);
7831 vty_out(vty
, "%10u", attr
->med
);
7832 else if (!json_paths
)
7836 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7840 * Adding "locPrf" field to match with corresponding
7841 * CLI. "localPref" will be deprecated in future.
7843 json_object_int_add(json_path
, "localpref",
7845 json_object_int_add(json_path
, "locPrf",
7848 vty_out(vty
, "%7u", attr
->local_pref
);
7849 else if (!json_paths
)
7853 json_object_int_add(json_path
, "weight", attr
->weight
);
7855 vty_out(vty
, "%7u ", attr
->weight
);
7859 json_object_string_add(
7860 json_path
, "peerId",
7861 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7869 * Adding "path" field to match with corresponding
7870 * CLI. "aspath" will be deprecated in future.
7872 json_object_string_add(json_path
, "aspath",
7874 json_object_string_add(json_path
, "path",
7877 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7882 json_object_string_add(json_path
, "origin",
7883 bgp_origin_long_str
[attr
->origin
]);
7885 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7888 if (safi
== SAFI_EVPN
&&
7889 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7890 json_ext_community
= json_object_new_object();
7891 json_object_string_add(json_ext_community
,
7893 attr
->ecommunity
->str
);
7894 json_object_object_add(json_path
,
7895 "extendedCommunity",
7896 json_ext_community
);
7900 json_object_boolean_true_add(json_path
,
7901 "announceNexthopSelf");
7902 if (nexthop_othervrf
) {
7903 json_object_string_add(json_path
, "nhVrfName",
7906 json_object_int_add(json_path
, "nhVrfId",
7907 ((nexthop_vrfid
== VRF_UNKNOWN
)
7909 : (int)nexthop_vrfid
));
7914 if (json_nexthop_global
|| json_nexthop_ll
) {
7915 json_nexthops
= json_object_new_array();
7917 if (json_nexthop_global
)
7918 json_object_array_add(json_nexthops
,
7919 json_nexthop_global
);
7921 if (json_nexthop_ll
)
7922 json_object_array_add(json_nexthops
,
7925 json_object_object_add(json_path
, "nexthops",
7929 json_object_array_add(json_paths
, json_path
);
7933 if (safi
== SAFI_EVPN
&&
7934 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7935 vty_out(vty
, "%*s", 20, " ");
7936 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7940 /* prints an additional line, indented, with VNC info, if
7942 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7943 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7948 /* called from terminal list command */
7949 void route_vty_out_tmp(struct vty
*vty
, const struct prefix
*p
,
7950 struct attr
*attr
, safi_t safi
, bool use_json
,
7951 json_object
*json_ar
)
7953 json_object
*json_status
= NULL
;
7954 json_object
*json_net
= NULL
;
7957 /* Route status display. */
7959 json_status
= json_object_new_object();
7960 json_net
= json_object_new_object();
7967 /* print prefix and mask */
7969 if (safi
== SAFI_EVPN
)
7970 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7971 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7972 json_object_string_add(
7973 json_net
, "addrPrefix",
7974 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7976 json_object_int_add(json_net
, "prefixLen",
7978 prefix2str(p
, buff
, PREFIX_STRLEN
);
7979 json_object_string_add(json_net
, "network", buff
);
7982 route_vty_out_route(p
, vty
, NULL
);
7984 /* Print attribute */
7987 if (p
->family
== AF_INET
7988 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7989 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7990 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7991 json_object_string_add(
7992 json_net
, "nextHop",
7994 attr
->mp_nexthop_global_in
));
7996 json_object_string_add(
7997 json_net
, "nextHop",
7998 inet_ntoa(attr
->nexthop
));
7999 } else if (p
->family
== AF_INET6
8000 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8003 json_object_string_add(
8004 json_net
, "nextHopGlobal",
8006 &attr
->mp_nexthop_global
, buf
,
8008 } else if (p
->family
== AF_EVPN
&&
8009 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8010 json_object_string_add(json_net
,
8011 "nextHop", inet_ntoa(
8012 attr
->mp_nexthop_global_in
));
8015 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8016 json_object_int_add(json_net
, "metric",
8019 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8022 * Adding "locPrf" field to match with
8023 * corresponding CLI. "localPref" will be
8024 * deprecated in future.
8026 json_object_int_add(json_net
, "localPref",
8028 json_object_int_add(json_net
, "locPrf",
8032 json_object_int_add(json_net
, "weight", attr
->weight
);
8038 * Adding "path" field to match with
8039 * corresponding CLI. "localPref" will be
8040 * deprecated in future.
8042 json_object_string_add(json_net
, "asPath",
8044 json_object_string_add(json_net
, "path",
8049 json_object_string_add(json_net
, "bgpOriginCode",
8050 bgp_origin_str
[attr
->origin
]);
8052 if (p
->family
== AF_INET
8053 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8054 || safi
== SAFI_EVPN
8055 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8056 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8057 || safi
== SAFI_EVPN
)
8058 vty_out(vty
, "%-16s",
8060 attr
->mp_nexthop_global_in
));
8062 vty_out(vty
, "%-16s",
8063 inet_ntoa(attr
->nexthop
));
8064 } else if (p
->family
== AF_INET6
8065 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
8072 &attr
->mp_nexthop_global
, buf
,
8076 vty_out(vty
, "\n%*s", 36, " ");
8078 vty_out(vty
, "%*s", len
, " ");
8081 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
8082 vty_out(vty
, "%10u", attr
->med
);
8086 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
8087 vty_out(vty
, "%7u", attr
->local_pref
);
8091 vty_out(vty
, "%7u ", attr
->weight
);
8095 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8098 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8102 json_object_boolean_true_add(json_status
, "*");
8103 json_object_boolean_true_add(json_status
, ">");
8104 json_object_object_add(json_net
, "appliedStatusSymbols",
8107 prefix2str(p
, buff
, PREFIX_STRLEN
);
8108 json_object_object_add(json_ar
, buff
, json_net
);
8113 void route_vty_out_tag(struct vty
*vty
, const struct prefix
*p
,
8114 struct bgp_path_info
*path
, int display
, safi_t safi
,
8117 json_object
*json_out
= NULL
;
8119 mpls_label_t label
= MPLS_INVALID_LABEL
;
8125 json_out
= json_object_new_object();
8127 /* short status lead text */
8128 route_vty_short_status_out(vty
, path
, json_out
);
8130 /* print prefix and mask */
8133 route_vty_out_route(p
, vty
, NULL
);
8135 vty_out(vty
, "%*s", 17, " ");
8138 /* Print attribute */
8140 if (((p
->family
== AF_INET
)
8141 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8142 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8143 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8144 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8145 || safi
== SAFI_EVPN
) {
8147 json_object_string_add(
8148 json_out
, "mpNexthopGlobalIn",
8149 inet_ntoa(attr
->mp_nexthop_global_in
));
8151 vty_out(vty
, "%-16s",
8152 inet_ntoa(attr
->mp_nexthop_global_in
));
8155 json_object_string_add(
8156 json_out
, "nexthop",
8157 inet_ntoa(attr
->nexthop
));
8159 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8161 } else if (((p
->family
== AF_INET6
)
8162 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8163 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8164 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8167 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8169 json_object_string_add(
8170 json_out
, "mpNexthopGlobalIn",
8172 &attr
->mp_nexthop_global
,
8173 buf_a
, sizeof(buf_a
)));
8177 &attr
->mp_nexthop_global
,
8178 buf_a
, sizeof(buf_a
)));
8179 } else if (attr
->mp_nexthop_len
8180 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8181 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8182 &attr
->mp_nexthop_global
,
8183 &attr
->mp_nexthop_local
);
8185 json_object_string_add(json_out
,
8186 "mpNexthopGlobalLocal",
8189 vty_out(vty
, "%s", buf_a
);
8193 label
= decode_label(&path
->extra
->label
[0]);
8195 if (bgp_is_valid_label(&label
)) {
8197 json_object_int_add(json_out
, "notag", label
);
8198 json_object_array_add(json
, json_out
);
8200 vty_out(vty
, "notag/%d", label
);
8206 void route_vty_out_overlay(struct vty
*vty
, const struct prefix
*p
,
8207 struct bgp_path_info
*path
, int display
,
8208 json_object
*json_paths
)
8211 char buf
[BUFSIZ
] = {0};
8212 json_object
*json_path
= NULL
;
8213 json_object
*json_nexthop
= NULL
;
8214 json_object
*json_overlay
= NULL
;
8220 json_path
= json_object_new_object();
8221 json_overlay
= json_object_new_object();
8222 json_nexthop
= json_object_new_object();
8225 /* short status lead text */
8226 route_vty_short_status_out(vty
, path
, json_path
);
8228 /* print prefix and mask */
8230 route_vty_out_route(p
, vty
, json_path
);
8232 vty_out(vty
, "%*s", 17, " ");
8234 /* Print attribute */
8237 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8241 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8243 vty_out(vty
, "%-16s", buf
);
8245 json_object_string_add(json_nexthop
, "ip", buf
);
8247 json_object_string_add(json_nexthop
, "afi", "ipv4");
8249 json_object_object_add(json_path
, "nexthop",
8254 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8255 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8257 vty_out(vty
, "%s(%s)", buf
, buf1
);
8259 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8261 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8264 json_object_string_add(json_nexthop
, "afi", "ipv6");
8266 json_object_object_add(json_path
, "nexthop",
8274 json_object_string_add(json_nexthop
, "Error",
8275 "Unsupported address-family");
8279 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
8282 vty_out(vty
, "%s", str
);
8284 json_object_string_add(json_overlay
, "esi", str
);
8286 XFREE(MTYPE_TMP
, str
);
8288 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8289 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8291 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8292 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8297 vty_out(vty
, "/%s", buf
);
8299 json_object_string_add(json_overlay
, "gw", buf
);
8301 if (attr
->ecommunity
) {
8303 struct ecommunity_val
*routermac
= ecommunity_lookup(
8304 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8305 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8308 mac
= ecom_mac2str((char *)routermac
->val
);
8311 vty_out(vty
, "/%s", (char *)mac
);
8313 json_object_string_add(json_overlay
, "rmac",
8316 XFREE(MTYPE_TMP
, mac
);
8323 json_object_object_add(json_path
, "overlay", json_overlay
);
8325 json_object_array_add(json_paths
, json_path
);
8329 /* dampening route */
8330 static void damp_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8331 struct bgp_path_info
*path
, int display
,
8332 afi_t afi
, safi_t safi
, bool use_json
,
8337 char timebuf
[BGP_UPTIME_LEN
];
8339 /* short status lead text */
8340 route_vty_short_status_out(vty
, path
, json
);
8342 /* print prefix and mask */
8345 route_vty_out_route(p
, vty
, NULL
);
8347 vty_out(vty
, "%*s", 17, " ");
8350 len
= vty_out(vty
, "%s", path
->peer
->host
);
8354 vty_out(vty
, "\n%*s", 34, " ");
8357 json_object_int_add(json
, "peerHost", len
);
8359 vty_out(vty
, "%*s", len
, " ");
8363 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8364 safi
, use_json
, json
);
8367 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8368 BGP_UPTIME_LEN
, afi
, safi
,
8371 /* Print attribute */
8377 json_object_string_add(json
, "asPath",
8380 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8385 json_object_string_add(json
, "origin",
8386 bgp_origin_str
[attr
->origin
]);
8388 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8395 static void flap_route_vty_out(struct vty
*vty
, const struct prefix
*p
,
8396 struct bgp_path_info
*path
, int display
,
8397 afi_t afi
, safi_t safi
, bool use_json
,
8401 struct bgp_damp_info
*bdi
;
8402 char timebuf
[BGP_UPTIME_LEN
];
8408 bdi
= path
->extra
->damp_info
;
8410 /* short status lead text */
8411 route_vty_short_status_out(vty
, path
, json
);
8413 /* print prefix and mask */
8416 route_vty_out_route(p
, vty
, NULL
);
8418 vty_out(vty
, "%*s", 17, " ");
8421 len
= vty_out(vty
, "%s", path
->peer
->host
);
8425 vty_out(vty
, "\n%*s", 33, " ");
8428 json_object_int_add(json
, "peerHost", len
);
8430 vty_out(vty
, "%*s", len
, " ");
8433 len
= vty_out(vty
, "%d", bdi
->flap
);
8440 json_object_int_add(json
, "bdiFlap", len
);
8442 vty_out(vty
, "%*s", len
, " ");
8446 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8449 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8450 BGP_UPTIME_LEN
, 0, NULL
));
8452 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8453 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8455 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8456 BGP_UPTIME_LEN
, afi
, safi
,
8460 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8461 BGP_UPTIME_LEN
, afi
,
8462 safi
, use_json
, json
));
8465 vty_out(vty
, "%*s ", 8, " ");
8468 /* Print attribute */
8474 json_object_string_add(json
, "asPath",
8477 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8482 json_object_string_add(json
, "origin",
8483 bgp_origin_str
[attr
->origin
]);
8485 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8491 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8492 int *first
, const char *header
,
8493 json_object
*json_adv_to
)
8495 char buf1
[INET6_ADDRSTRLEN
];
8496 json_object
*json_peer
= NULL
;
8499 /* 'advertised-to' is a dictionary of peers we have advertised
8501 * prefix too. The key is the peer's IP or swpX, the value is
8503 * hostname if we know it and "" if not.
8505 json_peer
= json_object_new_object();
8508 json_object_string_add(json_peer
, "hostname",
8512 json_object_object_add(json_adv_to
, peer
->conf_if
,
8515 json_object_object_add(
8517 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8521 vty_out(vty
, "%s", header
);
8526 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
8528 vty_out(vty
, " %s(%s)", peer
->hostname
,
8531 vty_out(vty
, " %s(%s)", peer
->hostname
,
8532 sockunion2str(&peer
->su
, buf1
,
8536 vty_out(vty
, " %s", peer
->conf_if
);
8539 sockunion2str(&peer
->su
, buf1
,
8545 static void route_vty_out_tx_ids(struct vty
*vty
,
8546 struct bgp_addpath_info_data
*d
)
8550 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8551 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8552 d
->addpath_tx_id
[i
],
8553 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8557 static const char *bgp_path_selection_reason2str(
8558 enum bgp_path_selection_reason reason
)
8561 case bgp_path_selection_none
:
8562 return "Nothing to Select";
8563 case bgp_path_selection_first
:
8564 return "First path received";
8565 case bgp_path_selection_evpn_sticky_mac
:
8566 return "EVPN Sticky Mac";
8567 case bgp_path_selection_evpn_seq
:
8568 return "EVPN sequence number";
8569 case bgp_path_selection_evpn_lower_ip
:
8570 return "EVPN lower IP";
8571 case bgp_path_selection_weight
:
8573 case bgp_path_selection_local_pref
:
8574 return "Local Pref";
8575 case bgp_path_selection_local_route
:
8576 return "Local Route";
8577 case bgp_path_selection_confed_as_path
:
8578 return "Confederation based AS Path";
8579 case bgp_path_selection_as_path
:
8581 case bgp_path_selection_origin
:
8583 case bgp_path_selection_med
:
8585 case bgp_path_selection_peer
:
8587 case bgp_path_selection_confed
:
8588 return "Confed Peer Type";
8589 case bgp_path_selection_igp_metric
:
8590 return "IGP Metric";
8591 case bgp_path_selection_older
:
8592 return "Older Path";
8593 case bgp_path_selection_router_id
:
8595 case bgp_path_selection_cluster_length
:
8596 return "Cluser length";
8597 case bgp_path_selection_stale
:
8598 return "Path Staleness";
8599 case bgp_path_selection_local_configured
:
8600 return "Locally configured route";
8601 case bgp_path_selection_neighbor_ip
:
8602 return "Neighbor IP";
8603 case bgp_path_selection_default
:
8604 return "Nothing left to compare";
8606 return "Invalid (internal error)";
8609 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8610 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8611 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8613 char buf
[INET6_ADDRSTRLEN
];
8615 char buf2
[EVPN_ROUTE_STRLEN
];
8616 struct attr
*attr
= path
->attr
;
8617 int sockunion_vty_out(struct vty
*, union sockunion
*);
8619 json_object
*json_bestpath
= NULL
;
8620 json_object
*json_cluster_list
= NULL
;
8621 json_object
*json_cluster_list_list
= NULL
;
8622 json_object
*json_ext_community
= NULL
;
8623 json_object
*json_last_update
= NULL
;
8624 json_object
*json_pmsi
= NULL
;
8625 json_object
*json_nexthop_global
= NULL
;
8626 json_object
*json_nexthop_ll
= NULL
;
8627 json_object
*json_nexthops
= NULL
;
8628 json_object
*json_path
= NULL
;
8629 json_object
*json_peer
= NULL
;
8630 json_object
*json_string
= NULL
;
8631 json_object
*json_adv_to
= NULL
;
8633 struct listnode
*node
, *nnode
;
8635 int addpath_capable
;
8637 unsigned int first_as
;
8639 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8641 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8644 json_path
= json_object_new_object();
8645 json_peer
= json_object_new_object();
8646 json_nexthop_global
= json_object_new_object();
8654 if (path
->extra
&& path
->extra
->num_labels
) {
8655 bgp_evpn_label2str(path
->extra
->label
,
8656 path
->extra
->num_labels
, tag_buf
,
8659 if (safi
== SAFI_EVPN
) {
8662 (struct prefix_evpn
*)
8663 bgp_node_get_prefix(bn
),
8664 buf2
, sizeof(buf2
));
8665 vty_out(vty
, " Route %s", buf2
);
8666 if (tag_buf
[0] != '\0')
8667 vty_out(vty
, " VNI %s", tag_buf
);
8671 json_object_string_add(json_path
, "VNI",
8676 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8677 struct bgp_path_info
*parent_ri
;
8678 struct bgp_node
*rn
, *prn
;
8680 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8681 rn
= parent_ri
->net
;
8682 if (rn
&& rn
->prn
) {
8684 prefix_rd2str((struct prefix_rd
*)
8685 bgp_node_get_prefix(prn
),
8686 buf1
, sizeof(buf1
));
8687 if (is_pi_family_evpn(parent_ri
)) {
8689 (struct prefix_evpn
*)
8690 bgp_node_get_prefix(rn
),
8691 buf2
, sizeof(buf2
));
8692 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8694 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8699 /* Line1 display AS-path, Aggregator */
8702 if (!attr
->aspath
->json
)
8703 aspath_str_update(attr
->aspath
, true);
8704 json_object_lock(attr
->aspath
->json
);
8705 json_object_object_add(json_path
, "aspath",
8706 attr
->aspath
->json
);
8708 if (attr
->aspath
->segments
)
8709 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8711 vty_out(vty
, " Local");
8715 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8717 json_object_boolean_true_add(json_path
, "removed");
8719 vty_out(vty
, ", (removed)");
8722 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8724 json_object_boolean_true_add(json_path
, "stale");
8726 vty_out(vty
, ", (stale)");
8729 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8731 json_object_int_add(json_path
, "aggregatorAs",
8732 attr
->aggregator_as
);
8733 json_object_string_add(
8734 json_path
, "aggregatorId",
8735 inet_ntoa(attr
->aggregator_addr
));
8736 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8737 json_object_boolean_true_add(
8738 json_path
, "aggregatorAsMalformed");
8740 json_object_boolean_false_add(
8741 json_path
, "aggregatorAsMalformed");
8743 if (attr
->aggregator_as
== BGP_AS_ZERO
)
8745 ", (aggregated by %u(malformed) %s)",
8746 attr
->aggregator_as
,
8747 inet_ntoa(attr
->aggregator_addr
));
8749 vty_out(vty
, ", (aggregated by %u %s)",
8750 attr
->aggregator_as
,
8751 inet_ntoa(attr
->aggregator_addr
));
8755 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8756 PEER_FLAG_REFLECTOR_CLIENT
)) {
8758 json_object_boolean_true_add(json_path
,
8759 "rxedFromRrClient");
8761 vty_out(vty
, ", (Received from a RR-client)");
8764 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8765 PEER_FLAG_RSERVER_CLIENT
)) {
8767 json_object_boolean_true_add(json_path
,
8768 "rxedFromRsClient");
8770 vty_out(vty
, ", (Received from a RS-client)");
8773 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8775 json_object_boolean_true_add(json_path
,
8776 "dampeningHistoryEntry");
8778 vty_out(vty
, ", (history entry)");
8779 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8781 json_object_boolean_true_add(json_path
,
8782 "dampeningSuppressed");
8784 vty_out(vty
, ", (suppressed due to dampening)");
8790 /* Line2 display Next-hop, Neighbor, Router-id */
8791 /* Display the nexthop */
8792 const struct prefix
*bn_p
= bgp_node_get_prefix(bn
);
8794 if ((bn_p
->family
== AF_INET
|| bn_p
->family
== AF_ETHERNET
8795 || bn_p
->family
== AF_EVPN
)
8796 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8797 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8798 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8799 || safi
== SAFI_EVPN
) {
8801 json_object_string_add(
8802 json_nexthop_global
, "ip",
8803 inet_ntoa(attr
->mp_nexthop_global_in
));
8805 if (nexthop_hostname
)
8806 json_object_string_add(
8807 json_nexthop_global
, "hostname",
8814 attr
->mp_nexthop_global_in
));
8817 json_object_string_add(
8818 json_nexthop_global
, "ip",
8819 inet_ntoa(attr
->nexthop
));
8821 if (nexthop_hostname
)
8822 json_object_string_add(
8823 json_nexthop_global
, "hostname",
8829 : inet_ntoa(attr
->nexthop
));
8833 json_object_string_add(json_nexthop_global
, "afi",
8837 json_object_string_add(
8838 json_nexthop_global
, "ip",
8839 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8840 buf
, INET6_ADDRSTRLEN
));
8842 if (nexthop_hostname
)
8843 json_object_string_add(json_nexthop_global
,
8847 json_object_string_add(json_nexthop_global
, "afi",
8849 json_object_string_add(json_nexthop_global
, "scope",
8855 : inet_ntop(AF_INET6
,
8856 &attr
->mp_nexthop_global
,
8857 buf
, INET6_ADDRSTRLEN
));
8861 /* Display the IGP cost or 'inaccessible' */
8862 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8864 json_object_boolean_false_add(json_nexthop_global
,
8867 vty_out(vty
, " (inaccessible)");
8869 if (path
->extra
&& path
->extra
->igpmetric
) {
8871 json_object_int_add(json_nexthop_global
,
8873 path
->extra
->igpmetric
);
8875 vty_out(vty
, " (metric %u)",
8876 path
->extra
->igpmetric
);
8879 /* IGP cost is 0, display this only for json */
8882 json_object_int_add(json_nexthop_global
,
8887 json_object_boolean_true_add(json_nexthop_global
,
8891 /* Display peer "from" output */
8892 /* This path was originated locally */
8893 if (path
->peer
== bgp
->peer_self
) {
8895 if (safi
== SAFI_EVPN
8896 || (bn_p
->family
== AF_INET
8897 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8899 json_object_string_add(json_peer
, "peerId",
8902 vty_out(vty
, " from 0.0.0.0 ");
8905 json_object_string_add(json_peer
, "peerId",
8908 vty_out(vty
, " from :: ");
8912 json_object_string_add(json_peer
, "routerId",
8913 inet_ntoa(bgp
->router_id
));
8915 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8918 /* We RXed this path from one of our peers */
8922 json_object_string_add(json_peer
, "peerId",
8923 sockunion2str(&path
->peer
->su
,
8926 json_object_string_add(json_peer
, "routerId",
8928 &path
->peer
->remote_id
,
8929 buf1
, sizeof(buf1
)));
8931 if (path
->peer
->hostname
)
8932 json_object_string_add(json_peer
, "hostname",
8933 path
->peer
->hostname
);
8935 if (path
->peer
->domainname
)
8936 json_object_string_add(json_peer
, "domainname",
8937 path
->peer
->domainname
);
8939 if (path
->peer
->conf_if
)
8940 json_object_string_add(json_peer
, "interface",
8941 path
->peer
->conf_if
);
8943 if (path
->peer
->conf_if
) {
8944 if (path
->peer
->hostname
8945 && CHECK_FLAG(path
->peer
->bgp
->flags
,
8946 BGP_FLAG_SHOW_HOSTNAME
))
8947 vty_out(vty
, " from %s(%s)",
8948 path
->peer
->hostname
,
8949 path
->peer
->conf_if
);
8951 vty_out(vty
, " from %s",
8952 path
->peer
->conf_if
);
8954 if (path
->peer
->hostname
8955 && CHECK_FLAG(path
->peer
->bgp
->flags
,
8956 BGP_FLAG_SHOW_HOSTNAME
))
8957 vty_out(vty
, " from %s(%s)",
8958 path
->peer
->hostname
,
8961 vty_out(vty
, " from %s",
8962 sockunion2str(&path
->peer
->su
,
8967 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8968 vty_out(vty
, " (%s)",
8969 inet_ntoa(attr
->originator_id
));
8971 vty_out(vty
, " (%s)",
8973 &path
->peer
->remote_id
, buf1
,
8979 * Note when vrfid of nexthop is different from that of prefix
8981 if (path
->extra
&& path
->extra
->bgp_orig
) {
8982 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8987 if (path
->extra
->bgp_orig
->inst_type
8988 == BGP_INSTANCE_TYPE_DEFAULT
)
8989 vn
= VRF_DEFAULT_NAME
;
8991 vn
= path
->extra
->bgp_orig
->name
;
8993 json_object_string_add(json_path
, "nhVrfName", vn
);
8995 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8996 json_object_int_add(json_path
, "nhVrfId", -1);
8998 json_object_int_add(json_path
, "nhVrfId",
8999 (int)nexthop_vrfid
);
9002 if (nexthop_vrfid
== VRF_UNKNOWN
)
9003 vty_out(vty
, " vrf ?");
9007 vrf
= vrf_lookup_by_id(nexthop_vrfid
);
9008 vty_out(vty
, " vrf %s(%u)",
9009 VRF_LOGNAME(vrf
), nexthop_vrfid
);
9016 json_object_boolean_true_add(json_path
,
9017 "announceNexthopSelf");
9019 vty_out(vty
, " announce-nh-self");
9026 /* display the link-local nexthop */
9027 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
9029 json_nexthop_ll
= json_object_new_object();
9030 json_object_string_add(
9031 json_nexthop_ll
, "ip",
9032 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9033 buf
, INET6_ADDRSTRLEN
));
9035 if (nexthop_hostname
)
9036 json_object_string_add(json_nexthop_ll
,
9040 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
9041 json_object_string_add(json_nexthop_ll
, "scope",
9044 json_object_boolean_true_add(json_nexthop_ll
,
9047 if (!attr
->mp_nexthop_prefer_global
)
9048 json_object_boolean_true_add(json_nexthop_ll
,
9051 json_object_boolean_true_add(
9052 json_nexthop_global
, "used");
9054 vty_out(vty
, " (%s) %s\n",
9055 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
9056 buf
, INET6_ADDRSTRLEN
),
9057 attr
->mp_nexthop_prefer_global
9062 /* If we do not have a link-local nexthop then we must flag the
9066 json_object_boolean_true_add(json_nexthop_global
,
9070 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9071 * Int/Ext/Local, Atomic, best */
9073 json_object_string_add(json_path
, "origin",
9074 bgp_origin_long_str
[attr
->origin
]);
9076 vty_out(vty
, " Origin %s",
9077 bgp_origin_long_str
[attr
->origin
]);
9079 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
9082 * Adding "metric" field to match with
9083 * corresponding CLI. "med" will be
9084 * deprecated in future.
9086 json_object_int_add(json_path
, "med", attr
->med
);
9087 json_object_int_add(json_path
, "metric", attr
->med
);
9089 vty_out(vty
, ", metric %u", attr
->med
);
9092 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
9094 json_object_int_add(json_path
, "localpref",
9097 vty_out(vty
, ", localpref %u", attr
->local_pref
);
9100 if (attr
->weight
!= 0) {
9102 json_object_int_add(json_path
, "weight", attr
->weight
);
9104 vty_out(vty
, ", weight %u", attr
->weight
);
9107 if (attr
->tag
!= 0) {
9109 json_object_int_add(json_path
, "tag", attr
->tag
);
9111 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9114 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9116 json_object_boolean_false_add(json_path
, "valid");
9118 vty_out(vty
, ", invalid");
9119 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9121 json_object_boolean_true_add(json_path
, "valid");
9123 vty_out(vty
, ", valid");
9126 if (path
->peer
!= bgp
->peer_self
) {
9127 if (path
->peer
->as
== path
->peer
->local_as
) {
9128 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9130 json_object_string_add(
9134 vty_out(vty
, ", confed-internal");
9137 json_object_string_add(
9138 json_peer
, "type", "internal");
9140 vty_out(vty
, ", internal");
9143 if (bgp_confederation_peers_check(bgp
,
9146 json_object_string_add(
9150 vty_out(vty
, ", confed-external");
9153 json_object_string_add(
9154 json_peer
, "type", "external");
9156 vty_out(vty
, ", external");
9159 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9161 json_object_boolean_true_add(json_path
, "aggregated");
9162 json_object_boolean_true_add(json_path
, "local");
9164 vty_out(vty
, ", aggregated, local");
9166 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9168 json_object_boolean_true_add(json_path
, "sourced");
9170 vty_out(vty
, ", sourced");
9173 json_object_boolean_true_add(json_path
, "sourced");
9174 json_object_boolean_true_add(json_path
, "local");
9176 vty_out(vty
, ", sourced, local");
9180 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9182 json_object_boolean_true_add(json_path
,
9185 vty_out(vty
, ", atomic-aggregate");
9188 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9189 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9190 && bgp_path_info_mpath_count(path
))) {
9192 json_object_boolean_true_add(json_path
, "multipath");
9194 vty_out(vty
, ", multipath");
9197 // Mark the bestpath(s)
9198 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9199 first_as
= aspath_get_first_as(attr
->aspath
);
9203 json_bestpath
= json_object_new_object();
9204 json_object_int_add(json_bestpath
, "bestpathFromAs",
9208 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9210 vty_out(vty
, ", bestpath-from-AS Local");
9214 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9217 json_bestpath
= json_object_new_object();
9218 json_object_boolean_true_add(json_bestpath
, "overall");
9219 json_object_string_add(
9220 json_bestpath
, "selectionReason",
9221 bgp_path_selection_reason2str(bn
->reason
));
9223 vty_out(vty
, ", best");
9224 vty_out(vty
, " (%s)",
9225 bgp_path_selection_reason2str(bn
->reason
));
9230 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9235 /* Line 4 display Community */
9236 if (attr
->community
) {
9238 if (!attr
->community
->json
)
9239 community_str(attr
->community
, true);
9240 json_object_lock(attr
->community
->json
);
9241 json_object_object_add(json_path
, "community",
9242 attr
->community
->json
);
9244 vty_out(vty
, " Community: %s\n",
9245 attr
->community
->str
);
9249 /* Line 5 display Extended-community */
9250 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9252 json_ext_community
= json_object_new_object();
9253 json_object_string_add(json_ext_community
, "string",
9254 attr
->ecommunity
->str
);
9255 json_object_object_add(json_path
, "extendedCommunity",
9256 json_ext_community
);
9258 vty_out(vty
, " Extended Community: %s\n",
9259 attr
->ecommunity
->str
);
9263 /* Line 6 display Large community */
9264 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9266 if (!attr
->lcommunity
->json
)
9267 lcommunity_str(attr
->lcommunity
, true);
9268 json_object_lock(attr
->lcommunity
->json
);
9269 json_object_object_add(json_path
, "largeCommunity",
9270 attr
->lcommunity
->json
);
9272 vty_out(vty
, " Large Community: %s\n",
9273 attr
->lcommunity
->str
);
9277 /* Line 7 display Originator, Cluster-id */
9278 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9279 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9280 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9282 json_object_string_add(
9283 json_path
, "originatorId",
9284 inet_ntoa(attr
->originator_id
));
9286 vty_out(vty
, " Originator: %s",
9287 inet_ntoa(attr
->originator_id
));
9290 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9294 json_cluster_list
= json_object_new_object();
9295 json_cluster_list_list
=
9296 json_object_new_array();
9298 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9300 json_string
= json_object_new_string(
9301 inet_ntoa(attr
->cluster
9303 json_object_array_add(
9304 json_cluster_list_list
,
9309 * struct cluster_list does not have
9310 * "str" variable like aspath and community
9311 * do. Add this someday if someone asks
9313 * json_object_string_add(json_cluster_list,
9314 * "string", attr->cluster->str);
9316 json_object_object_add(json_cluster_list
,
9318 json_cluster_list_list
);
9319 json_object_object_add(json_path
, "clusterList",
9322 vty_out(vty
, ", Cluster list: ");
9324 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9327 inet_ntoa(attr
->cluster
9337 if (path
->extra
&& path
->extra
->damp_info
)
9338 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9341 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9342 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9343 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9346 json_object_int_add(json_path
, "remoteLabel", label
);
9348 vty_out(vty
, " Remote label: %d\n", label
);
9352 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9353 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9355 json_object_string_add(json_path
, "remoteSid", buf
);
9357 vty_out(vty
, " Remote SID: %s\n", buf
);
9361 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9363 json_object_int_add(json_path
, "labelIndex",
9366 vty_out(vty
, " Label Index: %d\n",
9370 /* Line 8 display Addpath IDs */
9371 if (path
->addpath_rx_id
9372 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9374 json_object_int_add(json_path
, "addpathRxId",
9375 path
->addpath_rx_id
);
9377 /* Keep backwards compatibility with the old API
9378 * by putting TX All's ID in the old field
9380 json_object_int_add(
9381 json_path
, "addpathTxId",
9383 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9385 /* ... but create a specific field for each
9388 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9389 json_object_int_add(
9391 bgp_addpath_names(i
)->id_json_name
,
9392 path
->tx_addpath
.addpath_tx_id
[i
]);
9395 vty_out(vty
, " AddPath ID: RX %u, ",
9396 path
->addpath_rx_id
);
9398 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9402 /* If we used addpath to TX a non-bestpath we need to display
9403 * "Advertised to" on a path-by-path basis
9405 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9408 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9410 bgp_addpath_encode_tx(peer
, afi
, safi
);
9411 has_adj
= bgp_adj_out_lookup(
9413 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9414 &path
->tx_addpath
));
9416 if ((addpath_capable
&& has_adj
)
9417 || (!addpath_capable
&& has_adj
9418 && CHECK_FLAG(path
->flags
,
9419 BGP_PATH_SELECTED
))) {
9420 if (json_path
&& !json_adv_to
)
9421 json_adv_to
= json_object_new_object();
9423 route_vty_out_advertised_to(
9425 " Advertised to:", json_adv_to
);
9431 json_object_object_add(
9432 json_path
, "advertisedTo", json_adv_to
);
9441 /* Line 9 display Uptime */
9442 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9444 json_last_update
= json_object_new_object();
9445 json_object_int_add(json_last_update
, "epoch", tbuf
);
9446 json_object_string_add(json_last_update
, "string",
9448 json_object_object_add(json_path
, "lastUpdate",
9451 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9453 /* Line 10 display PMSI tunnel attribute, if present */
9454 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9456 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9457 PMSI_TNLTYPE_STR_DEFAULT
);
9460 json_pmsi
= json_object_new_object();
9461 json_object_string_add(json_pmsi
, "tunnelType", str
);
9462 json_object_int_add(json_pmsi
, "label",
9463 label2vni(&attr
->label
));
9464 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9466 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9467 str
, label2vni(&attr
->label
));
9470 /* We've constructed the json object for this path, add it to the json
9474 if (json_nexthop_global
|| json_nexthop_ll
) {
9475 json_nexthops
= json_object_new_array();
9477 if (json_nexthop_global
)
9478 json_object_array_add(json_nexthops
,
9479 json_nexthop_global
);
9481 if (json_nexthop_ll
)
9482 json_object_array_add(json_nexthops
,
9485 json_object_object_add(json_path
, "nexthops",
9489 json_object_object_add(json_path
, "peer", json_peer
);
9490 json_object_array_add(json_paths
, json_path
);
9494 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9495 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9496 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9498 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9499 const char *prefix_list_str
, afi_t afi
,
9500 safi_t safi
, enum bgp_show_type type
);
9501 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9502 const char *filter
, afi_t afi
, safi_t safi
,
9503 enum bgp_show_type type
);
9504 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9505 const char *rmap_str
, afi_t afi
, safi_t safi
,
9506 enum bgp_show_type type
);
9507 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9508 const char *com
, int exact
, afi_t afi
,
9510 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9511 const char *prefix
, afi_t afi
, safi_t safi
,
9512 enum bgp_show_type type
);
9513 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9514 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9516 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9517 const char *comstr
, int exact
, afi_t afi
,
9518 safi_t safi
, bool use_json
);
9521 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9522 struct bgp_table
*table
, enum bgp_show_type type
,
9523 void *output_arg
, bool use_json
, char *rd
,
9524 int is_last
, unsigned long *output_cum
,
9525 unsigned long *total_cum
,
9526 unsigned long *json_header_depth
)
9528 struct bgp_path_info
*pi
;
9529 struct bgp_node
*rn
;
9532 unsigned long output_count
= 0;
9533 unsigned long total_count
= 0;
9536 json_object
*json_paths
= NULL
;
9539 if (output_cum
&& *output_cum
!= 0)
9542 if (use_json
&& !*json_header_depth
) {
9544 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9545 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9546 " \"localAS\": %u,\n \"routes\": { ",
9547 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9548 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9551 table
->version
, inet_ntoa(bgp
->router_id
),
9552 bgp
->default_local_pref
, bgp
->as
);
9553 *json_header_depth
= 2;
9555 vty_out(vty
, " \"routeDistinguishers\" : {");
9556 ++*json_header_depth
;
9560 if (use_json
&& rd
) {
9561 vty_out(vty
, " \"%s\" : { ", rd
);
9564 /* Start processing of routes. */
9565 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9566 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
9568 pi
= bgp_node_get_bgp_path_info(rn
);
9574 json_paths
= json_object_new_array();
9578 for (; pi
; pi
= pi
->next
) {
9580 if (type
== bgp_show_type_flap_statistics
9581 || type
== bgp_show_type_flap_neighbor
9582 || type
== bgp_show_type_dampend_paths
9583 || type
== bgp_show_type_damp_neighbor
) {
9584 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9587 if (type
== bgp_show_type_regexp
) {
9588 regex_t
*regex
= output_arg
;
9590 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9594 if (type
== bgp_show_type_prefix_list
) {
9595 struct prefix_list
*plist
= output_arg
;
9597 if (prefix_list_apply(plist
, rn_p
)
9601 if (type
== bgp_show_type_filter_list
) {
9602 struct as_list
*as_list
= output_arg
;
9604 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9605 != AS_FILTER_PERMIT
)
9608 if (type
== bgp_show_type_route_map
) {
9609 struct route_map
*rmap
= output_arg
;
9610 struct bgp_path_info path
;
9611 struct attr dummy_attr
;
9612 route_map_result_t ret
;
9614 dummy_attr
= *pi
->attr
;
9616 path
.peer
= pi
->peer
;
9617 path
.attr
= &dummy_attr
;
9619 ret
= route_map_apply(rmap
, rn_p
, RMAP_BGP
,
9621 if (ret
== RMAP_DENYMATCH
)
9624 if (type
== bgp_show_type_neighbor
9625 || type
== bgp_show_type_flap_neighbor
9626 || type
== bgp_show_type_damp_neighbor
) {
9627 union sockunion
*su
= output_arg
;
9629 if (pi
->peer
== NULL
9630 || pi
->peer
->su_remote
== NULL
9631 || !sockunion_same(pi
->peer
->su_remote
, su
))
9634 if (type
== bgp_show_type_cidr_only
) {
9635 uint32_t destination
;
9637 destination
= ntohl(rn_p
->u
.prefix4
.s_addr
);
9638 if (IN_CLASSC(destination
)
9639 && rn_p
->prefixlen
== 24)
9641 if (IN_CLASSB(destination
)
9642 && rn_p
->prefixlen
== 16)
9644 if (IN_CLASSA(destination
)
9645 && rn_p
->prefixlen
== 8)
9648 if (type
== bgp_show_type_prefix_longer
) {
9650 if (!prefix_match(p
, rn_p
))
9653 if (type
== bgp_show_type_community_all
) {
9654 if (!pi
->attr
->community
)
9657 if (type
== bgp_show_type_community
) {
9658 struct community
*com
= output_arg
;
9660 if (!pi
->attr
->community
9661 || !community_match(pi
->attr
->community
,
9665 if (type
== bgp_show_type_community_exact
) {
9666 struct community
*com
= output_arg
;
9668 if (!pi
->attr
->community
9669 || !community_cmp(pi
->attr
->community
, com
))
9672 if (type
== bgp_show_type_community_list
) {
9673 struct community_list
*list
= output_arg
;
9675 if (!community_list_match(pi
->attr
->community
,
9679 if (type
== bgp_show_type_community_list_exact
) {
9680 struct community_list
*list
= output_arg
;
9682 if (!community_list_exact_match(
9683 pi
->attr
->community
, list
))
9686 if (type
== bgp_show_type_lcommunity
) {
9687 struct lcommunity
*lcom
= output_arg
;
9689 if (!pi
->attr
->lcommunity
9690 || !lcommunity_match(pi
->attr
->lcommunity
,
9695 if (type
== bgp_show_type_lcommunity_exact
) {
9696 struct lcommunity
*lcom
= output_arg
;
9698 if (!pi
->attr
->lcommunity
9699 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9703 if (type
== bgp_show_type_lcommunity_list
) {
9704 struct community_list
*list
= output_arg
;
9706 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9711 == bgp_show_type_lcommunity_list_exact
) {
9712 struct community_list
*list
= output_arg
;
9714 if (!lcommunity_list_exact_match(
9715 pi
->attr
->lcommunity
, list
))
9718 if (type
== bgp_show_type_lcommunity_all
) {
9719 if (!pi
->attr
->lcommunity
)
9722 if (type
== bgp_show_type_dampend_paths
9723 || type
== bgp_show_type_damp_neighbor
) {
9724 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9725 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9729 if (!use_json
&& header
) {
9730 vty_out(vty
, "BGP table version is %" PRIu64
9731 ", local router ID is %s, vrf id ",
9733 inet_ntoa(bgp
->router_id
));
9734 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9735 vty_out(vty
, "%s", VRFID_NONE_STR
);
9737 vty_out(vty
, "%u", bgp
->vrf_id
);
9739 vty_out(vty
, "Default local pref %u, ",
9740 bgp
->default_local_pref
);
9741 vty_out(vty
, "local AS %u\n", bgp
->as
);
9742 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9743 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9744 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9745 if (type
== bgp_show_type_dampend_paths
9746 || type
== bgp_show_type_damp_neighbor
)
9747 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9748 else if (type
== bgp_show_type_flap_statistics
9749 || type
== bgp_show_type_flap_neighbor
)
9750 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9752 vty_out(vty
, BGP_SHOW_HEADER
);
9755 if (rd
!= NULL
&& !display
&& !output_count
) {
9758 "Route Distinguisher: %s\n",
9761 if (type
== bgp_show_type_dampend_paths
9762 || type
== bgp_show_type_damp_neighbor
)
9763 damp_route_vty_out(vty
, rn_p
, pi
, display
,
9764 AFI_IP
, safi
, use_json
,
9766 else if (type
== bgp_show_type_flap_statistics
9767 || type
== bgp_show_type_flap_neighbor
)
9768 flap_route_vty_out(vty
, rn_p
, pi
, display
,
9769 AFI_IP
, safi
, use_json
,
9772 route_vty_out(vty
, rn_p
, pi
, display
, safi
,
9783 if (rn_p
->family
== AF_FLOWSPEC
) {
9784 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9786 bgp_fs_nlri_get_string(
9788 rn_p
->u
.prefix_flowspec
.ptr
,
9789 rn_p
->u
.prefix_flowspec
.prefixlen
,
9790 retstr
, NLRI_STRING_FORMAT_MIN
, NULL
);
9792 vty_out(vty
, "\"%s/%d\": ", retstr
,
9793 rn_p
->u
.prefix_flowspec
9796 vty_out(vty
, ",\"%s/%d\": ", retstr
,
9797 rn_p
->u
.prefix_flowspec
9800 prefix2str(rn_p
, buf2
, sizeof(buf2
));
9802 vty_out(vty
, "\"%s\": ", buf2
);
9804 vty_out(vty
, ",\"%s\": ", buf2
);
9807 json_object_to_json_string_ext(
9808 json_paths
, JSON_C_TO_STRING_PRETTY
));
9809 json_object_free(json_paths
);
9813 json_object_free(json_paths
);
9817 output_count
+= *output_cum
;
9818 *output_cum
= output_count
;
9821 total_count
+= *total_cum
;
9822 *total_cum
= total_count
;
9826 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9830 for (i
= 0; i
< *json_header_depth
; ++i
)
9831 vty_out(vty
, " } ");
9836 /* No route is displayed */
9837 if (output_count
== 0) {
9838 if (type
== bgp_show_type_normal
)
9840 "No BGP prefixes displayed, %ld exist\n",
9844 "\nDisplayed %ld routes and %ld total paths\n",
9845 output_count
, total_count
);
9852 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9853 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9854 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9856 struct bgp_node
*rn
, *next
;
9857 unsigned long output_cum
= 0;
9858 unsigned long total_cum
= 0;
9859 unsigned long json_header_depth
= 0;
9860 struct bgp_table
*itable
;
9863 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9865 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9866 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
9868 next
= bgp_route_next(rn
);
9869 if (prd_match
&& memcmp(rn_p
->u
.val
, prd_match
->val
, 8) != 0)
9872 itable
= bgp_node_get_bgp_table_info(rn
);
9873 if (itable
!= NULL
) {
9874 struct prefix_rd prd
;
9875 char rd
[RD_ADDRSTRLEN
];
9877 memcpy(&prd
, rn_p
, sizeof(struct prefix_rd
));
9878 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9879 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9880 use_json
, rd
, next
== NULL
, &output_cum
,
9881 &total_cum
, &json_header_depth
);
9887 if (output_cum
== 0)
9888 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9892 "\nDisplayed %ld routes and %ld total paths\n",
9893 output_cum
, total_cum
);
9897 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9898 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9900 struct bgp_table
*table
;
9901 unsigned long json_header_depth
= 0;
9904 bgp
= bgp_get_default();
9909 vty_out(vty
, "No BGP process is configured\n");
9911 vty_out(vty
, "{}\n");
9915 table
= bgp
->rib
[afi
][safi
];
9916 /* use MPLS and ENCAP specific shows until they are merged */
9917 if (safi
== SAFI_MPLS_VPN
) {
9918 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9919 output_arg
, use_json
);
9922 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9923 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9924 output_arg
, use_json
,
9927 /* labeled-unicast routes live in the unicast table */
9928 else if (safi
== SAFI_LABELED_UNICAST
)
9929 safi
= SAFI_UNICAST
;
9931 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9932 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9935 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9936 safi_t safi
, bool use_json
)
9938 struct listnode
*node
, *nnode
;
9941 bool route_output
= false;
9944 vty_out(vty
, "{\n");
9946 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9947 route_output
= true;
9950 vty_out(vty
, ",\n");
9954 vty_out(vty
, "\"%s\":",
9955 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9959 vty_out(vty
, "\nInstance %s:\n",
9960 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9964 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9969 vty_out(vty
, "}\n");
9970 else if (!route_output
)
9971 vty_out(vty
, "%% BGP instance not found\n");
9974 /* Header of detailed BGP route information */
9975 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9976 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9977 afi_t afi
, safi_t safi
, json_object
*json
)
9979 struct bgp_path_info
*pi
;
9980 const struct prefix
*p
;
9982 struct listnode
*node
, *nnode
;
9983 char buf1
[RD_ADDRSTRLEN
];
9984 char buf2
[INET6_ADDRSTRLEN
];
9985 char buf3
[EVPN_ROUTE_STRLEN
];
9986 char prefix_str
[BUFSIZ
];
9991 int route_filter_translated_v4
= 0;
9992 int route_filter_v4
= 0;
9993 int route_filter_translated_v6
= 0;
9994 int route_filter_v6
= 0;
9997 int accept_own_nexthop
= 0;
10000 int no_advertise
= 0;
10004 int has_valid_label
= 0;
10005 mpls_label_t label
= 0;
10006 json_object
*json_adv_to
= NULL
;
10008 p
= bgp_node_get_prefix(rn
);
10009 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
10011 if (has_valid_label
)
10012 label
= label_pton(&rn
->local_label
);
10014 if (safi
== SAFI_EVPN
) {
10017 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
10018 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
10019 : "", prd
? ":" : "",
10020 bgp_evpn_route2str((struct prefix_evpn
*)p
,
10021 buf3
, sizeof(buf3
)));
10023 json_object_string_add(json
, "rd",
10024 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
10026 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
10030 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
10031 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
10032 ? prefix_rd2str(prd
, buf1
,
10035 safi
== SAFI_MPLS_VPN
? ":" : "",
10036 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
10041 json_object_string_add(json
, "prefix",
10042 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
10045 if (has_valid_label
) {
10047 json_object_int_add(json
, "localLabel", label
);
10049 vty_out(vty
, "Local label: %d\n", label
);
10053 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
10054 vty_out(vty
, "not allocated\n");
10056 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10058 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
10060 if (pi
->extra
&& pi
->extra
->suppress
)
10063 if (pi
->attr
->community
== NULL
)
10066 no_advertise
+= community_include(
10067 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
10068 no_export
+= community_include(pi
->attr
->community
,
10069 COMMUNITY_NO_EXPORT
);
10070 local_as
+= community_include(pi
->attr
->community
,
10071 COMMUNITY_LOCAL_AS
);
10072 accept_own
+= community_include(pi
->attr
->community
,
10073 COMMUNITY_ACCEPT_OWN
);
10074 route_filter_translated_v4
+= community_include(
10075 pi
->attr
->community
,
10076 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
10077 route_filter_translated_v6
+= community_include(
10078 pi
->attr
->community
,
10079 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
10080 route_filter_v4
+= community_include(
10081 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
10082 route_filter_v6
+= community_include(
10083 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
10084 llgr_stale
+= community_include(pi
->attr
->community
,
10085 COMMUNITY_LLGR_STALE
);
10086 no_llgr
+= community_include(pi
->attr
->community
,
10087 COMMUNITY_NO_LLGR
);
10088 accept_own_nexthop
+=
10089 community_include(pi
->attr
->community
,
10090 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
10091 blackhole
+= community_include(pi
->attr
->community
,
10092 COMMUNITY_BLACKHOLE
);
10093 no_peer
+= community_include(pi
->attr
->community
,
10094 COMMUNITY_NO_PEER
);
10099 vty_out(vty
, "Paths: (%d available", count
);
10101 vty_out(vty
, ", best #%d", best
);
10102 if (safi
== SAFI_UNICAST
) {
10103 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
10104 vty_out(vty
, ", table %s",
10107 vty_out(vty
, ", vrf %s",
10111 vty_out(vty
, ", no best path");
10115 ", accept own local route exported and imported in different VRF");
10116 else if (route_filter_translated_v4
)
10118 ", mark translated RTs for VPNv4 route filtering");
10119 else if (route_filter_v4
)
10121 ", attach RT as-is for VPNv4 route filtering");
10122 else if (route_filter_translated_v6
)
10124 ", mark translated RTs for VPNv6 route filtering");
10125 else if (route_filter_v6
)
10127 ", attach RT as-is for VPNv6 route filtering");
10128 else if (llgr_stale
)
10130 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10133 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10134 else if (accept_own_nexthop
)
10136 ", accept local nexthop");
10137 else if (blackhole
)
10138 vty_out(vty
, ", inform peer to blackhole prefix");
10139 else if (no_export
)
10140 vty_out(vty
, ", not advertised to EBGP peer");
10141 else if (no_advertise
)
10142 vty_out(vty
, ", not advertised to any peer");
10144 vty_out(vty
, ", not advertised outside local AS");
10147 ", inform EBGP peer not to advertise to their EBGP peers");
10151 ", Advertisements suppressed by an aggregate.");
10152 vty_out(vty
, ")\n");
10155 /* If we are not using addpath then we can display Advertised to and
10157 * show what peers we advertised the bestpath to. If we are using
10159 * though then we must display Advertised to on a path-by-path basis. */
10160 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10161 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10162 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
10163 if (json
&& !json_adv_to
)
10164 json_adv_to
= json_object_new_object();
10166 route_vty_out_advertised_to(
10168 " Advertised to non peer-group peers:\n ",
10175 json_object_object_add(json
, "advertisedTo",
10180 vty_out(vty
, " Not advertised to any peer");
10181 vty_out(vty
, "\n");
10186 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10187 struct bgp_node
*bgp_node
, struct vty
*vty
,
10188 struct bgp
*bgp
, afi_t afi
,
10189 safi_t safi
, json_object
*json
,
10190 enum bgp_path_type pathtype
, int *display
)
10192 struct bgp_path_info
*pi
;
10194 char rdbuf
[RD_ADDRSTRLEN
];
10195 json_object
*json_header
= NULL
;
10196 json_object
*json_paths
= NULL
;
10198 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
10201 if (json
&& !json_paths
) {
10202 /* Instantiate json_paths only if path is valid */
10203 json_paths
= json_object_new_array();
10205 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10206 json_header
= json_object_new_object();
10208 json_header
= json
;
10212 route_vty_out_detail_header(
10213 vty
, bgp
, bgp_node
, pfx_rd
,
10214 AFI_IP
, safi
, json_header
);
10219 if (pathtype
== BGP_PATH_SHOW_ALL
10220 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10221 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10222 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10223 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10224 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10225 route_vty_out_detail(vty
, bgp
, bgp_node
,
10230 if (json
&& json_paths
) {
10231 json_object_object_add(json_header
, "paths", json_paths
);
10234 json_object_object_add(json
, rdbuf
, json_header
);
10238 /* Display specified route of BGP table. */
10239 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10240 struct bgp_table
*rib
, const char *ip_str
,
10241 afi_t afi
, safi_t safi
,
10242 struct prefix_rd
*prd
, int prefix_check
,
10243 enum bgp_path_type pathtype
, bool use_json
)
10247 struct prefix match
;
10248 struct bgp_node
*rn
;
10249 struct bgp_node
*rm
;
10250 struct bgp_table
*table
;
10251 json_object
*json
= NULL
;
10252 json_object
*json_paths
= NULL
;
10254 /* Check IP address argument. */
10255 ret
= str2prefix(ip_str
, &match
);
10257 vty_out(vty
, "address is malformed\n");
10258 return CMD_WARNING
;
10261 match
.family
= afi2family(afi
);
10264 json
= json_object_new_object();
10266 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10267 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10268 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
10270 if (prd
&& memcmp(rn_p
->u
.val
, prd
->val
, 8) != 0)
10272 table
= bgp_node_get_bgp_table_info(rn
);
10276 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10279 const struct prefix
*rm_p
= bgp_node_get_prefix(rm
);
10281 && rm_p
->prefixlen
!= match
.prefixlen
) {
10282 bgp_unlock_node(rm
);
10286 bgp_show_path_info((struct prefix_rd
*)rn_p
, rm
, vty
,
10287 bgp
, afi
, safi
, json
, pathtype
,
10290 bgp_unlock_node(rm
);
10292 } else if (safi
== SAFI_EVPN
) {
10293 struct bgp_node
*longest_pfx
;
10294 bool is_exact_pfxlen_match
= FALSE
;
10296 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10297 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
10299 if (prd
&& memcmp(&rn_p
->u
.val
, prd
->val
, 8) != 0)
10301 table
= bgp_node_get_bgp_table_info(rn
);
10305 longest_pfx
= NULL
;
10306 is_exact_pfxlen_match
= FALSE
;
10308 * Search through all the prefixes for a match. The
10309 * pfx's are enumerated in ascending order of pfxlens.
10310 * So, the last pfx match is the longest match. Set
10311 * is_exact_pfxlen_match when we get exact pfxlen match
10313 for (rm
= bgp_table_top(table
); rm
;
10314 rm
= bgp_route_next(rm
)) {
10315 const struct prefix
*rm_p
=
10316 bgp_node_get_prefix(rm
);
10318 * Get prefixlen of the ip-prefix within type5
10321 if (evpn_type5_prefix_match(rm_p
, &match
)
10325 bgp_evpn_get_type5_prefixlen(
10327 if (type5_pfxlen
== match
.prefixlen
) {
10328 is_exact_pfxlen_match
= TRUE
;
10329 bgp_unlock_node(rm
);
10338 if (prefix_check
&& !is_exact_pfxlen_match
)
10344 bgp_show_path_info((struct prefix_rd
*)rn_p
, rm
, vty
,
10345 bgp
, afi
, safi
, json
, pathtype
,
10348 bgp_unlock_node(rm
);
10350 } else if (safi
== SAFI_FLOWSPEC
) {
10352 json_paths
= json_object_new_array();
10354 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10355 &match
, prefix_check
,
10359 if (use_json
&& display
)
10360 json_object_object_add(json
, "paths", json_paths
);
10362 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
10363 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
10365 || rn_p
->prefixlen
== match
.prefixlen
) {
10366 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
10368 pathtype
, &display
);
10371 bgp_unlock_node(rn
);
10376 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10377 json
, JSON_C_TO_STRING_PRETTY
|
10378 JSON_C_TO_STRING_NOSLASHESCAPE
));
10379 json_object_free(json
);
10382 vty_out(vty
, "%% Network not in table\n");
10383 return CMD_WARNING
;
10387 return CMD_SUCCESS
;
10390 /* Display specified route of Main RIB */
10391 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10392 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10393 int prefix_check
, enum bgp_path_type pathtype
,
10397 bgp
= bgp_get_default();
10400 vty_out(vty
, "No BGP process is configured\n");
10402 vty_out(vty
, "{}\n");
10403 return CMD_WARNING
;
10407 /* labeled-unicast routes live in the unicast table */
10408 if (safi
== SAFI_LABELED_UNICAST
)
10409 safi
= SAFI_UNICAST
;
10411 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10412 afi
, safi
, prd
, prefix_check
, pathtype
,
10416 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10417 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10418 safi_t safi
, bool uj
)
10420 struct lcommunity
*lcom
;
10426 b
= buffer_new(1024);
10427 for (i
= 0; i
< argc
; i
++) {
10429 buffer_putc(b
, ' ');
10431 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10433 buffer_putstr(b
, argv
[i
]->arg
);
10437 buffer_putc(b
, '\0');
10439 str
= buffer_getstr(b
);
10442 lcom
= lcommunity_str2com(str
);
10443 XFREE(MTYPE_TMP
, str
);
10445 vty_out(vty
, "%% Large-community malformed\n");
10446 return CMD_WARNING
;
10449 return bgp_show(vty
, bgp
, afi
, safi
,
10450 (exact
? bgp_show_type_lcommunity_exact
10451 : bgp_show_type_lcommunity
),
10455 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10456 const char *lcom
, bool exact
, afi_t afi
,
10457 safi_t safi
, bool uj
)
10459 struct community_list
*list
;
10461 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10462 LARGE_COMMUNITY_LIST_MASTER
);
10463 if (list
== NULL
) {
10464 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10466 return CMD_WARNING
;
10469 return bgp_show(vty
, bgp
, afi
, safi
,
10470 (exact
? bgp_show_type_lcommunity_list_exact
10471 : bgp_show_type_lcommunity_list
),
10475 DEFUN (show_ip_bgp_large_community_list
,
10476 show_ip_bgp_large_community_list_cmd
,
10477 "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]",
10481 BGP_INSTANCE_HELP_STR
10483 BGP_SAFI_WITH_LABEL_HELP_STR
10484 "Display routes matching the large-community-list\n"
10485 "large-community-list number\n"
10486 "large-community-list name\n"
10487 "Exact match of the large-communities\n"
10490 afi_t afi
= AFI_IP6
;
10491 safi_t safi
= SAFI_UNICAST
;
10493 bool exact_match
= 0;
10494 struct bgp
*bgp
= NULL
;
10495 bool uj
= use_json(argc
, argv
);
10500 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10503 return CMD_WARNING
;
10505 argv_find(argv
, argc
, "large-community-list", &idx
);
10507 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10509 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10512 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10513 exact_match
, afi
, safi
, uj
);
10515 DEFUN (show_ip_bgp_large_community
,
10516 show_ip_bgp_large_community_cmd
,
10517 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10521 BGP_INSTANCE_HELP_STR
10523 BGP_SAFI_WITH_LABEL_HELP_STR
10524 "Display routes matching the large-communities\n"
10525 "List of large-community numbers\n"
10526 "Exact match of the large-communities\n"
10529 afi_t afi
= AFI_IP6
;
10530 safi_t safi
= SAFI_UNICAST
;
10532 bool exact_match
= 0;
10533 struct bgp
*bgp
= NULL
;
10534 bool uj
= use_json(argc
, argv
);
10539 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10542 return CMD_WARNING
;
10544 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10545 if (argv_find(argv
, argc
, "exact-match", &idx
))
10547 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10548 exact_match
, afi
, safi
, uj
);
10550 return bgp_show(vty
, bgp
, afi
, safi
,
10551 bgp_show_type_lcommunity_all
, NULL
, uj
);
10554 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10555 safi_t safi
, struct json_object
*json
);
10558 DEFUN (show_ip_bgp_statistics_all
,
10559 show_ip_bgp_statistics_all_cmd
,
10560 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10564 BGP_INSTANCE_HELP_STR
10565 "Display number of prefixes for all afi/safi\n"
10568 bool uj
= use_json(argc
, argv
);
10569 struct bgp
*bgp
= NULL
;
10573 struct json_object
*json_all
= NULL
;
10574 struct json_object
*json_afi_safi
= NULL
;
10576 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10579 return CMD_WARNING
;
10582 json_all
= json_object_new_object();
10584 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
10585 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
10587 * So limit output to those afi/safi
10589 * actualy have something interesting in
10592 if (strmatch(get_afi_safi_str(afi
, safi
, true),
10597 json_afi_safi
= json_object_new_array();
10599 json_afi_safi
= NULL
;
10601 bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10604 json_object_object_add(json_all
,
10605 get_afi_safi_str(afi
,
10613 vty_out(vty
, "%s", json_object_to_json_string_ext(
10614 json_all
, JSON_C_TO_STRING_PRETTY
));
10615 json_object_free(json_all
);
10618 return CMD_SUCCESS
;
10621 /* BGP route print out function without JSON */
10622 DEFUN (show_ip_bgp_l2vpn_evpn_statistics
,
10623 show_ip_bgp_l2vpn_evpn_statistics_cmd
,
10624 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [l2vpn [evpn]] statistics [json]",
10628 BGP_INSTANCE_HELP_STR
10631 "BGP RIB advertisement statistics\n"
10634 afi_t afi
= AFI_L2VPN
;
10635 safi_t safi
= SAFI_EVPN
;
10636 struct bgp
*bgp
= NULL
;
10638 bool uj
= use_json(argc
, argv
);
10639 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10641 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10644 return CMD_WARNING
;
10647 json_afi_safi
= json_object_new_array();
10649 json_afi_safi
= NULL
;
10651 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10654 json
= json_object_new_object();
10655 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10657 vty_out(vty
, "%s", json_object_to_json_string_ext(
10658 json
, JSON_C_TO_STRING_PRETTY
));
10659 json_object_free(json
);
10664 /* BGP route print out function without JSON */
10665 DEFUN (show_ip_bgp_afi_safi_statistics
,
10666 show_ip_bgp_afi_safi_statistics_cmd
,
10667 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10668 statistics [json]",
10672 BGP_INSTANCE_HELP_STR
10674 BGP_SAFI_WITH_LABEL_HELP_STR
10675 "BGP RIB advertisement statistics\n"
10678 afi_t afi
= AFI_IP6
;
10679 safi_t safi
= SAFI_UNICAST
;
10680 struct bgp
*bgp
= NULL
;
10682 bool uj
= use_json(argc
, argv
);
10683 struct json_object
*json_afi_safi
= NULL
, *json
= NULL
;
10685 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10688 return CMD_WARNING
;
10691 json_afi_safi
= json_object_new_array();
10693 json_afi_safi
= NULL
;
10695 ret
= bgp_table_stats(vty
, bgp
, afi
, safi
, json_afi_safi
);
10698 json
= json_object_new_object();
10699 json_object_object_add(json
, get_afi_safi_str(afi
, safi
, true),
10701 vty_out(vty
, "%s", json_object_to_json_string_ext(
10702 json
, JSON_C_TO_STRING_PRETTY
));
10703 json_object_free(json
);
10709 /* BGP route print out function without JSON */
10710 DEFUN (show_ip_bgp
,
10712 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10713 <dampening <parameters>\
10717 |community-list <(1-500)|WORD> [exact-match]\
10718 |A.B.C.D/M longer-prefixes\
10719 |X:X::X:X/M longer-prefixes\
10724 BGP_INSTANCE_HELP_STR
10726 BGP_SAFI_WITH_LABEL_HELP_STR
10727 "Display detailed information about dampening\n"
10728 "Display detail of configured dampening parameters\n"
10729 "Display routes matching the route-map\n"
10730 "A route-map to match on\n"
10731 "Display routes conforming to the prefix-list\n"
10732 "Prefix-list name\n"
10733 "Display routes conforming to the filter-list\n"
10734 "Regular expression access list name\n"
10735 "Display routes matching the community-list\n"
10736 "community-list number\n"
10737 "community-list name\n"
10738 "Exact match of the communities\n"
10740 "Display route and more specific routes\n"
10742 "Display route and more specific routes\n")
10744 afi_t afi
= AFI_IP6
;
10745 safi_t safi
= SAFI_UNICAST
;
10746 int exact_match
= 0;
10747 struct bgp
*bgp
= NULL
;
10750 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10753 return CMD_WARNING
;
10755 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10756 if (argv_find(argv
, argc
, "parameters", &idx
))
10757 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10760 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10761 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10762 safi
, bgp_show_type_prefix_list
);
10764 if (argv_find(argv
, argc
, "filter-list", &idx
))
10765 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10766 safi
, bgp_show_type_filter_list
);
10768 if (argv_find(argv
, argc
, "route-map", &idx
))
10769 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10770 safi
, bgp_show_type_route_map
);
10772 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10773 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10774 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10776 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10777 exact_match
, afi
, safi
);
10779 /* prefix-longer */
10780 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10781 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10782 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10784 bgp_show_type_prefix_longer
);
10786 return CMD_WARNING
;
10789 /* BGP route print out function with JSON */
10790 DEFUN (show_ip_bgp_json
,
10791 show_ip_bgp_json_cmd
,
10792 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10794 |dampening <flap-statistics|dampened-paths>\
10795 |community [AA:NN|local-AS|no-advertise|no-export\
10796 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10797 |accept-own|accept-own-nexthop|route-filter-v6\
10798 |route-filter-v4|route-filter-translated-v6\
10799 |route-filter-translated-v4] [exact-match]\
10804 BGP_INSTANCE_HELP_STR
10806 BGP_SAFI_WITH_LABEL_HELP_STR
10807 "Display only routes with non-natural netmasks\n"
10808 "Display detailed information about dampening\n"
10809 "Display flap statistics of routes\n"
10810 "Display paths suppressed due to dampening\n"
10811 "Display routes matching the communities\n"
10813 "Do not send outside local AS (well-known community)\n"
10814 "Do not advertise to any peer (well-known community)\n"
10815 "Do not export to next AS (well-known community)\n"
10816 "Graceful shutdown (well-known community)\n"
10817 "Do not export to any peer (well-known community)\n"
10818 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10819 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10820 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10821 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10822 "Should accept VPN route with local nexthop (well-known community)\n"
10823 "RT VPNv6 route filtering (well-known community)\n"
10824 "RT VPNv4 route filtering (well-known community)\n"
10825 "RT translated VPNv6 route filtering (well-known community)\n"
10826 "RT translated VPNv4 route filtering (well-known community)\n"
10827 "Exact match of the communities\n"
10830 afi_t afi
= AFI_IP6
;
10831 safi_t safi
= SAFI_UNICAST
;
10832 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10833 struct bgp
*bgp
= NULL
;
10835 int exact_match
= 0;
10836 bool uj
= use_json(argc
, argv
);
10841 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10844 return CMD_WARNING
;
10846 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10847 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10850 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10851 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10852 return bgp_show(vty
, bgp
, afi
, safi
,
10853 bgp_show_type_dampend_paths
, NULL
, uj
);
10854 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10855 return bgp_show(vty
, bgp
, afi
, safi
,
10856 bgp_show_type_flap_statistics
, NULL
,
10860 if (argv_find(argv
, argc
, "community", &idx
)) {
10861 char *maybecomm
= NULL
;
10862 char *community
= NULL
;
10864 if (idx
+ 1 < argc
) {
10865 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10866 maybecomm
= argv
[idx
+ 1]->arg
;
10868 maybecomm
= argv
[idx
+ 1]->text
;
10871 if (maybecomm
&& !strmatch(maybecomm
, "json")
10872 && !strmatch(maybecomm
, "exact-match"))
10873 community
= maybecomm
;
10875 if (argv_find(argv
, argc
, "exact-match", &idx
))
10879 return bgp_show_community(vty
, bgp
, community
,
10880 exact_match
, afi
, safi
, uj
);
10882 return (bgp_show(vty
, bgp
, afi
, safi
,
10883 bgp_show_type_community_all
, NULL
,
10887 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10890 DEFUN (show_ip_bgp_route
,
10891 show_ip_bgp_route_cmd
,
10892 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10893 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10897 BGP_INSTANCE_HELP_STR
10899 BGP_SAFI_WITH_LABEL_HELP_STR
10900 "Network in the BGP routing table to display\n"
10902 "Network in the BGP routing table to display\n"
10904 "Display only the bestpath\n"
10905 "Display only multipaths\n"
10908 int prefix_check
= 0;
10910 afi_t afi
= AFI_IP6
;
10911 safi_t safi
= SAFI_UNICAST
;
10912 char *prefix
= NULL
;
10913 struct bgp
*bgp
= NULL
;
10914 enum bgp_path_type path_type
;
10915 bool uj
= use_json(argc
, argv
);
10919 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10922 return CMD_WARNING
;
10926 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10927 return CMD_WARNING
;
10930 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10931 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10932 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10934 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10935 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10938 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10939 && afi
!= AFI_IP6
) {
10941 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10942 return CMD_WARNING
;
10944 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10945 && afi
!= AFI_IP
) {
10947 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10948 return CMD_WARNING
;
10951 prefix
= argv
[idx
]->arg
;
10953 /* [<bestpath|multipath>] */
10954 if (argv_find(argv
, argc
, "bestpath", &idx
))
10955 path_type
= BGP_PATH_SHOW_BESTPATH
;
10956 else if (argv_find(argv
, argc
, "multipath", &idx
))
10957 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10959 path_type
= BGP_PATH_SHOW_ALL
;
10961 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10965 DEFUN (show_ip_bgp_regexp
,
10966 show_ip_bgp_regexp_cmd
,
10967 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10971 BGP_INSTANCE_HELP_STR
10973 BGP_SAFI_WITH_LABEL_HELP_STR
10974 "Display routes matching the AS path regular expression\n"
10975 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10978 afi_t afi
= AFI_IP6
;
10979 safi_t safi
= SAFI_UNICAST
;
10980 struct bgp
*bgp
= NULL
;
10981 bool uj
= use_json(argc
, argv
);
10982 char *regstr
= NULL
;
10985 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10988 return CMD_WARNING
;
10990 // get index of regex
10991 if (argv_find(argv
, argc
, "REGEX", &idx
))
10992 regstr
= argv
[idx
]->arg
;
10995 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10996 bgp_show_type_regexp
, uj
);
10999 DEFUN (show_ip_bgp_instance_all
,
11000 show_ip_bgp_instance_all_cmd
,
11001 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
11005 BGP_INSTANCE_ALL_HELP_STR
11007 BGP_SAFI_WITH_LABEL_HELP_STR
11010 afi_t afi
= AFI_IP
;
11011 safi_t safi
= SAFI_UNICAST
;
11012 struct bgp
*bgp
= NULL
;
11014 bool uj
= use_json(argc
, argv
);
11019 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11022 return CMD_WARNING
;
11024 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
11025 return CMD_SUCCESS
;
11028 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
11029 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
11035 if (!config_bgp_aspath_validate(regstr
)) {
11036 vty_out(vty
, "Invalid character in REGEX %s\n",
11038 return CMD_WARNING_CONFIG_FAILED
;
11041 regex
= bgp_regcomp(regstr
);
11043 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
11044 return CMD_WARNING
;
11047 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
11048 bgp_regex_free(regex
);
11052 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
11053 const char *prefix_list_str
, afi_t afi
,
11054 safi_t safi
, enum bgp_show_type type
)
11056 struct prefix_list
*plist
;
11058 plist
= prefix_list_lookup(afi
, prefix_list_str
);
11059 if (plist
== NULL
) {
11060 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
11062 return CMD_WARNING
;
11065 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
11068 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
11069 const char *filter
, afi_t afi
, safi_t safi
,
11070 enum bgp_show_type type
)
11072 struct as_list
*as_list
;
11074 as_list
= as_list_lookup(filter
);
11075 if (as_list
== NULL
) {
11076 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
11078 return CMD_WARNING
;
11081 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
11084 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
11085 const char *rmap_str
, afi_t afi
, safi_t safi
,
11086 enum bgp_show_type type
)
11088 struct route_map
*rmap
;
11090 rmap
= route_map_lookup_by_name(rmap_str
);
11092 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
11093 return CMD_WARNING
;
11096 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
11099 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
11100 const char *comstr
, int exact
, afi_t afi
,
11101 safi_t safi
, bool use_json
)
11103 struct community
*com
;
11106 com
= community_str2com(comstr
);
11108 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
11109 return CMD_WARNING
;
11112 ret
= bgp_show(vty
, bgp
, afi
, safi
,
11113 (exact
? bgp_show_type_community_exact
11114 : bgp_show_type_community
),
11116 community_free(&com
);
11121 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
11122 const char *com
, int exact
, afi_t afi
,
11125 struct community_list
*list
;
11127 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
11128 if (list
== NULL
) {
11129 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
11130 return CMD_WARNING
;
11133 return bgp_show(vty
, bgp
, afi
, safi
,
11134 (exact
? bgp_show_type_community_list_exact
11135 : bgp_show_type_community_list
),
11139 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
11140 const char *prefix
, afi_t afi
, safi_t safi
,
11141 enum bgp_show_type type
)
11148 ret
= str2prefix(prefix
, p
);
11150 vty_out(vty
, "%% Malformed Prefix\n");
11151 return CMD_WARNING
;
11154 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
11160 BGP_STATS_MAXBITLEN
= 0,
11162 BGP_STATS_PREFIXES
,
11164 BGP_STATS_UNAGGREGATEABLE
,
11165 BGP_STATS_MAX_AGGREGATEABLE
,
11166 BGP_STATS_AGGREGATES
,
11168 BGP_STATS_ASPATH_COUNT
,
11169 BGP_STATS_ASPATH_MAXHOPS
,
11170 BGP_STATS_ASPATH_TOTHOPS
,
11171 BGP_STATS_ASPATH_MAXSIZE
,
11172 BGP_STATS_ASPATH_TOTSIZE
,
11173 BGP_STATS_ASN_HIGHEST
,
11177 #define TABLE_STATS_IDX_VTY 0
11178 #define TABLE_STATS_IDX_JSON 1
11180 static const char *table_stats_strs
[][2] = {
11181 [BGP_STATS_PREFIXES
] = {"Total Prefixes", "totalPrefixes"},
11182 [BGP_STATS_TOTPLEN
] = {"Average prefix length", "averagePrefixLength"},
11183 [BGP_STATS_RIB
] = {"Total Advertisements", "totalAdvertisements"},
11184 [BGP_STATS_UNAGGREGATEABLE
] =
11185 {"Unaggregateable prefixes", "unaggregateablePrefixes"},
11186 [BGP_STATS_MAX_AGGREGATEABLE
] =
11187 {"Maximum aggregateable prefixes", "maximumAggregateablePrefixes"},
11188 [BGP_STATS_AGGREGATES
] =
11189 {"BGP Aggregate advertisements", "bgpAggregateAdvertisements"},
11190 [BGP_STATS_SPACE
] = {"Address space advertised",
11191 "addressSpaceAdvertised"},
11192 [BGP_STATS_ASPATH_COUNT
] =
11193 {"Advertisements with paths", "advertisementsWithPaths"},
11194 [BGP_STATS_ASPATH_MAXHOPS
] =
11195 {"Longest AS-Path (hops)", "longestAsPath"},
11196 [BGP_STATS_ASPATH_MAXSIZE
] =
11197 {"Largest AS-Path (bytes)","largestAsPath"},
11198 [BGP_STATS_ASPATH_TOTHOPS
] =
11199 {"Average AS-Path length (hops)", "averageAsPathLengthHops"},
11200 [BGP_STATS_ASPATH_TOTSIZE
] =
11201 {"Average AS-Path size (bytes)", "averageAsPathSizeBytes"},
11202 [BGP_STATS_ASN_HIGHEST
] = {"Highest public ASN","highestPublicAsn"},
11203 [BGP_STATS_MAX
] = {NULL
, NULL
}
11206 struct bgp_table_stats
{
11207 struct bgp_table
*table
;
11208 unsigned long long counts
[BGP_STATS_MAX
];
11209 double total_space
;
11213 #define TALLY_SIGFIG 100000
11214 static unsigned long
11215 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
11217 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
11218 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
11219 unsigned long ret
= newtot
/ count
;
11221 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
11228 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
11229 struct bgp_table_stats
*ts
, unsigned int space
)
11231 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
11232 struct bgp_path_info
*pi
;
11233 const struct prefix
*rn_p
;
11238 if (!bgp_node_has_bgp_path_info_data(rn
))
11241 rn_p
= bgp_node_get_prefix(rn
);
11242 ts
->counts
[BGP_STATS_PREFIXES
]++;
11243 ts
->counts
[BGP_STATS_TOTPLEN
] += rn_p
->prefixlen
;
11246 ts
->counts
[BGP_STATS_AVGPLEN
]
11247 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
11248 ts
->counts
[BGP_STATS_AVGPLEN
],
11252 /* check if the prefix is included by any other announcements */
11253 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
11254 prn
= bgp_node_parent_nolock(prn
);
11256 if (prn
== NULL
|| prn
== top
) {
11257 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
11258 /* announced address space */
11260 ts
->total_space
+= pow(2.0, space
- rn_p
->prefixlen
);
11261 } else if (bgp_node_has_bgp_path_info_data(prn
))
11262 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11265 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11266 ts
->counts
[BGP_STATS_RIB
]++;
11268 if (CHECK_FLAG(pi
->attr
->flag
,
11269 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11270 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11272 /* as-path stats */
11273 if (pi
->attr
->aspath
) {
11274 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11275 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11276 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11278 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11280 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11281 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11283 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11284 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11286 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11287 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11289 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11290 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11291 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11293 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11294 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11295 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11298 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11299 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11304 static int bgp_table_stats_walker(struct thread
*t
)
11306 struct bgp_node
*rn
, *nrn
;
11307 struct bgp_node
*top
;
11308 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11309 unsigned int space
= 0;
11311 if (!(top
= bgp_table_top(ts
->table
)))
11314 switch (ts
->table
->afi
) {
11316 space
= IPV4_MAX_BITLEN
;
11319 space
= IPV6_MAX_BITLEN
;
11325 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11327 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
11328 if (ts
->table
->safi
== SAFI_MPLS_VPN
||
11329 ts
->table
->safi
== SAFI_ENCAP
||
11330 ts
->table
->safi
== SAFI_EVPN
) {
11331 struct bgp_table
*table
;
11333 table
= bgp_node_get_bgp_table_info(rn
);
11337 top
= bgp_table_top(table
);
11338 for (nrn
= bgp_table_top(table
); nrn
;
11339 nrn
= bgp_route_next(nrn
))
11340 bgp_table_stats_rn(nrn
, top
, ts
, space
);
11342 bgp_table_stats_rn(rn
, top
, ts
, space
);
11349 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11350 safi_t safi
, struct json_object
*json_array
)
11352 struct bgp_table_stats ts
;
11354 int ret
= CMD_SUCCESS
;
11356 struct json_object
*json
= NULL
;
11359 json
= json_object_new_object();
11361 if (!bgp
->rib
[afi
][safi
]) {
11362 char warning_msg
[50];
11364 snprintf(warning_msg
, sizeof(warning_msg
),
11365 "%% No RIB exist's for the AFI(%d)/SAFI(%d)",
11369 vty_out(vty
, "%s\n", warning_msg
);
11371 json_object_string_add(json
, "warning",
11375 goto end_table_stats
;
11379 vty_out(vty
, "BGP %s RIB statistics\n",
11380 get_afi_safi_str(afi
, safi
, false));
11382 /* labeled-unicast routes live in the unicast table */
11383 if (safi
== SAFI_LABELED_UNICAST
)
11384 safi
= SAFI_UNICAST
;
11386 memset(&ts
, 0, sizeof(ts
));
11387 ts
.table
= bgp
->rib
[afi
][safi
];
11388 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11390 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11391 if ((!json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_VTY
]) ||
11392 (json
&& !table_stats_strs
[i
][TABLE_STATS_IDX_JSON
]))
11397 case BGP_STATS_ASPATH_AVGHOPS
:
11398 case BGP_STATS_ASPATH_AVGSIZE
:
11399 case BGP_STATS_AVGPLEN
:
11400 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11401 vty_out (vty
, "%12.2f",
11402 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11405 case BGP_STATS_ASPATH_TOTHOPS
:
11406 case BGP_STATS_ASPATH_TOTSIZE
:
11408 snprintf(temp_buf
, sizeof(temp_buf
), "%12.2f",
11409 ts
.counts
[i
] ? (float)ts
.counts
[i
] /
11410 (float)ts
.counts
[BGP_STATS_ASPATH_COUNT
]
11412 vty_out(vty
, "%-30s: %s",
11413 table_stats_strs
[i
][TABLE_STATS_IDX_VTY
],
11416 json_object_double_add(json
,
11417 table_stats_strs
[i
][TABLE_STATS_IDX_JSON
],
11418 ts
.counts
[i
] ? (double)ts
.counts
[i
] /
11419 (double)ts
.counts
[BGP_STATS_ASPATH_COUNT
]
11422 case BGP_STATS_TOTPLEN
:
11424 snprintf(temp_buf
, sizeof(temp_buf
), "%12.2f",
11425 ts
.counts
[i
] ? (float)ts
.counts
[i
] /
11426 (float)ts
.counts
[BGP_STATS_PREFIXES
]
11428 vty_out(vty
, "%-30s: %s",
11429 table_stats_strs
[i
][TABLE_STATS_IDX_VTY
],
11432 json_object_double_add(json
,
11433 table_stats_strs
[i
][TABLE_STATS_IDX_JSON
],
11434 ts
.counts
[i
] ? (double)ts
.counts
[i
] /
11435 (double)ts
.counts
[BGP_STATS_PREFIXES
] : 0);
11437 case BGP_STATS_SPACE
:
11439 snprintf(temp_buf
, sizeof(temp_buf
), "%12g",
11441 vty_out(vty
, "%-30s: %s\n",
11442 table_stats_strs
[i
][TABLE_STATS_IDX_VTY
],
11445 json_object_double_add(json
,
11446 table_stats_strs
[i
][TABLE_STATS_IDX_JSON
],
11447 (double)ts
.total_space
);
11448 if (afi
== AFI_IP6
) {
11450 snprintf(temp_buf
, sizeof(temp_buf
),
11451 "%12g", ts
.total_space
*
11452 pow(2.0, -128 + 32));
11453 vty_out(vty
, "%30s: %s\n",
11454 "/32 equivalent %s\n",
11457 json_object_double_add(json
,
11459 (double)(ts
.total_space
*
11460 pow(2.0, -128 + 32)));
11462 snprintf(temp_buf
, sizeof(temp_buf
),
11463 "%12g", ts
.total_space
*
11464 pow(2.0, -128 + 48));
11465 vty_out(vty
, "%30s: %s\n",
11466 "/48 equivalent %s\n",
11469 json_object_double_add(json
,
11471 (double)(ts
.total_space
*
11472 pow(2.0, -128 + 48)));
11475 snprintf(temp_buf
, sizeof(temp_buf
),
11477 ts
.total_space
* 100. *
11479 vty_out(vty
, "%30s: %s\n",
11483 json_object_double_add(json
,
11485 (double)(ts
.total_space
*
11489 snprintf(temp_buf
, sizeof(temp_buf
),
11492 pow(2.0, -32 + 8));
11493 vty_out(vty
, "%30s: %s\n",
11494 "/8 equivalent ", temp_buf
);
11496 json_object_double_add(json
,
11498 (double)(ts
.total_space
*
11499 pow(2.0, -32 + 8)));
11501 snprintf(temp_buf
, sizeof(temp_buf
),
11504 pow(2.0, -32 + 24));
11505 vty_out(vty
, "%30s: %s\n",
11509 json_object_double_add(json
,
11511 (double)(ts
.total_space
*
11512 pow(2.0, -32 + 24)));
11517 snprintf(temp_buf
, sizeof(temp_buf
), "%12llu",
11519 vty_out(vty
, "%-30s: %s",
11520 table_stats_strs
[i
][TABLE_STATS_IDX_VTY
],
11523 json_object_int_add(json
,
11524 table_stats_strs
[i
][TABLE_STATS_IDX_JSON
],
11528 vty_out(vty
, "\n");
11532 json_object_array_add(json_array
, json
);
11545 PCOUNT_PFCNT
, /* the figure we display to users */
11549 static const char *const pcount_strs
[] = {
11550 [PCOUNT_ADJ_IN
] = "Adj-in",
11551 [PCOUNT_DAMPED
] = "Damped",
11552 [PCOUNT_REMOVED
] = "Removed",
11553 [PCOUNT_HISTORY
] = "History",
11554 [PCOUNT_STALE
] = "Stale",
11555 [PCOUNT_VALID
] = "Valid",
11556 [PCOUNT_ALL
] = "All RIB",
11557 [PCOUNT_COUNTED
] = "PfxCt counted",
11558 [PCOUNT_PFCNT
] = "Useable",
11559 [PCOUNT_MAX
] = NULL
,
11562 struct peer_pcounts
{
11563 unsigned int count
[PCOUNT_MAX
];
11564 const struct peer
*peer
;
11565 const struct bgp_table
*table
;
11569 static void bgp_peer_count_proc(struct bgp_node
*rn
,
11570 struct peer_pcounts
*pc
)
11572 const struct bgp_adj_in
*ain
;
11573 const struct bgp_path_info
*pi
;
11574 const struct peer
*peer
= pc
->peer
;
11576 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11577 if (ain
->peer
== peer
)
11578 pc
->count
[PCOUNT_ADJ_IN
]++;
11580 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11582 if (pi
->peer
!= peer
)
11585 pc
->count
[PCOUNT_ALL
]++;
11587 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11588 pc
->count
[PCOUNT_DAMPED
]++;
11589 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11590 pc
->count
[PCOUNT_HISTORY
]++;
11591 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11592 pc
->count
[PCOUNT_REMOVED
]++;
11593 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11594 pc
->count
[PCOUNT_STALE
]++;
11595 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11596 pc
->count
[PCOUNT_VALID
]++;
11597 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11598 pc
->count
[PCOUNT_PFCNT
]++;
11600 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11601 pc
->count
[PCOUNT_COUNTED
]++;
11602 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11604 EC_LIB_DEVELOPMENT
,
11605 "Attempting to count but flags say it is unusable");
11607 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11609 EC_LIB_DEVELOPMENT
,
11610 "Not counted but flags say we should");
11615 static int bgp_peer_count_walker(struct thread
*t
)
11617 struct bgp_node
*rn
, *rm
;
11618 const struct bgp_table
*table
;
11619 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11621 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11622 || pc
->safi
== SAFI_EVPN
) {
11623 /* Special handling for 2-level routing tables. */
11624 for (rn
= bgp_table_top(pc
->table
); rn
;
11625 rn
= bgp_route_next(rn
)) {
11626 table
= bgp_node_get_bgp_table_info(rn
);
11628 for (rm
= bgp_table_top(table
); rm
;
11629 rm
= bgp_route_next(rm
))
11630 bgp_peer_count_proc(rm
, pc
);
11633 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11634 bgp_peer_count_proc(rn
, pc
);
11639 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11640 safi_t safi
, bool use_json
)
11642 struct peer_pcounts pcounts
= {.peer
= peer
};
11644 json_object
*json
= NULL
;
11645 json_object
*json_loop
= NULL
;
11648 json
= json_object_new_object();
11649 json_loop
= json_object_new_object();
11652 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11653 || !peer
->bgp
->rib
[afi
][safi
]) {
11655 json_object_string_add(
11657 "No such neighbor or address family");
11658 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11659 json_object_free(json
);
11661 vty_out(vty
, "%% No such neighbor or address family\n");
11663 return CMD_WARNING
;
11666 memset(&pcounts
, 0, sizeof(pcounts
));
11667 pcounts
.peer
= peer
;
11668 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11669 pcounts
.safi
= safi
;
11671 /* in-place call via thread subsystem so as to record execution time
11672 * stats for the thread-walk (i.e. ensure this can't be blamed on
11673 * on just vty_read()).
11675 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11678 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11679 json_object_string_add(json
, "multiProtocol",
11680 get_afi_safi_str(afi
, safi
, true));
11681 json_object_int_add(json
, "pfxCounter",
11682 peer
->pcount
[afi
][safi
]);
11684 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11685 json_object_int_add(json_loop
, pcount_strs
[i
],
11688 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11690 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11691 json_object_string_add(json
, "pfxctDriftFor",
11693 json_object_string_add(
11694 json
, "recommended",
11695 "Please report this bug, with the above command output");
11697 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11698 json
, JSON_C_TO_STRING_PRETTY
));
11699 json_object_free(json
);
11703 && CHECK_FLAG(peer
->bgp
->flags
, BGP_FLAG_SHOW_HOSTNAME
)) {
11704 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11705 peer
->hostname
, peer
->host
,
11706 get_afi_safi_str(afi
, safi
, false));
11708 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11709 get_afi_safi_str(afi
, safi
, false));
11712 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11713 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11715 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11716 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11719 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11720 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11722 "Please report this bug, with the above command output\n");
11726 return CMD_SUCCESS
;
11729 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11730 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11731 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11732 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11736 BGP_INSTANCE_HELP_STR
11739 "Detailed information on TCP and BGP neighbor connections\n"
11740 "Neighbor to display information about\n"
11741 "Neighbor to display information about\n"
11742 "Neighbor on BGP configured interface\n"
11743 "Display detailed prefix count information\n"
11746 afi_t afi
= AFI_IP6
;
11747 safi_t safi
= SAFI_UNICAST
;
11750 struct bgp
*bgp
= NULL
;
11751 bool uj
= use_json(argc
, argv
);
11756 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11759 return CMD_WARNING
;
11761 argv_find(argv
, argc
, "neighbors", &idx
);
11762 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11764 return CMD_WARNING
;
11766 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11769 #ifdef KEEP_OLD_VPN_COMMANDS
11770 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11771 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11772 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11777 "Display information about all VPNv4 NLRIs\n"
11778 "Detailed information on TCP and BGP neighbor connections\n"
11779 "Neighbor to display information about\n"
11780 "Neighbor to display information about\n"
11781 "Neighbor on BGP configured interface\n"
11782 "Display detailed prefix count information\n"
11787 bool uj
= use_json(argc
, argv
);
11789 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11791 return CMD_WARNING
;
11793 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11796 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11797 show_ip_bgp_vpn_all_route_prefix_cmd
,
11798 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11803 "Display information about all VPNv4 NLRIs\n"
11804 "Network in the BGP routing table to display\n"
11805 "Network in the BGP routing table to display\n"
11809 char *network
= NULL
;
11810 struct bgp
*bgp
= bgp_get_default();
11812 vty_out(vty
, "Can't find default instance\n");
11813 return CMD_WARNING
;
11816 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11817 network
= argv
[idx
]->arg
;
11818 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11819 network
= argv
[idx
]->arg
;
11821 vty_out(vty
, "Unable to figure out Network\n");
11822 return CMD_WARNING
;
11825 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11826 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11828 #endif /* KEEP_OLD_VPN_COMMANDS */
11830 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11831 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11832 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11837 "Network in the BGP routing table to display\n"
11838 "Network in the BGP routing table to display\n"
11839 "Network in the BGP routing table to display\n"
11840 "Network in the BGP routing table to display\n"
11844 char *network
= NULL
;
11845 int prefix_check
= 0;
11847 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11848 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11849 network
= argv
[idx
]->arg
;
11850 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11851 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11852 network
= argv
[idx
]->arg
;
11855 vty_out(vty
, "Unable to figure out Network\n");
11856 return CMD_WARNING
;
11858 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11859 prefix_check
, BGP_PATH_SHOW_ALL
,
11860 use_json(argc
, argv
));
11863 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11864 safi_t safi
, enum bgp_show_adj_route_type type
,
11865 const char *rmap_name
, bool use_json
,
11868 struct bgp_table
*table
;
11869 struct bgp_adj_in
*ain
;
11870 struct bgp_adj_out
*adj
;
11871 unsigned long output_count
;
11872 unsigned long filtered_count
;
11873 struct bgp_node
*rn
;
11879 struct update_subgroup
*subgrp
;
11880 json_object
*json_scode
= NULL
;
11881 json_object
*json_ocode
= NULL
;
11882 json_object
*json_ar
= NULL
;
11883 struct peer_af
*paf
;
11884 bool route_filtered
;
11887 json_scode
= json_object_new_object();
11888 json_ocode
= json_object_new_object();
11889 json_ar
= json_object_new_object();
11891 json_object_string_add(json_scode
, "suppressed", "s");
11892 json_object_string_add(json_scode
, "damped", "d");
11893 json_object_string_add(json_scode
, "history", "h");
11894 json_object_string_add(json_scode
, "valid", "*");
11895 json_object_string_add(json_scode
, "best", ">");
11896 json_object_string_add(json_scode
, "multipath", "=");
11897 json_object_string_add(json_scode
, "internal", "i");
11898 json_object_string_add(json_scode
, "ribFailure", "r");
11899 json_object_string_add(json_scode
, "stale", "S");
11900 json_object_string_add(json_scode
, "removed", "R");
11902 json_object_string_add(json_ocode
, "igp", "i");
11903 json_object_string_add(json_ocode
, "egp", "e");
11904 json_object_string_add(json_ocode
, "incomplete", "?");
11911 json_object_string_add(json
, "alert", "no BGP");
11912 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11913 json_object_free(json
);
11915 vty_out(vty
, "%% No bgp\n");
11919 /* labeled-unicast routes live in the unicast table */
11920 if (safi
== SAFI_LABELED_UNICAST
)
11921 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11923 table
= bgp
->rib
[afi
][safi
];
11925 output_count
= filtered_count
= 0;
11926 subgrp
= peer_subgroup(peer
, afi
, safi
);
11928 if (type
== bgp_show_adj_route_advertised
&& subgrp
11929 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11931 json_object_int_add(json
, "bgpTableVersion",
11933 json_object_string_add(json
, "bgpLocalRouterId",
11934 inet_ntoa(bgp
->router_id
));
11935 json_object_int_add(json
, "defaultLocPrf",
11936 bgp
->default_local_pref
);
11937 json_object_int_add(json
, "localAS", bgp
->as
);
11938 json_object_object_add(json
, "bgpStatusCodes",
11940 json_object_object_add(json
, "bgpOriginCodes",
11942 json_object_string_add(
11943 json
, "bgpOriginatingDefaultNetwork",
11944 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11946 vty_out(vty
, "BGP table version is %" PRIu64
11947 ", local router ID is %s, vrf id ",
11948 table
->version
, inet_ntoa(bgp
->router_id
));
11949 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11950 vty_out(vty
, "%s", VRFID_NONE_STR
);
11952 vty_out(vty
, "%u", bgp
->vrf_id
);
11953 vty_out(vty
, "\n");
11954 vty_out(vty
, "Default local pref %u, ",
11955 bgp
->default_local_pref
);
11956 vty_out(vty
, "local AS %u\n", bgp
->as
);
11957 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11958 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11959 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11961 vty_out(vty
, "Originating default network %s\n\n",
11962 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11967 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11968 if (type
== bgp_show_adj_route_received
11969 || type
== bgp_show_adj_route_filtered
) {
11970 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11971 if (ain
->peer
!= peer
)
11976 json_object_int_add(
11977 json
, "bgpTableVersion",
11979 json_object_string_add(
11981 "bgpLocalRouterId",
11984 json_object_int_add(json
,
11986 bgp
->default_local_pref
);
11987 json_object_int_add(json
,
11988 "localAS", bgp
->as
);
11989 json_object_object_add(
11990 json
, "bgpStatusCodes",
11992 json_object_object_add(
11993 json
, "bgpOriginCodes",
11997 "BGP table version is 0, local router ID is %s, vrf id ",
12000 if (bgp
->vrf_id
== VRF_UNKNOWN
)
12006 vty_out(vty
, "\n");
12008 "Default local pref %u, ",
12009 bgp
->default_local_pref
);
12010 vty_out(vty
, "local AS %u\n",
12013 BGP_SHOW_SCODE_HEADER
);
12015 BGP_SHOW_NCODE_HEADER
);
12017 BGP_SHOW_OCODE_HEADER
);
12023 vty_out(vty
, BGP_SHOW_HEADER
);
12028 route_filtered
= false;
12030 /* Filter prefix using distribute list,
12031 * filter list or prefix list
12033 const struct prefix
*rn_p
=
12034 bgp_node_get_prefix(rn
);
12035 if ((bgp_input_filter(peer
, rn_p
, &attr
, afi
,
12038 route_filtered
= true;
12040 /* Filter prefix using route-map */
12041 ret
= bgp_input_modifier(peer
, rn_p
, &attr
, afi
,
12042 safi
, rmap_name
, NULL
,
12045 if (type
== bgp_show_adj_route_filtered
&&
12046 !route_filtered
&& ret
!= RMAP_DENY
) {
12047 bgp_attr_undup(&attr
, ain
->attr
);
12051 if (type
== bgp_show_adj_route_received
&&
12052 (route_filtered
|| ret
== RMAP_DENY
))
12055 route_vty_out_tmp(vty
, rn_p
, &attr
, safi
,
12056 use_json
, json_ar
);
12057 bgp_attr_undup(&attr
, ain
->attr
);
12060 } else if (type
== bgp_show_adj_route_advertised
) {
12061 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
12062 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
12063 if (paf
->peer
!= peer
|| !adj
->attr
)
12068 json_object_int_add(
12072 json_object_string_add(
12074 "bgpLocalRouterId",
12077 json_object_int_add(
12078 json
, "defaultLocPrf",
12079 bgp
->default_local_pref
12081 json_object_int_add(
12084 json_object_object_add(
12088 json_object_object_add(
12094 "BGP table version is %" PRIu64
12095 ", local router ID is %s, vrf id ",
12108 vty_out(vty
, "\n");
12110 "Default local pref %u, ",
12111 bgp
->default_local_pref
12117 BGP_SHOW_SCODE_HEADER
);
12119 BGP_SHOW_NCODE_HEADER
);
12121 BGP_SHOW_OCODE_HEADER
);
12132 const struct prefix
*rn_p
=
12133 bgp_node_get_prefix(rn
);
12136 ret
= bgp_output_modifier(
12137 peer
, rn_p
, &attr
, afi
, safi
,
12140 if (ret
!= RMAP_DENY
) {
12142 vty
, rn_p
, &attr
, safi
,
12143 use_json
, json_ar
);
12149 bgp_attr_undup(&attr
, adj
->attr
);
12155 json_object_object_add(json
, "advertisedRoutes", json_ar
);
12156 json_object_int_add(json
, "totalPrefixCounter", output_count
);
12157 json_object_int_add(json
, "filteredPrefixCounter",
12160 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
12161 json
, JSON_C_TO_STRING_PRETTY
));
12162 json_object_free(json
);
12163 } else if (output_count
> 0) {
12164 if (filtered_count
> 0)
12166 "\nTotal number of prefixes %ld (%ld filtered)\n",
12167 output_count
, filtered_count
);
12169 vty_out(vty
, "\nTotal number of prefixes %ld\n",
12174 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
12175 safi_t safi
, enum bgp_show_adj_route_type type
,
12176 const char *rmap_name
, bool use_json
)
12178 json_object
*json
= NULL
;
12181 json
= json_object_new_object();
12183 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12185 json_object_string_add(
12187 "No such neighbor or address family");
12188 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12189 json_object_free(json
);
12191 vty_out(vty
, "%% No such neighbor or address family\n");
12193 return CMD_WARNING
;
12196 if ((type
== bgp_show_adj_route_received
12197 || type
== bgp_show_adj_route_filtered
)
12198 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
12199 PEER_FLAG_SOFT_RECONFIG
)) {
12201 json_object_string_add(
12203 "Inbound soft reconfiguration not enabled");
12204 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
12205 json_object_free(json
);
12208 "%% Inbound soft reconfiguration not enabled\n");
12210 return CMD_WARNING
;
12213 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
12215 return CMD_SUCCESS
;
12218 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
12219 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
12220 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12221 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
12225 BGP_INSTANCE_HELP_STR
12227 BGP_SAFI_WITH_LABEL_HELP_STR
12228 "Detailed information on TCP and BGP neighbor connections\n"
12229 "Neighbor to display information about\n"
12230 "Neighbor to display information about\n"
12231 "Neighbor on BGP configured interface\n"
12232 "Display the routes advertised to a BGP neighbor\n"
12233 "Display the received routes from neighbor\n"
12234 "Display the filtered routes received from neighbor\n"
12235 "Route-map to modify the attributes\n"
12236 "Name of the route map\n"
12239 afi_t afi
= AFI_IP6
;
12240 safi_t safi
= SAFI_UNICAST
;
12241 char *rmap_name
= NULL
;
12242 char *peerstr
= NULL
;
12243 struct bgp
*bgp
= NULL
;
12245 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
12247 bool uj
= use_json(argc
, argv
);
12252 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12255 return CMD_WARNING
;
12257 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12258 argv_find(argv
, argc
, "neighbors", &idx
);
12259 peerstr
= argv
[++idx
]->arg
;
12261 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12263 return CMD_WARNING
;
12265 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
12266 type
= bgp_show_adj_route_advertised
;
12267 else if (argv_find(argv
, argc
, "received-routes", &idx
))
12268 type
= bgp_show_adj_route_received
;
12269 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
12270 type
= bgp_show_adj_route_filtered
;
12272 if (argv_find(argv
, argc
, "route-map", &idx
))
12273 rmap_name
= argv
[++idx
]->arg
;
12275 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
12278 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
12279 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
12280 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
12286 "Address Family modifier\n"
12287 "Detailed information on TCP and BGP neighbor connections\n"
12288 "Neighbor to display information about\n"
12289 "Neighbor to display information about\n"
12290 "Neighbor on BGP configured interface\n"
12291 "Display information received from a BGP neighbor\n"
12292 "Display the prefixlist filter\n"
12295 afi_t afi
= AFI_IP6
;
12296 safi_t safi
= SAFI_UNICAST
;
12297 char *peerstr
= NULL
;
12300 union sockunion su
;
12306 /* show [ip] bgp */
12307 if (argv_find(argv
, argc
, "ip", &idx
))
12309 /* [<ipv4|ipv6> [unicast]] */
12310 if (argv_find(argv
, argc
, "ipv4", &idx
))
12312 if (argv_find(argv
, argc
, "ipv6", &idx
))
12314 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12315 argv_find(argv
, argc
, "neighbors", &idx
);
12316 peerstr
= argv
[++idx
]->arg
;
12318 bool uj
= use_json(argc
, argv
);
12320 ret
= str2sockunion(peerstr
, &su
);
12322 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
12325 vty_out(vty
, "{}\n");
12328 "%% Malformed address or name: %s\n",
12330 return CMD_WARNING
;
12333 peer
= peer_lookup(NULL
, &su
);
12336 vty_out(vty
, "{}\n");
12338 vty_out(vty
, "No peer\n");
12339 return CMD_WARNING
;
12343 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
12344 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
12347 vty_out(vty
, "Address Family: %s\n",
12348 get_afi_safi_str(afi
, safi
, false));
12349 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
12352 vty_out(vty
, "{}\n");
12354 vty_out(vty
, "No functional output\n");
12357 return CMD_SUCCESS
;
12360 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
12361 afi_t afi
, safi_t safi
,
12362 enum bgp_show_type type
, bool use_json
)
12364 /* labeled-unicast routes live in the unicast table */
12365 if (safi
== SAFI_LABELED_UNICAST
)
12366 safi
= SAFI_UNICAST
;
12368 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12370 json_object
*json_no
= NULL
;
12371 json_no
= json_object_new_object();
12372 json_object_string_add(
12373 json_no
, "warning",
12374 "No such neighbor or address family");
12375 vty_out(vty
, "%s\n",
12376 json_object_to_json_string(json_no
));
12377 json_object_free(json_no
);
12379 vty_out(vty
, "%% No such neighbor or address family\n");
12380 return CMD_WARNING
;
12383 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
12386 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12387 show_ip_bgp_flowspec_routes_detailed_cmd
,
12388 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12392 BGP_INSTANCE_HELP_STR
12395 "Detailed information on flowspec entries\n"
12398 afi_t afi
= AFI_IP
;
12399 safi_t safi
= SAFI_UNICAST
;
12400 struct bgp
*bgp
= NULL
;
12402 bool uj
= use_json(argc
, argv
);
12407 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12410 return CMD_WARNING
;
12412 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
12415 DEFUN (show_ip_bgp_neighbor_routes
,
12416 show_ip_bgp_neighbor_routes_cmd
,
12417 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12418 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
12422 BGP_INSTANCE_HELP_STR
12424 BGP_SAFI_WITH_LABEL_HELP_STR
12425 "Detailed information on TCP and BGP neighbor connections\n"
12426 "Neighbor to display information about\n"
12427 "Neighbor to display information about\n"
12428 "Neighbor on BGP configured interface\n"
12429 "Display flap statistics of the routes learned from neighbor\n"
12430 "Display the dampened routes received from neighbor\n"
12431 "Display routes learned from neighbor\n"
12434 char *peerstr
= NULL
;
12435 struct bgp
*bgp
= NULL
;
12436 afi_t afi
= AFI_IP6
;
12437 safi_t safi
= SAFI_UNICAST
;
12439 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12441 bool uj
= use_json(argc
, argv
);
12446 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12449 return CMD_WARNING
;
12451 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12452 argv_find(argv
, argc
, "neighbors", &idx
);
12453 peerstr
= argv
[++idx
]->arg
;
12455 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12457 return CMD_WARNING
;
12459 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12460 sh_type
= bgp_show_type_flap_neighbor
;
12461 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12462 sh_type
= bgp_show_type_damp_neighbor
;
12463 else if (argv_find(argv
, argc
, "routes", &idx
))
12464 sh_type
= bgp_show_type_neighbor
;
12466 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12469 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12471 struct bgp_distance
{
12472 /* Distance value for the IP source prefix. */
12475 /* Name of the access-list to be matched. */
12479 DEFUN (show_bgp_afi_vpn_rd_route
,
12480 show_bgp_afi_vpn_rd_route_cmd
,
12481 "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]",
12485 "Address Family modifier\n"
12486 "Display information for a route distinguisher\n"
12487 "Route Distinguisher\n"
12488 "Network in the BGP routing table to display\n"
12489 "Network in the BGP routing table to display\n"
12493 struct prefix_rd prd
;
12494 afi_t afi
= AFI_MAX
;
12497 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12498 vty_out(vty
, "%% Malformed Address Family\n");
12499 return CMD_WARNING
;
12502 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12504 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12505 return CMD_WARNING
;
12508 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12509 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12512 static struct bgp_distance
*bgp_distance_new(void)
12514 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12517 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12519 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12522 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12523 const char *ip_str
, const char *access_list_str
)
12530 struct bgp_node
*rn
;
12531 struct bgp_distance
*bdistance
;
12533 afi
= bgp_node_afi(vty
);
12534 safi
= bgp_node_safi(vty
);
12536 ret
= str2prefix(ip_str
, &p
);
12538 vty_out(vty
, "Malformed prefix\n");
12539 return CMD_WARNING_CONFIG_FAILED
;
12542 distance
= atoi(distance_str
);
12544 /* Get BGP distance node. */
12545 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
12546 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12548 bgp_unlock_node(rn
);
12550 bdistance
= bgp_distance_new();
12551 bgp_node_set_bgp_distance_info(rn
, bdistance
);
12554 /* Set distance value. */
12555 bdistance
->distance
= distance
;
12557 /* Reset access-list configuration. */
12558 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12559 if (access_list_str
)
12560 bdistance
->access_list
=
12561 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12563 return CMD_SUCCESS
;
12566 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12567 const char *ip_str
, const char *access_list_str
)
12574 struct bgp_node
*rn
;
12575 struct bgp_distance
*bdistance
;
12577 afi
= bgp_node_afi(vty
);
12578 safi
= bgp_node_safi(vty
);
12580 ret
= str2prefix(ip_str
, &p
);
12582 vty_out(vty
, "Malformed prefix\n");
12583 return CMD_WARNING_CONFIG_FAILED
;
12586 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
12587 (struct prefix
*)&p
);
12589 vty_out(vty
, "Can't find specified prefix\n");
12590 return CMD_WARNING_CONFIG_FAILED
;
12593 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12594 distance
= atoi(distance_str
);
12596 if (bdistance
->distance
!= distance
) {
12597 vty_out(vty
, "Distance does not match configured\n");
12598 return CMD_WARNING_CONFIG_FAILED
;
12601 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12602 bgp_distance_free(bdistance
);
12604 bgp_node_set_bgp_path_info(rn
, NULL
);
12605 bgp_unlock_node(rn
);
12606 bgp_unlock_node(rn
);
12608 return CMD_SUCCESS
;
12611 /* Apply BGP information to distance method. */
12612 uint8_t bgp_distance_apply(const struct prefix
*p
, struct bgp_path_info
*pinfo
,
12613 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12615 struct bgp_node
*rn
;
12618 struct bgp_distance
*bdistance
;
12619 struct access_list
*alist
;
12620 struct bgp_static
*bgp_static
;
12625 peer
= pinfo
->peer
;
12627 if (pinfo
->attr
->distance
)
12628 return pinfo
->attr
->distance
;
12630 /* Check source address. */
12631 sockunion2hostprefix(&peer
->su
, &q
);
12632 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12634 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12635 bgp_unlock_node(rn
);
12637 if (bdistance
->access_list
) {
12638 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12640 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12641 return bdistance
->distance
;
12643 return bdistance
->distance
;
12646 /* Backdoor check. */
12647 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12649 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12650 bgp_unlock_node(rn
);
12652 if (bgp_static
->backdoor
) {
12653 if (bgp
->distance_local
[afi
][safi
])
12654 return bgp
->distance_local
[afi
][safi
];
12656 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12660 if (peer
->sort
== BGP_PEER_EBGP
) {
12661 if (bgp
->distance_ebgp
[afi
][safi
])
12662 return bgp
->distance_ebgp
[afi
][safi
];
12663 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12665 if (bgp
->distance_ibgp
[afi
][safi
])
12666 return bgp
->distance_ibgp
[afi
][safi
];
12667 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12671 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12672 * we should tell ZEBRA update the routes for a specific
12673 * AFI/SAFI to reflect changes in RIB.
12675 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12677 safi_t update_safi
)
12682 FOREACH_AFI_SAFI (afi
, safi
) {
12683 if (!bgp_fibupd_safi(safi
))
12686 if (afi
!= update_afi
&& safi
!= update_safi
)
12689 if (BGP_DEBUG(zebra
, ZEBRA
))
12691 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12692 __func__
, afi
, safi
);
12693 bgp_zebra_announce_table(bgp
, afi
, safi
);
12697 DEFUN (bgp_distance
,
12699 "distance bgp (1-255) (1-255) (1-255)",
12700 "Define an administrative distance\n"
12702 "Distance for routes external to the AS\n"
12703 "Distance for routes internal to the AS\n"
12704 "Distance for local routes\n")
12706 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12707 int idx_number
= 2;
12708 int idx_number_2
= 3;
12709 int idx_number_3
= 4;
12710 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12711 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12712 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12716 afi
= bgp_node_afi(vty
);
12717 safi
= bgp_node_safi(vty
);
12719 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12720 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12721 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12722 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12723 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12724 bgp
->distance_local
[afi
][safi
] = distance_local
;
12725 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12727 return CMD_SUCCESS
;
12730 DEFUN (no_bgp_distance
,
12731 no_bgp_distance_cmd
,
12732 "no distance bgp [(1-255) (1-255) (1-255)]",
12734 "Define an administrative distance\n"
12736 "Distance for routes external to the AS\n"
12737 "Distance for routes internal to the AS\n"
12738 "Distance for local routes\n")
12740 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12744 afi
= bgp_node_afi(vty
);
12745 safi
= bgp_node_safi(vty
);
12747 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12748 || bgp
->distance_ibgp
[afi
][safi
] != 0
12749 || bgp
->distance_local
[afi
][safi
] != 0) {
12750 bgp
->distance_ebgp
[afi
][safi
] = 0;
12751 bgp
->distance_ibgp
[afi
][safi
] = 0;
12752 bgp
->distance_local
[afi
][safi
] = 0;
12753 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12755 return CMD_SUCCESS
;
12759 DEFUN (bgp_distance_source
,
12760 bgp_distance_source_cmd
,
12761 "distance (1-255) A.B.C.D/M",
12762 "Define an administrative distance\n"
12763 "Administrative distance\n"
12764 "IP source prefix\n")
12766 int idx_number
= 1;
12767 int idx_ipv4_prefixlen
= 2;
12768 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12769 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12770 return CMD_SUCCESS
;
12773 DEFUN (no_bgp_distance_source
,
12774 no_bgp_distance_source_cmd
,
12775 "no distance (1-255) A.B.C.D/M",
12777 "Define an administrative distance\n"
12778 "Administrative distance\n"
12779 "IP source prefix\n")
12781 int idx_number
= 2;
12782 int idx_ipv4_prefixlen
= 3;
12783 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12784 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12785 return CMD_SUCCESS
;
12788 DEFUN (bgp_distance_source_access_list
,
12789 bgp_distance_source_access_list_cmd
,
12790 "distance (1-255) A.B.C.D/M WORD",
12791 "Define an administrative distance\n"
12792 "Administrative distance\n"
12793 "IP source prefix\n"
12794 "Access list name\n")
12796 int idx_number
= 1;
12797 int idx_ipv4_prefixlen
= 2;
12799 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12800 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12801 return CMD_SUCCESS
;
12804 DEFUN (no_bgp_distance_source_access_list
,
12805 no_bgp_distance_source_access_list_cmd
,
12806 "no distance (1-255) A.B.C.D/M WORD",
12808 "Define an administrative distance\n"
12809 "Administrative distance\n"
12810 "IP source prefix\n"
12811 "Access list name\n")
12813 int idx_number
= 2;
12814 int idx_ipv4_prefixlen
= 3;
12816 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12817 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12818 return CMD_SUCCESS
;
12821 DEFUN (ipv6_bgp_distance_source
,
12822 ipv6_bgp_distance_source_cmd
,
12823 "distance (1-255) X:X::X:X/M",
12824 "Define an administrative distance\n"
12825 "Administrative distance\n"
12826 "IP source prefix\n")
12828 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12829 return CMD_SUCCESS
;
12832 DEFUN (no_ipv6_bgp_distance_source
,
12833 no_ipv6_bgp_distance_source_cmd
,
12834 "no distance (1-255) X:X::X:X/M",
12836 "Define an administrative distance\n"
12837 "Administrative distance\n"
12838 "IP source prefix\n")
12840 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12841 return CMD_SUCCESS
;
12844 DEFUN (ipv6_bgp_distance_source_access_list
,
12845 ipv6_bgp_distance_source_access_list_cmd
,
12846 "distance (1-255) X:X::X:X/M WORD",
12847 "Define an administrative distance\n"
12848 "Administrative distance\n"
12849 "IP source prefix\n"
12850 "Access list name\n")
12852 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12853 return CMD_SUCCESS
;
12856 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12857 no_ipv6_bgp_distance_source_access_list_cmd
,
12858 "no distance (1-255) X:X::X:X/M WORD",
12860 "Define an administrative distance\n"
12861 "Administrative distance\n"
12862 "IP source prefix\n"
12863 "Access list name\n")
12865 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12866 return CMD_SUCCESS
;
12869 DEFUN (bgp_damp_set
,
12871 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12872 "BGP Specific commands\n"
12873 "Enable route-flap dampening\n"
12874 "Half-life time for the penalty\n"
12875 "Value to start reusing a route\n"
12876 "Value to start suppressing a route\n"
12877 "Maximum duration to suppress a stable route\n")
12879 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12880 int idx_half_life
= 2;
12882 int idx_suppress
= 4;
12883 int idx_max_suppress
= 5;
12884 int half
= DEFAULT_HALF_LIFE
* 60;
12885 int reuse
= DEFAULT_REUSE
;
12886 int suppress
= DEFAULT_SUPPRESS
;
12887 int max
= 4 * half
;
12890 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12891 reuse
= atoi(argv
[idx_reuse
]->arg
);
12892 suppress
= atoi(argv
[idx_suppress
]->arg
);
12893 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12894 } else if (argc
== 3) {
12895 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12900 * These can't be 0 but our SA doesn't understand the
12901 * way our cli is constructed
12905 if (suppress
< reuse
) {
12907 "Suppress value cannot be less than reuse value \n");
12911 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12912 reuse
, suppress
, max
);
12915 DEFUN (bgp_damp_unset
,
12916 bgp_damp_unset_cmd
,
12917 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12919 "BGP Specific commands\n"
12920 "Enable route-flap dampening\n"
12921 "Half-life time for the penalty\n"
12922 "Value to start reusing a route\n"
12923 "Value to start suppressing a route\n"
12924 "Maximum duration to suppress a stable route\n")
12926 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12927 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12930 /* Display specified route of BGP table. */
12931 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12932 const char *ip_str
, afi_t afi
, safi_t safi
,
12933 struct prefix_rd
*prd
, int prefix_check
)
12936 struct prefix match
;
12937 struct bgp_node
*rn
;
12938 struct bgp_node
*rm
;
12939 struct bgp_path_info
*pi
;
12940 struct bgp_path_info
*pi_temp
;
12942 struct bgp_table
*table
;
12944 /* BGP structure lookup. */
12946 bgp
= bgp_lookup_by_name(view_name
);
12948 vty_out(vty
, "%% Can't find BGP instance %s\n",
12950 return CMD_WARNING
;
12953 bgp
= bgp_get_default();
12955 vty_out(vty
, "%% No BGP process is configured\n");
12956 return CMD_WARNING
;
12960 /* Check IP address argument. */
12961 ret
= str2prefix(ip_str
, &match
);
12963 vty_out(vty
, "%% address is malformed\n");
12964 return CMD_WARNING
;
12967 match
.family
= afi2family(afi
);
12969 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12970 || (safi
== SAFI_EVPN
)) {
12971 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12972 rn
= bgp_route_next(rn
)) {
12973 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
12975 if (prd
&& memcmp(rn_p
->u
.val
, prd
->val
, 8) != 0)
12977 table
= bgp_node_get_bgp_table_info(rn
);
12980 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12983 const struct prefix
*rm_p
= bgp_node_get_prefix(rn
);
12986 || rm_p
->prefixlen
== match
.prefixlen
) {
12987 pi
= bgp_node_get_bgp_path_info(rm
);
12989 if (pi
->extra
&& pi
->extra
->damp_info
) {
12990 pi_temp
= pi
->next
;
12991 bgp_damp_info_free(
12992 pi
->extra
->damp_info
,
13000 bgp_unlock_node(rm
);
13003 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
13005 const struct prefix
*rn_p
= bgp_node_get_prefix(rn
);
13008 || rn_p
->prefixlen
== match
.prefixlen
) {
13009 pi
= bgp_node_get_bgp_path_info(rn
);
13011 if (pi
->extra
&& pi
->extra
->damp_info
) {
13012 pi_temp
= pi
->next
;
13013 bgp_damp_info_free(
13014 pi
->extra
->damp_info
,
13022 bgp_unlock_node(rn
);
13026 return CMD_SUCCESS
;
13029 DEFUN (clear_ip_bgp_dampening
,
13030 clear_ip_bgp_dampening_cmd
,
13031 "clear ip bgp dampening",
13035 "Clear route flap dampening information\n")
13037 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
13038 return CMD_SUCCESS
;
13041 DEFUN (clear_ip_bgp_dampening_prefix
,
13042 clear_ip_bgp_dampening_prefix_cmd
,
13043 "clear ip bgp dampening A.B.C.D/M",
13047 "Clear route flap dampening information\n"
13050 int idx_ipv4_prefixlen
= 4;
13051 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
13052 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
13055 DEFUN (clear_ip_bgp_dampening_address
,
13056 clear_ip_bgp_dampening_address_cmd
,
13057 "clear ip bgp dampening A.B.C.D",
13061 "Clear route flap dampening information\n"
13062 "Network to clear damping information\n")
13065 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
13066 SAFI_UNICAST
, NULL
, 0);
13069 DEFUN (clear_ip_bgp_dampening_address_mask
,
13070 clear_ip_bgp_dampening_address_mask_cmd
,
13071 "clear ip bgp dampening A.B.C.D A.B.C.D",
13075 "Clear route flap dampening information\n"
13076 "Network to clear damping information\n"
13080 int idx_ipv4_2
= 5;
13082 char prefix_str
[BUFSIZ
];
13084 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
13087 vty_out(vty
, "%% Inconsistent address and mask\n");
13088 return CMD_WARNING
;
13091 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
13095 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
13097 struct vty
*vty
= arg
;
13098 struct peer
*peer
= bucket
->data
;
13099 char buf
[SU_ADDRSTRLEN
];
13101 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
13102 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
13105 DEFUN (show_bgp_listeners
,
13106 show_bgp_listeners_cmd
,
13107 "show bgp listeners",
13110 "Display Listen Sockets and who created them\n")
13112 bgp_dump_listener_info(vty
);
13114 return CMD_SUCCESS
;
13117 DEFUN (show_bgp_peerhash
,
13118 show_bgp_peerhash_cmd
,
13119 "show bgp peerhash",
13122 "Display information about the BGP peerhash\n")
13124 struct list
*instances
= bm
->bgp
;
13125 struct listnode
*node
;
13128 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
13129 vty_out(vty
, "BGP: %s\n", bgp
->name
);
13130 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
13134 return CMD_SUCCESS
;
13137 /* also used for encap safi */
13138 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
13139 afi_t afi
, safi_t safi
)
13141 struct bgp_node
*prn
;
13142 struct bgp_node
*rn
;
13143 struct bgp_table
*table
;
13144 const struct prefix
*p
;
13145 const struct prefix_rd
*prd
;
13146 struct bgp_static
*bgp_static
;
13147 mpls_label_t label
;
13148 char buf
[SU_ADDRSTRLEN
];
13149 char rdbuf
[RD_ADDRSTRLEN
];
13151 /* Network configuration. */
13152 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
13153 prn
= bgp_route_next(prn
)) {
13154 table
= bgp_node_get_bgp_table_info(prn
);
13158 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
13159 bgp_static
= bgp_node_get_bgp_static_info(rn
);
13160 if (bgp_static
== NULL
)
13163 p
= bgp_node_get_prefix(rn
);
13164 prd
= (const struct prefix_rd
*)bgp_node_get_prefix(
13167 /* "network" configuration display. */
13168 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13169 label
= decode_label(&bgp_static
->label
);
13171 vty_out(vty
, " network %s/%d rd %s",
13172 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
13174 p
->prefixlen
, rdbuf
);
13175 if (safi
== SAFI_MPLS_VPN
)
13176 vty_out(vty
, " label %u", label
);
13178 if (bgp_static
->rmap
.name
)
13179 vty_out(vty
, " route-map %s",
13180 bgp_static
->rmap
.name
);
13182 if (bgp_static
->backdoor
)
13183 vty_out(vty
, " backdoor");
13185 vty_out(vty
, "\n");
13190 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
13191 afi_t afi
, safi_t safi
)
13193 struct bgp_node
*prn
;
13194 struct bgp_node
*rn
;
13195 struct bgp_table
*table
;
13196 const struct prefix
*p
;
13197 const struct prefix_rd
*prd
;
13198 struct bgp_static
*bgp_static
;
13199 char buf
[PREFIX_STRLEN
* 2];
13200 char buf2
[SU_ADDRSTRLEN
];
13201 char rdbuf
[RD_ADDRSTRLEN
];
13203 /* Network configuration. */
13204 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
13205 prn
= bgp_route_next(prn
)) {
13206 table
= bgp_node_get_bgp_table_info(prn
);
13210 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
13211 bgp_static
= bgp_node_get_bgp_static_info(rn
);
13212 if (bgp_static
== NULL
)
13215 char *macrouter
= NULL
;
13218 if (bgp_static
->router_mac
)
13219 macrouter
= prefix_mac2str(
13220 bgp_static
->router_mac
, NULL
, 0);
13221 if (bgp_static
->eth_s_id
)
13222 esi
= esi2str(bgp_static
->eth_s_id
);
13223 p
= bgp_node_get_prefix(rn
);
13224 prd
= (struct prefix_rd
*)bgp_node_get_prefix(prn
);
13226 /* "network" configuration display. */
13227 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
13228 if (p
->u
.prefix_evpn
.route_type
== 5) {
13229 char local_buf
[PREFIX_STRLEN
];
13230 uint8_t family
= is_evpn_prefix_ipaddr_v4((
13231 struct prefix_evpn
*)p
)
13235 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
13236 local_buf
, PREFIX_STRLEN
);
13237 sprintf(buf
, "%s/%u", local_buf
,
13238 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
13240 prefix2str(p
, buf
, sizeof(buf
));
13243 if (bgp_static
->gatewayIp
.family
== AF_INET
13244 || bgp_static
->gatewayIp
.family
== AF_INET6
)
13245 inet_ntop(bgp_static
->gatewayIp
.family
,
13246 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
13249 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
13251 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
13252 decode_label(&bgp_static
->label
), esi
, buf2
,
13255 XFREE(MTYPE_TMP
, macrouter
);
13256 XFREE(MTYPE_TMP
, esi
);
13261 /* Configuration of static route announcement and aggregate
13263 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13266 struct bgp_node
*rn
;
13267 const struct prefix
*p
;
13268 struct bgp_static
*bgp_static
;
13269 struct bgp_aggregate
*bgp_aggregate
;
13270 char buf
[SU_ADDRSTRLEN
];
13272 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
13273 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
13277 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
13278 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
13282 /* Network configuration. */
13283 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
13284 rn
= bgp_route_next(rn
)) {
13285 bgp_static
= bgp_node_get_bgp_static_info(rn
);
13286 if (bgp_static
== NULL
)
13289 p
= bgp_node_get_prefix(rn
);
13291 vty_out(vty
, " network %s/%d",
13292 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13295 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
13296 vty_out(vty
, " label-index %u",
13297 bgp_static
->label_index
);
13299 if (bgp_static
->rmap
.name
)
13300 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
13302 if (bgp_static
->backdoor
)
13303 vty_out(vty
, " backdoor");
13305 vty_out(vty
, "\n");
13308 /* Aggregate-address configuration. */
13309 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
13310 rn
= bgp_route_next(rn
)) {
13311 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
13312 if (bgp_aggregate
== NULL
)
13315 p
= bgp_node_get_prefix(rn
);
13317 vty_out(vty
, " aggregate-address %s/%d",
13318 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
13321 if (bgp_aggregate
->as_set
)
13322 vty_out(vty
, " as-set");
13324 if (bgp_aggregate
->summary_only
)
13325 vty_out(vty
, " summary-only");
13327 if (bgp_aggregate
->rmap
.name
)
13328 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
13330 if (bgp_aggregate
->origin
!= BGP_ORIGIN_UNSPECIFIED
)
13331 vty_out(vty
, " origin %s",
13332 bgp_origin2str(bgp_aggregate
->origin
));
13334 vty_out(vty
, "\n");
13338 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
13341 struct bgp_node
*rn
;
13342 struct bgp_distance
*bdistance
;
13344 /* Distance configuration. */
13345 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
13346 && bgp
->distance_local
[afi
][safi
]
13347 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
13348 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
13349 || bgp
->distance_local
[afi
][safi
]
13350 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
13351 vty_out(vty
, " distance bgp %d %d %d\n",
13352 bgp
->distance_ebgp
[afi
][safi
],
13353 bgp
->distance_ibgp
[afi
][safi
],
13354 bgp
->distance_local
[afi
][safi
]);
13357 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
13358 rn
= bgp_route_next(rn
)) {
13359 bdistance
= bgp_node_get_bgp_distance_info(rn
);
13360 if (bdistance
!= NULL
)
13361 vty_out(vty
, " distance %d %pRN %s\n",
13362 bdistance
->distance
, rn
,
13363 bdistance
->access_list
? bdistance
->access_list
13368 /* Allocate routing table structure and install commands. */
13369 void bgp_route_init(void)
13374 /* Init BGP distance table. */
13375 FOREACH_AFI_SAFI (afi
, safi
)
13376 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
13378 /* IPv4 BGP commands. */
13379 install_element(BGP_NODE
, &bgp_table_map_cmd
);
13380 install_element(BGP_NODE
, &bgp_network_cmd
);
13381 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
13383 install_element(BGP_NODE
, &aggregate_address_cmd
);
13384 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
13385 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
13386 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
13388 /* IPv4 unicast configuration. */
13389 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
13390 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
13391 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
13393 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
13394 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
13395 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
13396 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
13398 /* IPv4 multicast configuration. */
13399 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
13400 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
13401 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
13402 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
13403 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
13404 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
13405 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13407 /* IPv4 labeled-unicast configuration. */
13408 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13409 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13410 install_element(VIEW_NODE
, &show_ip_bgp_afi_safi_statistics_cmd
);
13411 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_statistics_cmd
);
13412 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13413 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13414 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13415 install_element(VIEW_NODE
, &show_ip_bgp_statistics_all_cmd
);
13417 install_element(VIEW_NODE
,
13418 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13419 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13420 install_element(VIEW_NODE
,
13421 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13422 #ifdef KEEP_OLD_VPN_COMMANDS
13423 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13424 #endif /* KEEP_OLD_VPN_COMMANDS */
13425 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13426 install_element(VIEW_NODE
,
13427 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13429 /* BGP dampening clear commands */
13430 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13431 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13433 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13434 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13437 install_element(ENABLE_NODE
,
13438 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13439 #ifdef KEEP_OLD_VPN_COMMANDS
13440 install_element(ENABLE_NODE
,
13441 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13442 #endif /* KEEP_OLD_VPN_COMMANDS */
13444 /* New config IPv6 BGP commands. */
13445 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13446 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13447 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13449 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13450 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13452 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13454 install_element(BGP_NODE
, &bgp_distance_cmd
);
13455 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13456 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13457 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13458 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13459 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13460 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13461 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13462 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13463 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13464 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13465 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13466 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13467 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13468 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13469 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13470 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13471 install_element(BGP_IPV4M_NODE
,
13472 &no_bgp_distance_source_access_list_cmd
);
13473 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13474 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13475 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13476 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13477 install_element(BGP_IPV6_NODE
,
13478 &ipv6_bgp_distance_source_access_list_cmd
);
13479 install_element(BGP_IPV6_NODE
,
13480 &no_ipv6_bgp_distance_source_access_list_cmd
);
13481 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13482 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13483 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13484 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13485 install_element(BGP_IPV6M_NODE
,
13486 &ipv6_bgp_distance_source_access_list_cmd
);
13487 install_element(BGP_IPV6M_NODE
,
13488 &no_ipv6_bgp_distance_source_access_list_cmd
);
13490 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13491 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13492 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13493 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13495 /* IPv4 Multicast Mode */
13496 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13497 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13499 /* Large Communities */
13500 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13501 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13503 /* show bgp ipv4 flowspec detailed */
13504 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13506 install_element(VIEW_NODE
, &show_bgp_listeners_cmd
);
13507 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13510 void bgp_route_finish(void)
13515 FOREACH_AFI_SAFI (afi
, safi
) {
13516 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13517 bgp_distance_table
[afi
][safi
] = NULL
;