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"
74 #include "bgpd/rfapi/rfapi_backend.h"
75 #include "bgpd/rfapi/vnc_import_bgp.h"
76 #include "bgpd/rfapi/vnc_export_bgp.h"
78 #include "bgpd/bgp_encap_types.h"
79 #include "bgpd/bgp_encap_tlv.h"
80 #include "bgpd/bgp_evpn.h"
81 #include "bgpd/bgp_evpn_vty.h"
82 #include "bgpd/bgp_flowspec.h"
83 #include "bgpd/bgp_flowspec_util.h"
84 #include "bgpd/bgp_pbr.h"
86 #ifndef VTYSH_EXTRACT_PL
87 #include "bgpd/bgp_route_clippy.c"
90 /* Extern from bgp_dump.c */
91 extern const char *bgp_origin_str
[];
92 extern const char *bgp_origin_long_str
[];
93 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
95 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
96 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
97 static const struct message bgp_pmsi_tnltype_str
[] = {
98 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
99 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
100 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
101 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
102 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
103 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
104 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
105 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
109 #define VRFID_NONE_STR "-"
111 DEFINE_HOOK(bgp_process
,
112 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
113 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
114 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
117 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
118 safi_t safi
, struct prefix
*p
,
119 struct prefix_rd
*prd
)
122 struct bgp_node
*prn
= NULL
;
128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
129 || (safi
== SAFI_EVPN
)) {
130 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
132 if (!bgp_node_has_bgp_path_info_data(prn
))
133 bgp_node_set_bgp_table_info(
134 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
136 bgp_unlock_node(prn
);
137 table
= bgp_node_get_bgp_table_info(prn
);
140 rn
= bgp_node_get(table
, p
);
142 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
143 || (safi
== SAFI_EVPN
))
149 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
150 safi_t safi
, struct prefix
*p
,
151 struct prefix_rd
*prd
)
154 struct bgp_node
*prn
= NULL
;
159 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
160 || (safi
== SAFI_EVPN
)) {
161 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
165 if (!bgp_node_has_bgp_path_info_data(prn
)) {
166 bgp_unlock_node(prn
);
170 table
= bgp_node_get_bgp_table_info(prn
);
173 rn
= bgp_node_lookup(table
, p
);
178 /* Allocate bgp_path_info_extra */
179 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
181 struct bgp_path_info_extra
*new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
183 sizeof(struct bgp_path_info_extra
));
184 new->label
[0] = MPLS_INVALID_LABEL
;
186 new->bgp_fs_pbr
= NULL
;
187 new->bgp_fs_iprule
= NULL
;
191 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
193 struct bgp_path_info_extra
*e
;
195 if (!extra
|| !*extra
)
200 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
205 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
218 bpi
= bgp_path_info_lock(bpi
);
219 refcount
= bpi
->net
->lock
- 1;
220 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
223 bgp_path_info_unlock(bpi
);
225 bgp_path_info_unlock(e
->parent
);
230 bgp_unlock(e
->bgp_orig
);
232 if ((*extra
)->bgp_fs_iprule
)
233 list_delete(&((*extra
)->bgp_fs_iprule
));
234 if ((*extra
)->bgp_fs_pbr
)
235 list_delete(&((*extra
)->bgp_fs_pbr
));
236 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
241 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
242 * allocated if required.
244 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
247 pi
->extra
= bgp_path_info_extra_new();
251 /* Free bgp route information. */
252 static void bgp_path_info_free(struct bgp_path_info
*path
)
254 bgp_attr_unintern(&path
->attr
);
256 bgp_unlink_nexthop(path
);
257 bgp_path_info_extra_free(&path
->extra
);
258 bgp_path_info_mpath_free(&path
->mpath
);
260 bgp_addpath_free_info_data(&path
->tx_addpath
,
261 &path
->net
->tx_addpath
);
263 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
265 XFREE(MTYPE_BGP_ROUTE
, path
);
268 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
274 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
276 assert(path
&& path
->lock
> 0);
279 if (path
->lock
== 0) {
281 zlog_debug ("%s: unlocked and freeing", __func__
);
282 zlog_backtrace (LOG_DEBUG
);
284 bgp_path_info_free(path
);
291 zlog_debug ("%s: unlocked to 1", __func__
);
292 zlog_backtrace (LOG_DEBUG
);
299 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
300 static int bgp_node_set_defer_flag(struct bgp_node
*rn
, bool delete)
303 struct bgp_path_info
*old_pi
, *nextpi
;
305 struct bgp
*bgp
= NULL
;
306 struct bgp_table
*table
= NULL
;
309 char buf
[PREFIX2STR_BUFFER
];
311 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
312 * then the route selection is deferred
314 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
317 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
318 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
319 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
321 "Route %s is in workqueue and being processed, not deferred.",
327 table
= bgp_node_table(rn
);
334 for (old_pi
= bgp_node_get_bgp_path_info(rn
);
335 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
336 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
339 /* Route selection is deferred if there is a stale path which
340 * which indicates peer is in restart mode
342 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
)
343 && (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
346 /* If the peer is graceful restart capable and peer is
347 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
350 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
)
351 && BGP_PEER_RESTARTING_MODE(peer
)
353 && old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
361 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
364 if (set_flag
&& table
) {
365 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
366 SET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
367 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
368 if (rn
->rt_node
== NULL
)
369 rn
->rt_node
= listnode_add(
370 bgp
->gr_info
[afi
][safi
].route_list
, rn
);
371 if (BGP_DEBUG(update
, UPDATE_OUT
))
372 zlog_debug("DEFER route %s, rn %p, node %p",
373 buf
, rn
, rn
->rt_node
);
380 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
382 struct bgp_path_info
*top
;
384 top
= bgp_node_get_bgp_path_info(rn
);
390 bgp_node_set_bgp_path_info(rn
, pi
);
392 bgp_path_info_lock(pi
);
394 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
395 bgp_node_set_defer_flag(rn
, false);
398 /* Do the actual removal of info from RIB, for use by bgp_process
399 completion callback *only* */
400 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
403 pi
->next
->prev
= pi
->prev
;
405 pi
->prev
->next
= pi
->next
;
407 bgp_node_set_bgp_path_info(rn
, pi
->next
);
409 bgp_path_info_mpath_dequeue(pi
);
410 bgp_path_info_unlock(pi
);
414 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
416 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
417 /* set of previous already took care of pcount */
418 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
421 /* undo the effects of a previous call to bgp_path_info_delete; typically
422 called when a route is deleted and then quickly re-added before the
423 deletion has been processed */
424 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
426 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
427 /* unset of previous already took care of pcount */
428 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
431 /* Adjust pcount as required */
432 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
434 struct bgp_table
*table
;
436 assert(rn
&& bgp_node_table(rn
));
437 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
439 table
= bgp_node_table(rn
);
441 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
444 if (!BGP_PATH_COUNTABLE(pi
)
445 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
447 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
449 /* slight hack, but more robust against errors. */
450 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
451 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
453 flog_err(EC_LIB_DEVELOPMENT
,
454 "Asked to decrement 0 prefix count for peer");
455 } else if (BGP_PATH_COUNTABLE(pi
)
456 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
457 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
458 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
462 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
463 struct bgp_path_info
*pi2
)
465 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
468 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
469 * This is here primarily to keep prefix-count in check.
471 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
474 SET_FLAG(pi
->flags
, flag
);
476 /* early bath if we know it's not a flag that changes countability state
478 if (!CHECK_FLAG(flag
,
479 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
482 bgp_pcount_adjust(rn
, pi
);
485 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
488 UNSET_FLAG(pi
->flags
, flag
);
490 /* early bath if we know it's not a flag that changes countability state
492 if (!CHECK_FLAG(flag
,
493 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
496 bgp_pcount_adjust(rn
, pi
);
499 /* Get MED value. If MED value is missing and "bgp bestpath
500 missing-as-worst" is specified, treat it as the worst value. */
501 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
503 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
506 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
513 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
515 if (pi
->addpath_rx_id
)
516 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
519 sprintf(buf
, "path %s", pi
->peer
->host
);
522 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
524 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
525 struct bgp_path_info
*exist
, int *paths_eq
,
526 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
527 char *pfx_buf
, afi_t afi
, safi_t safi
,
528 enum bgp_path_selection_reason
*reason
)
530 struct attr
*newattr
, *existattr
;
531 bgp_peer_sort_t new_sort
;
532 bgp_peer_sort_t exist_sort
;
538 uint32_t exist_weight
;
539 uint32_t newm
, existm
;
540 struct in_addr new_id
;
541 struct in_addr exist_id
;
544 int internal_as_route
;
547 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
548 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
550 uint32_t exist_mm_seq
;
557 *reason
= bgp_path_selection_none
;
559 zlog_debug("%s: new is NULL", pfx_buf
);
564 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
567 *reason
= bgp_path_selection_first
;
569 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
575 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
576 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
577 pfx_buf
, new_buf
, new->flags
, exist_buf
,
582 existattr
= exist
->attr
;
584 /* For EVPN routes, we cannot just go by local vs remote, we have to
585 * look at the MAC mobility sequence number, if present.
587 if (safi
== SAFI_EVPN
) {
588 /* This is an error condition described in RFC 7432 Section
590 * states that in this scenario "the PE MUST alert the operator"
592 * does not state what other action to take. In order to provide
594 * consistency in this scenario we are going to prefer the path
598 if (newattr
->sticky
!= existattr
->sticky
) {
600 prefix2str(&new->net
->p
, pfx_buf
,
602 * PREFIX2STR_BUFFER
);
603 bgp_path_info_path_with_addpath_rx_str(new,
605 bgp_path_info_path_with_addpath_rx_str(
609 if (newattr
->sticky
&& !existattr
->sticky
) {
610 *reason
= bgp_path_selection_evpn_sticky_mac
;
613 "%s: %s wins over %s due to sticky MAC flag",
614 pfx_buf
, new_buf
, exist_buf
);
618 if (!newattr
->sticky
&& existattr
->sticky
) {
619 *reason
= bgp_path_selection_evpn_sticky_mac
;
622 "%s: %s loses to %s due to sticky MAC flag",
623 pfx_buf
, new_buf
, exist_buf
);
628 new_mm_seq
= mac_mobility_seqnum(newattr
);
629 exist_mm_seq
= mac_mobility_seqnum(existattr
);
631 if (new_mm_seq
> exist_mm_seq
) {
632 *reason
= bgp_path_selection_evpn_seq
;
635 "%s: %s wins over %s due to MM seq %u > %u",
636 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
641 if (new_mm_seq
< exist_mm_seq
) {
642 *reason
= bgp_path_selection_evpn_seq
;
645 "%s: %s loses to %s due to MM seq %u < %u",
646 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
652 * if sequence numbers are the same path with the lowest IP
655 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
657 *reason
= bgp_path_selection_evpn_lower_ip
;
660 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
661 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
662 inet_ntoa(new->attr
->nexthop
));
666 *reason
= bgp_path_selection_evpn_lower_ip
;
669 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
670 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
671 inet_ntoa(new->attr
->nexthop
));
676 /* 1. Weight check. */
677 new_weight
= newattr
->weight
;
678 exist_weight
= existattr
->weight
;
680 if (new_weight
> exist_weight
) {
681 *reason
= bgp_path_selection_weight
;
683 zlog_debug("%s: %s wins over %s due to weight %d > %d",
684 pfx_buf
, new_buf
, exist_buf
, new_weight
,
689 if (new_weight
< exist_weight
) {
690 *reason
= bgp_path_selection_weight
;
692 zlog_debug("%s: %s loses to %s due to weight %d < %d",
693 pfx_buf
, new_buf
, exist_buf
, new_weight
,
698 /* 2. Local preference check. */
699 new_pref
= exist_pref
= bgp
->default_local_pref
;
701 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
702 new_pref
= newattr
->local_pref
;
703 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
704 exist_pref
= existattr
->local_pref
;
706 if (new_pref
> exist_pref
) {
707 *reason
= bgp_path_selection_local_pref
;
710 "%s: %s wins over %s due to localpref %d > %d",
711 pfx_buf
, new_buf
, exist_buf
, new_pref
,
716 if (new_pref
< exist_pref
) {
717 *reason
= bgp_path_selection_local_pref
;
720 "%s: %s loses to %s due to localpref %d < %d",
721 pfx_buf
, new_buf
, exist_buf
, new_pref
,
726 /* 3. Local route check. We prefer:
728 * - BGP_ROUTE_AGGREGATE
729 * - BGP_ROUTE_REDISTRIBUTE
731 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
732 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
733 *reason
= bgp_path_selection_local_route
;
736 "%s: %s wins over %s due to preferred BGP_ROUTE type",
737 pfx_buf
, new_buf
, exist_buf
);
741 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
742 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
743 *reason
= bgp_path_selection_local_route
;
746 "%s: %s loses to %s due to preferred BGP_ROUTE type",
747 pfx_buf
, new_buf
, exist_buf
);
751 /* 4. AS path length check. */
752 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
753 int exist_hops
= aspath_count_hops(existattr
->aspath
);
754 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
756 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
759 aspath_hops
= aspath_count_hops(newattr
->aspath
);
760 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
762 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
763 *reason
= bgp_path_selection_confed_as_path
;
766 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
767 pfx_buf
, new_buf
, exist_buf
,
769 (exist_hops
+ exist_confeds
));
773 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
774 *reason
= bgp_path_selection_confed_as_path
;
777 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
778 pfx_buf
, new_buf
, exist_buf
,
780 (exist_hops
+ exist_confeds
));
784 int newhops
= aspath_count_hops(newattr
->aspath
);
786 if (newhops
< exist_hops
) {
787 *reason
= bgp_path_selection_as_path
;
790 "%s: %s wins over %s due to aspath hopcount %d < %d",
791 pfx_buf
, new_buf
, exist_buf
,
792 newhops
, exist_hops
);
796 if (newhops
> exist_hops
) {
797 *reason
= bgp_path_selection_as_path
;
800 "%s: %s loses to %s due to aspath hopcount %d > %d",
801 pfx_buf
, new_buf
, exist_buf
,
802 newhops
, exist_hops
);
808 /* 5. Origin check. */
809 if (newattr
->origin
< existattr
->origin
) {
810 *reason
= bgp_path_selection_origin
;
812 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
813 pfx_buf
, new_buf
, exist_buf
,
814 bgp_origin_long_str
[newattr
->origin
],
815 bgp_origin_long_str
[existattr
->origin
]);
819 if (newattr
->origin
> existattr
->origin
) {
820 *reason
= bgp_path_selection_origin
;
822 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
823 pfx_buf
, new_buf
, exist_buf
,
824 bgp_origin_long_str
[newattr
->origin
],
825 bgp_origin_long_str
[existattr
->origin
]);
830 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
831 && aspath_count_hops(existattr
->aspath
) == 0);
832 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
833 && aspath_count_confeds(existattr
->aspath
) > 0
834 && aspath_count_hops(newattr
->aspath
) == 0
835 && aspath_count_hops(existattr
->aspath
) == 0);
837 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
838 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
839 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
840 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
841 || internal_as_route
) {
842 new_med
= bgp_med_value(new->attr
, bgp
);
843 exist_med
= bgp_med_value(exist
->attr
, bgp
);
845 if (new_med
< exist_med
) {
846 *reason
= bgp_path_selection_med
;
849 "%s: %s wins over %s due to MED %d < %d",
850 pfx_buf
, new_buf
, exist_buf
, new_med
,
855 if (new_med
> exist_med
) {
856 *reason
= bgp_path_selection_med
;
859 "%s: %s loses to %s due to MED %d > %d",
860 pfx_buf
, new_buf
, exist_buf
, new_med
,
866 /* 7. Peer type check. */
867 new_sort
= new->peer
->sort
;
868 exist_sort
= exist
->peer
->sort
;
870 if (new_sort
== BGP_PEER_EBGP
871 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
872 *reason
= bgp_path_selection_peer
;
875 "%s: %s wins over %s due to eBGP peer > iBGP peer",
876 pfx_buf
, new_buf
, exist_buf
);
880 if (exist_sort
== BGP_PEER_EBGP
881 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
882 *reason
= bgp_path_selection_peer
;
885 "%s: %s loses to %s due to iBGP peer < eBGP peer",
886 pfx_buf
, new_buf
, exist_buf
);
890 /* 8. IGP metric check. */
894 newm
= new->extra
->igpmetric
;
896 existm
= exist
->extra
->igpmetric
;
901 "%s: %s wins over %s due to IGP metric %d < %d",
902 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
909 "%s: %s loses to %s due to IGP metric %d > %d",
910 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
914 /* 9. Same IGP metric. Compare the cluster list length as
915 representative of IGP hops metric. Rewrite the metric value
916 pair (newm, existm) with the cluster list length. Prefer the
917 path with smaller cluster list length. */
918 if (newm
== existm
) {
919 if (peer_sort(new->peer
) == BGP_PEER_IBGP
920 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
921 && (mpath_cfg
== NULL
923 mpath_cfg
->ibgp_flags
,
924 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
925 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
926 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
931 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
932 pfx_buf
, new_buf
, exist_buf
,
940 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
941 pfx_buf
, new_buf
, exist_buf
,
948 /* 10. confed-external vs. confed-internal */
949 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
950 if (new_sort
== BGP_PEER_CONFED
951 && exist_sort
== BGP_PEER_IBGP
) {
952 *reason
= bgp_path_selection_confed
;
955 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
956 pfx_buf
, new_buf
, exist_buf
);
960 if (exist_sort
== BGP_PEER_CONFED
961 && new_sort
== BGP_PEER_IBGP
) {
962 *reason
= bgp_path_selection_confed
;
965 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
966 pfx_buf
, new_buf
, exist_buf
);
971 /* 11. Maximum path check. */
972 if (newm
== existm
) {
973 /* If one path has a label but the other does not, do not treat
974 * them as equals for multipath
976 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
978 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
981 "%s: %s and %s cannot be multipath, one has a label while the other does not",
982 pfx_buf
, new_buf
, exist_buf
);
983 } else if (bgp_flag_check(bgp
,
984 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
987 * For the two paths, all comparison steps till IGP
989 * have succeeded - including AS_PATH hop count. Since
991 * bestpath as-path multipath-relax' knob is on, we
993 * an exact match of AS_PATH. Thus, mark the paths are
995 * That will trigger both these paths to get into the
1003 "%s: %s and %s are equal via multipath-relax",
1004 pfx_buf
, new_buf
, exist_buf
);
1005 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1006 if (aspath_cmp(new->attr
->aspath
,
1007 exist
->attr
->aspath
)) {
1012 "%s: %s and %s are equal via matching aspaths",
1013 pfx_buf
, new_buf
, exist_buf
);
1015 } else if (new->peer
->as
== exist
->peer
->as
) {
1020 "%s: %s and %s are equal via same remote-as",
1021 pfx_buf
, new_buf
, exist_buf
);
1025 * TODO: If unequal cost ibgp multipath is enabled we can
1026 * mark the paths as equal here instead of returning
1031 "%s: %s wins over %s after IGP metric comparison",
1032 pfx_buf
, new_buf
, exist_buf
);
1035 "%s: %s loses to %s after IGP metric comparison",
1036 pfx_buf
, new_buf
, exist_buf
);
1038 *reason
= bgp_path_selection_igp_metric
;
1042 /* 12. If both paths are external, prefer the path that was received
1043 first (the oldest one). This step minimizes route-flap, since a
1044 newer path won't displace an older one, even if it was the
1045 preferred route based on the additional decision criteria below. */
1046 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
1047 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1048 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1049 *reason
= bgp_path_selection_older
;
1052 "%s: %s wins over %s due to oldest external",
1053 pfx_buf
, new_buf
, exist_buf
);
1057 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1058 *reason
= bgp_path_selection_older
;
1061 "%s: %s loses to %s due to oldest external",
1062 pfx_buf
, new_buf
, exist_buf
);
1067 /* 13. Router-ID comparision. */
1068 /* If one of the paths is "stale", the corresponding peer router-id will
1069 * be 0 and would always win over the other path. If originator id is
1070 * used for the comparision, it will decide which path is better.
1072 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1073 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1075 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1076 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1077 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1079 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1081 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1082 *reason
= bgp_path_selection_router_id
;
1085 "%s: %s wins over %s due to Router-ID comparison",
1086 pfx_buf
, new_buf
, exist_buf
);
1090 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1091 *reason
= bgp_path_selection_router_id
;
1094 "%s: %s loses to %s due to Router-ID comparison",
1095 pfx_buf
, new_buf
, exist_buf
);
1099 /* 14. Cluster length comparision. */
1100 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1101 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1103 if (new_cluster
< exist_cluster
) {
1104 *reason
= bgp_path_selection_cluster_length
;
1107 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1108 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1113 if (new_cluster
> exist_cluster
) {
1114 *reason
= bgp_path_selection_cluster_length
;
1117 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1118 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1123 /* 15. Neighbor address comparision. */
1124 /* Do this only if neither path is "stale" as stale paths do not have
1125 * valid peer information (as the connection may or may not be up).
1127 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1128 *reason
= bgp_path_selection_stale
;
1131 "%s: %s wins over %s due to latter path being STALE",
1132 pfx_buf
, new_buf
, exist_buf
);
1136 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1137 *reason
= bgp_path_selection_stale
;
1140 "%s: %s loses to %s due to former path being STALE",
1141 pfx_buf
, new_buf
, exist_buf
);
1145 /* locally configured routes to advertise do not have su_remote */
1146 if (new->peer
->su_remote
== NULL
) {
1147 *reason
= bgp_path_selection_local_configured
;
1150 if (exist
->peer
->su_remote
== NULL
) {
1151 *reason
= bgp_path_selection_local_configured
;
1155 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1158 *reason
= bgp_path_selection_neighbor_ip
;
1161 "%s: %s loses to %s due to Neighor IP comparison",
1162 pfx_buf
, new_buf
, exist_buf
);
1167 *reason
= bgp_path_selection_neighbor_ip
;
1170 "%s: %s wins over %s due to Neighor IP comparison",
1171 pfx_buf
, new_buf
, exist_buf
);
1175 *reason
= bgp_path_selection_default
;
1177 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1178 pfx_buf
, new_buf
, exist_buf
);
1183 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1184 * is preferred, or 0 if they are the same (usually will only occur if
1185 * multipath is enabled
1186 * This version is compatible with */
1187 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1188 struct bgp_path_info
*exist
, char *pfx_buf
,
1189 afi_t afi
, safi_t safi
,
1190 enum bgp_path_selection_reason
*reason
)
1194 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1208 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1209 struct attr
*attr
, afi_t afi
,
1212 struct bgp_filter
*filter
;
1214 filter
= &peer
->filter
[afi
][safi
];
1216 #define FILTER_EXIST_WARN(F, f, filter) \
1217 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1218 zlog_debug("%s: Could not find configured input %s-list %s!", \
1219 peer->host, #f, F##_IN_NAME(filter));
1221 if (DISTRIBUTE_IN_NAME(filter
)) {
1222 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1224 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1228 if (PREFIX_LIST_IN_NAME(filter
)) {
1229 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1231 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1235 if (FILTER_LIST_IN_NAME(filter
)) {
1236 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1238 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1243 return FILTER_PERMIT
;
1244 #undef FILTER_EXIST_WARN
1247 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1248 struct attr
*attr
, afi_t afi
,
1251 struct bgp_filter
*filter
;
1253 filter
= &peer
->filter
[afi
][safi
];
1255 #define FILTER_EXIST_WARN(F, f, filter) \
1256 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1257 zlog_debug("%s: Could not find configured output %s-list %s!", \
1258 peer->host, #f, F##_OUT_NAME(filter));
1260 if (DISTRIBUTE_OUT_NAME(filter
)) {
1261 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1263 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1267 if (PREFIX_LIST_OUT_NAME(filter
)) {
1268 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1270 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1275 if (FILTER_LIST_OUT_NAME(filter
)) {
1276 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1278 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1283 return FILTER_PERMIT
;
1284 #undef FILTER_EXIST_WARN
1287 /* If community attribute includes no_export then return 1. */
1288 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1290 if (attr
->community
) {
1291 /* NO_ADVERTISE check. */
1292 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1295 /* NO_EXPORT check. */
1296 if (peer
->sort
== BGP_PEER_EBGP
1297 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1300 /* NO_EXPORT_SUBCONFED check. */
1301 if (peer
->sort
== BGP_PEER_EBGP
1302 || peer
->sort
== BGP_PEER_CONFED
)
1303 if (community_include(attr
->community
,
1304 COMMUNITY_NO_EXPORT_SUBCONFED
))
1310 /* Route reflection loop check. */
1311 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1313 struct in_addr cluster_id
;
1315 if (attr
->cluster
) {
1316 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1317 cluster_id
= peer
->bgp
->cluster_id
;
1319 cluster_id
= peer
->bgp
->router_id
;
1321 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1327 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1328 struct attr
*attr
, afi_t afi
, safi_t safi
,
1329 const char *rmap_name
, mpls_label_t
*label
,
1330 uint32_t num_labels
, struct bgp_node
*rn
)
1332 struct bgp_filter
*filter
;
1333 struct bgp_path_info rmap_path
= { 0 };
1334 struct bgp_path_info_extra extra
= { 0 };
1335 route_map_result_t ret
;
1336 struct route_map
*rmap
= NULL
;
1338 filter
= &peer
->filter
[afi
][safi
];
1340 /* Apply default weight value. */
1341 if (peer
->weight
[afi
][safi
])
1342 attr
->weight
= peer
->weight
[afi
][safi
];
1345 rmap
= route_map_lookup_by_name(rmap_name
);
1350 if (ROUTE_MAP_IN_NAME(filter
)) {
1351 rmap
= ROUTE_MAP_IN(filter
);
1358 /* Route map apply. */
1360 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1361 /* Duplicate current value to new strucutre for modification. */
1362 rmap_path
.peer
= peer
;
1363 rmap_path
.attr
= attr
;
1364 rmap_path
.extra
= &extra
;
1367 extra
.num_labels
= num_labels
;
1368 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1369 memcpy(extra
.label
, label
,
1370 num_labels
* sizeof(mpls_label_t
));
1372 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1374 /* Apply BGP route map to the attribute. */
1375 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1377 peer
->rmap_type
= 0;
1379 if (ret
== RMAP_DENYMATCH
)
1385 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1386 struct attr
*attr
, afi_t afi
, safi_t safi
,
1387 const char *rmap_name
)
1389 struct bgp_path_info rmap_path
;
1390 route_map_result_t ret
;
1391 struct route_map
*rmap
= NULL
;
1395 * So if we get to this point and have no rmap_name
1396 * we want to just show the output as it currently
1402 /* Apply default weight value. */
1403 if (peer
->weight
[afi
][safi
])
1404 attr
->weight
= peer
->weight
[afi
][safi
];
1406 rmap
= route_map_lookup_by_name(rmap_name
);
1409 * If we have a route map name and we do not find
1410 * the routemap that means we have an implicit
1416 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1417 /* Route map apply. */
1418 /* Duplicate current value to new strucutre for modification. */
1419 rmap_path
.peer
= peer
;
1420 rmap_path
.attr
= attr
;
1422 rmap_type
= peer
->rmap_type
;
1423 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1425 /* Apply BGP route map to the attribute. */
1426 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1428 peer
->rmap_type
= rmap_type
;
1430 if (ret
== RMAP_DENYMATCH
)
1432 * caller has multiple error paths with bgp_attr_flush()
1439 /* If this is an EBGP peer with remove-private-AS */
1440 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1441 struct peer
*peer
, struct attr
*attr
)
1443 if (peer
->sort
== BGP_PEER_EBGP
1444 && (peer_af_flag_check(peer
, afi
, safi
,
1445 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1446 || peer_af_flag_check(peer
, afi
, safi
,
1447 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1448 || peer_af_flag_check(peer
, afi
, safi
,
1449 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1450 || peer_af_flag_check(peer
, afi
, safi
,
1451 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1452 // Take action on the entire aspath
1453 if (peer_af_flag_check(peer
, afi
, safi
,
1454 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1455 || peer_af_flag_check(peer
, afi
, safi
,
1456 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1457 if (peer_af_flag_check(
1459 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1460 attr
->aspath
= aspath_replace_private_asns(
1461 attr
->aspath
, bgp
->as
, peer
->as
);
1463 // The entire aspath consists of private ASNs so create
1465 else if (aspath_private_as_check(attr
->aspath
))
1466 attr
->aspath
= aspath_empty_get();
1468 // There are some public and some private ASNs, remove
1471 attr
->aspath
= aspath_remove_private_asns(
1472 attr
->aspath
, peer
->as
);
1475 // 'all' was not specified so the entire aspath must be private
1477 // for us to do anything
1478 else if (aspath_private_as_check(attr
->aspath
)) {
1479 if (peer_af_flag_check(
1481 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1482 attr
->aspath
= aspath_replace_private_asns(
1483 attr
->aspath
, bgp
->as
, peer
->as
);
1485 attr
->aspath
= aspath_empty_get();
1490 /* If this is an EBGP peer with as-override */
1491 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1492 struct peer
*peer
, struct attr
*attr
)
1494 if (peer
->sort
== BGP_PEER_EBGP
1495 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1496 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1497 attr
->aspath
= aspath_replace_specific_asn(
1498 attr
->aspath
, peer
->as
, bgp
->as
);
1502 void bgp_attr_add_gshut_community(struct attr
*attr
)
1504 struct community
*old
;
1505 struct community
*new;
1506 struct community
*merge
;
1507 struct community
*gshut
;
1509 old
= attr
->community
;
1510 gshut
= community_str2com("graceful-shutdown");
1515 merge
= community_merge(community_dup(old
), gshut
);
1517 if (old
->refcnt
== 0)
1518 community_free(&old
);
1520 new = community_uniq_sort(merge
);
1521 community_free(&merge
);
1523 new = community_dup(gshut
);
1526 community_free(&gshut
);
1527 attr
->community
= new;
1528 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1530 /* When we add the graceful-shutdown community we must also
1531 * lower the local-preference */
1532 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1533 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1537 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1539 if (family
== AF_INET
) {
1540 attr
->nexthop
.s_addr
= 0;
1541 attr
->mp_nexthop_global_in
.s_addr
= 0;
1543 if (family
== AF_INET6
)
1544 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1545 if (family
== AF_EVPN
)
1546 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1549 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1550 struct update_subgroup
*subgrp
, struct prefix
*p
,
1553 struct bgp_filter
*filter
;
1556 struct peer
*onlypeer
;
1558 struct attr
*piattr
;
1559 char buf
[PREFIX_STRLEN
];
1560 route_map_result_t ret
;
1565 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1567 if (DISABLE_BGP_ANNOUNCE
)
1570 afi
= SUBGRP_AFI(subgrp
);
1571 safi
= SUBGRP_SAFI(subgrp
);
1572 peer
= SUBGRP_PEER(subgrp
);
1574 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1575 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1578 filter
= &peer
->filter
[afi
][safi
];
1579 bgp
= SUBGRP_INST(subgrp
);
1580 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1584 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1585 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1586 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1589 * direct and direct_ext type routes originate internally even
1590 * though they can have peer pointers that reference other
1593 prefix2str(p
, buf
, PREFIX_STRLEN
);
1594 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1600 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1601 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1602 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1603 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1605 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1610 /* With addpath we may be asked to TX all kinds of paths so make sure
1612 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1613 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1614 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1618 /* If this is not the bestpath then check to see if there is an enabled
1620 * feature that requires us to advertise it */
1621 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1622 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1627 /* Aggregate-address suppress check. */
1628 if (pi
->extra
&& pi
->extra
->suppress
)
1629 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1634 * If we are doing VRF 2 VRF leaking via the import
1635 * statement, we want to prevent the route going
1636 * off box as that the RT and RD created are localy
1637 * significant and globaly useless.
1639 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1640 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1643 /* If it's labeled safi, make sure the route has a valid label. */
1644 if (safi
== SAFI_LABELED_UNICAST
) {
1645 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1646 if (!bgp_is_valid_label(&label
)) {
1647 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1648 zlog_debug("u%" PRIu64
":s%" PRIu64
1649 " %s/%d is filtered - no label (%p)",
1650 subgrp
->update_group
->id
, subgrp
->id
,
1651 inet_ntop(p
->family
, &p
->u
.prefix
,
1652 buf
, SU_ADDRSTRLEN
),
1653 p
->prefixlen
, &label
);
1658 /* Do not send back route to sender. */
1659 if (onlypeer
&& from
== onlypeer
) {
1663 /* Do not send the default route in the BGP table if the neighbor is
1664 * configured for default-originate */
1665 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1666 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1667 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1669 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1673 /* Transparency check. */
1674 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1675 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1680 /* If community is not disabled check the no-export and local. */
1681 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1682 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1684 "subgrpannouncecheck: community filter check fail");
1688 /* If the attribute has originator-id and it is same as remote
1690 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1691 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1692 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1694 "%s [Update:SEND] %s originator-id is same as "
1697 prefix2str(p
, buf
, sizeof(buf
)));
1701 /* ORF prefix-list filter check */
1702 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1703 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1704 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1705 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1706 if (peer
->orf_plist
[afi
][safi
]) {
1707 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1709 if (bgp_debug_update(NULL
, p
,
1710 subgrp
->update_group
, 0))
1712 "%s [Update:SEND] %s is filtered via ORF",
1720 /* Output filter check. */
1721 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1722 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1723 zlog_debug("%s [Update:SEND] %s is filtered",
1724 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1728 /* AS path loop check. */
1729 if (onlypeer
&& onlypeer
->as_path_loop_detection
1730 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1731 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1733 "%s [Update:SEND] suppress announcement to peer AS %u "
1734 "that is part of AS path.",
1735 onlypeer
->host
, onlypeer
->as
);
1739 /* If we're a CONFED we need to loop check the CONFED ID too */
1740 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1741 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1742 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1744 "%s [Update:SEND] suppress announcement to peer AS %u"
1746 peer
->host
, bgp
->confed_id
);
1751 /* Route-Reflect check. */
1752 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1757 /* IBGP reflection check. */
1758 if (reflect
&& !samepeer_safe
) {
1759 /* A route from a Client peer. */
1760 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1761 PEER_FLAG_REFLECTOR_CLIENT
)) {
1762 /* Reflect to all the Non-Client peers and also to the
1763 Client peers other than the originator. Originator
1765 is already done. So there is noting to do. */
1766 /* no bgp client-to-client reflection check. */
1767 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1768 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1769 PEER_FLAG_REFLECTOR_CLIENT
))
1772 /* A route from a Non-client peer. Reflect to all other
1774 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1775 PEER_FLAG_REFLECTOR_CLIENT
))
1780 /* For modify attribute, copy it to temporary structure. */
1783 /* If local-preference is not set. */
1784 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1785 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1786 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1787 attr
->local_pref
= bgp
->default_local_pref
;
1790 /* If originator-id is not set and the route is to be reflected,
1791 set the originator id */
1793 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1794 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1795 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1798 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1800 if (peer
->sort
== BGP_PEER_EBGP
1801 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1802 if (from
!= bgp
->peer_self
&& !transparent
1803 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1804 PEER_FLAG_MED_UNCHANGED
))
1806 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1809 /* Since the nexthop attribute can vary per peer, it is not explicitly
1811 * in announce check, only certain flags and length (or number of
1813 * -- for IPv6/MP_REACH) are set here in order to guide the update
1815 * code in setting the nexthop(s) on a per peer basis in
1817 * Typically, the source nexthop in the attribute is preserved but in
1819 * scenarios where we know it will always be overwritten, we reset the
1820 * nexthop to "0" in an attempt to achieve better Update packing. An
1821 * example of this is when a prefix from each of 2 IBGP peers needs to
1823 * announced to an EBGP peer (and they have the same attributes barring
1827 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1829 #define NEXTHOP_IS_V6 \
1830 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1831 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1832 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1833 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1835 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1837 * the peer (group) is configured to receive link-local nexthop
1839 * and it is available in the prefix OR we're not reflecting the route,
1840 * link-local nexthop address is valid and
1841 * the peer (group) to whom we're going to announce is on a shared
1843 * and this is either a self-originated route or the peer is EBGP.
1844 * By checking if nexthop LL address is valid we are sure that
1845 * we do not announce LL address as `::`.
1847 if (NEXTHOP_IS_V6
) {
1848 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1849 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1850 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1851 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1853 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1854 && peer
->shared_network
1855 && (from
== bgp
->peer_self
1856 || peer
->sort
== BGP_PEER_EBGP
))) {
1857 attr
->mp_nexthop_len
=
1858 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1861 /* Clear off link-local nexthop in source, whenever it is not
1863 * ensure more prefixes share the same attribute for
1866 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1867 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1868 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1871 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1872 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1874 /* Route map & unsuppress-map apply. */
1875 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1876 struct bgp_path_info rmap_path
= {0};
1877 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1878 struct attr dummy_attr
= {0};
1880 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1881 rmap_path
.peer
= peer
;
1882 rmap_path
.attr
= attr
;
1886 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1887 sizeof(struct bgp_path_info_extra
));
1888 rmap_path
.extra
= &dummy_rmap_path_extra
;
1891 /* don't confuse inbound and outbound setting */
1892 RESET_FLAG(attr
->rmap_change_flags
);
1895 * The route reflector is not allowed to modify the attributes
1896 * of the reflected IBGP routes unless explicitly allowed.
1898 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1899 && !bgp_flag_check(bgp
,
1900 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1902 rmap_path
.attr
= &dummy_attr
;
1905 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1907 if (pi
->extra
&& pi
->extra
->suppress
)
1908 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1909 RMAP_BGP
, &rmap_path
);
1911 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1912 RMAP_BGP
, &rmap_path
);
1914 peer
->rmap_type
= 0;
1916 if (ret
== RMAP_DENYMATCH
) {
1917 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1918 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1919 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1921 bgp_attr_flush(attr
);
1926 /* RFC 8212 to prevent route leaks.
1927 * This specification intends to improve this situation by requiring the
1928 * explicit configuration of both BGP Import and Export Policies for any
1929 * External BGP (EBGP) session such as customers, peers, or
1930 * confederation boundaries for all enabled address families. Through
1931 * codification of the aforementioned requirement, operators will
1932 * benefit from consistent behavior across different BGP
1935 if (peer
->bgp
->ebgp_requires_policy
1936 == DEFAULT_EBGP_POLICY_ENABLED
)
1937 if (!bgp_outbound_policy_exists(peer
, filter
))
1940 /* draft-ietf-idr-deprecate-as-set-confed-set
1941 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1942 * Eventually, This document (if approved) updates RFC 4271
1943 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1944 * and obsoletes RFC 6472.
1946 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
1947 if (aspath_check_as_sets(attr
->aspath
))
1950 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1951 if (peer
->sort
== BGP_PEER_IBGP
1952 || peer
->sort
== BGP_PEER_CONFED
) {
1953 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1954 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1956 bgp_attr_add_gshut_community(attr
);
1960 /* After route-map has been applied, we check to see if the nexthop to
1961 * be carried in the attribute (that is used for the announcement) can
1962 * be cleared off or not. We do this in all cases where we would be
1963 * setting the nexthop to "ourselves". For IPv6, we only need to
1965 * the global nexthop here; the link-local nexthop would have been
1967 * already, and if not, it is required by the update formation code.
1968 * Also see earlier comments in this function.
1971 * If route-map has performed some operation on the nexthop or the peer
1972 * configuration says to pass it unchanged, we cannot reset the nexthop
1973 * here, so only attempt to do it if these aren't true. Note that the
1974 * route-map handler itself might have cleared the nexthop, if for
1976 * it is configured as 'peer-address'.
1978 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1979 piattr
->rmap_change_flags
)
1981 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1982 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1983 /* We can reset the nexthop, if setting (or forcing) it to
1985 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1986 PEER_FLAG_NEXTHOP_SELF
)
1987 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1988 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1990 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1991 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1992 subgroup_announce_reset_nhop(
1993 (peer_cap_enhe(peer
, afi
, safi
)
1997 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1998 /* Can also reset the nexthop if announcing to EBGP, but
2000 * no peer in the subgroup is on a shared subnet.
2001 * Note: 3rd party nexthop currently implemented for
2004 if ((p
->family
== AF_INET
) &&
2005 (!bgp_subgrp_multiaccess_check_v4(
2008 subgroup_announce_reset_nhop(
2009 (peer_cap_enhe(peer
, afi
, safi
)
2014 if ((p
->family
== AF_INET6
) &&
2015 (!bgp_subgrp_multiaccess_check_v6(
2016 piattr
->mp_nexthop_global
,
2018 subgroup_announce_reset_nhop(
2019 (peer_cap_enhe(peer
, afi
, safi
)
2026 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2028 * This flag is used for leaked vpn-vrf routes
2030 int family
= p
->family
;
2032 if (peer_cap_enhe(peer
, afi
, safi
))
2035 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2037 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2038 __func__
, family2str(family
));
2039 subgroup_announce_reset_nhop(family
, attr
);
2043 /* If IPv6/MP and nexthop does not have any override and happens
2045 * be a link-local address, reset it so that we don't pass along
2047 * source's link-local IPv6 address to recipients who may not be
2049 * the same interface.
2051 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2052 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
2053 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2059 static int bgp_route_select_timer_expire(struct thread
*thread
)
2061 struct afi_safi_info
*info
;
2066 info
= THREAD_ARG(thread
);
2071 if (BGP_DEBUG(update
, UPDATE_OUT
))
2072 zlog_debug("afi %d, safi %d : route select timer expired", afi
,
2075 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2077 XFREE(MTYPE_TMP
, info
);
2079 /* Best path selection */
2080 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2083 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
2084 struct bgp_maxpaths_cfg
*mpath_cfg
,
2085 struct bgp_path_info_pair
*result
, afi_t afi
,
2088 struct bgp_path_info
*new_select
;
2089 struct bgp_path_info
*old_select
;
2090 struct bgp_path_info
*pi
;
2091 struct bgp_path_info
*pi1
;
2092 struct bgp_path_info
*pi2
;
2093 struct bgp_path_info
*nextpi
= NULL
;
2094 int paths_eq
, do_mpath
, debug
;
2095 struct list mp_list
;
2096 char pfx_buf
[PREFIX2STR_BUFFER
];
2097 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2099 bgp_mp_list_init(&mp_list
);
2101 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2103 debug
= bgp_debug_bestpath(&rn
->p
);
2106 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2108 /* bgp deterministic-med */
2110 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
2112 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2113 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2115 bgp_path_info_unset_flag(rn
, pi1
,
2116 BGP_PATH_DMED_SELECTED
);
2118 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2120 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2122 if (BGP_PATH_HOLDDOWN(pi1
))
2124 if (pi1
->peer
!= bgp
->peer_self
)
2125 if (pi1
->peer
->status
!= Established
)
2130 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2131 if (CHECK_FLAG(pi2
->flags
,
2132 BGP_PATH_DMED_CHECK
))
2134 if (BGP_PATH_HOLDDOWN(pi2
))
2136 if (pi2
->peer
!= bgp
->peer_self
2139 PEER_STATUS_NSF_WAIT
))
2140 if (pi2
->peer
->status
2144 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2146 && !aspath_cmp_left_confed(
2151 if (bgp_path_info_cmp(
2152 bgp
, pi2
, new_select
,
2153 &paths_eq
, mpath_cfg
, debug
,
2156 bgp_path_info_unset_flag(
2158 BGP_PATH_DMED_SELECTED
);
2162 bgp_path_info_set_flag(
2163 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2166 bgp_path_info_set_flag(rn
, new_select
,
2167 BGP_PATH_DMED_CHECK
);
2168 bgp_path_info_set_flag(rn
, new_select
,
2169 BGP_PATH_DMED_SELECTED
);
2172 bgp_path_info_path_with_addpath_rx_str(
2173 new_select
, path_buf
);
2174 zlog_debug("%s: %s is the bestpath from AS %u",
2176 aspath_get_first_as(
2177 new_select
->attr
->aspath
));
2182 /* Check old selected route and new selected route. */
2185 for (pi
= bgp_node_get_bgp_path_info(rn
);
2186 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2187 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2190 if (BGP_PATH_HOLDDOWN(pi
)) {
2191 /* reap REMOVED routes, if needs be
2192 * selected route must stay for a while longer though
2194 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2195 && (pi
!= old_select
))
2196 bgp_path_info_reap(rn
, pi
);
2199 zlog_debug("%s: pi %p in holddown", __func__
,
2205 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2206 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2207 if (pi
->peer
->status
!= Established
) {
2211 "%s: pi %p non self peer %s not estab state",
2212 __func__
, pi
, pi
->peer
->host
);
2217 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2218 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2219 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2221 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2225 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2227 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2228 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2233 /* Now that we know which path is the bestpath see if any of the other
2235 * qualify as multipaths
2239 bgp_path_info_path_with_addpath_rx_str(new_select
,
2242 sprintf(path_buf
, "NONE");
2244 "%s: After path selection, newbest is %s oldbest was %s",
2246 old_select
? old_select
->peer
->host
: "NONE");
2249 if (do_mpath
&& new_select
) {
2250 for (pi
= bgp_node_get_bgp_path_info(rn
);
2251 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2254 bgp_path_info_path_with_addpath_rx_str(
2257 if (pi
== new_select
) {
2260 "%s: %s is the bestpath, add to the multipath list",
2262 bgp_mp_list_add(&mp_list
, pi
);
2266 if (BGP_PATH_HOLDDOWN(pi
))
2269 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2270 && !CHECK_FLAG(pi
->peer
->sflags
,
2271 PEER_STATUS_NSF_WAIT
))
2272 if (pi
->peer
->status
!= Established
)
2275 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2278 "%s: %s has the same nexthop as the bestpath, skip it",
2283 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2284 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2290 "%s: %s is equivalent to the bestpath, add to the multipath list",
2292 bgp_mp_list_add(&mp_list
, pi
);
2297 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2299 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2300 bgp_mp_list_clear(&mp_list
);
2302 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2304 result
->old
= old_select
;
2305 result
->new = new_select
;
2311 * A new route/change in bestpath of an existing route. Evaluate the path
2312 * for advertisement to the subgroup.
2314 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2315 struct bgp_path_info
*selected
,
2316 struct bgp_node
*rn
,
2317 uint32_t addpath_tx_id
)
2320 struct peer
*onlypeer
;
2326 afi
= SUBGRP_AFI(subgrp
);
2327 safi
= SUBGRP_SAFI(subgrp
);
2328 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2331 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2332 char buf_prefix
[PREFIX_STRLEN
];
2333 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2334 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2338 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2339 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2340 PEER_STATUS_ORF_WAIT_REFRESH
))
2343 memset(&attr
, 0, sizeof(struct attr
));
2344 /* It's initialized in bgp_announce_check() */
2346 /* Announcement to the subgroup. If the route is filtered withdraw it.
2349 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2350 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2352 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2356 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2358 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 int 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
;
2447 char pfx_buf
[PREFIX2STR_BUFFER
];
2450 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2452 debug
= bgp_debug_bestpath(&rn
->p
);
2454 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2456 "%s: bgp delete in progress, ignoring event, p=%s",
2461 /* Is it end of initial update? (after startup) */
2463 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2464 sizeof(bgp
->update_delay_zebra_resume_time
));
2466 bgp
->main_zebra_update_hold
= 0;
2467 FOREACH_AFI_SAFI (afi
, safi
) {
2468 if (bgp_fibupd_safi(safi
))
2469 bgp_zebra_announce_table(bgp
, afi
, safi
);
2471 bgp
->main_peers_update_hold
= 0;
2473 bgp_start_routeadv(bgp
);
2477 struct prefix
*p
= &rn
->p
;
2479 debug
= bgp_debug_bestpath(&rn
->p
);
2481 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2482 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2483 afi2str(afi
), safi2str(safi
));
2486 /* The best path calculation for the route is deferred if
2487 * BGP_NODE_SELECT_DEFER is set
2489 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2490 if (BGP_DEBUG(update
, UPDATE_OUT
))
2491 zlog_debug("SELECT_DEFER falg set for route %p", rn
);
2495 /* Best path selection. */
2496 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2498 old_select
= old_and_new
.old
;
2499 new_select
= old_and_new
.new;
2501 /* Do we need to allocate or free labels?
2502 * Right now, since we only deal with per-prefix labels, it is not
2503 * necessary to do this upon changes to best path. Exceptions:
2504 * - label index has changed -> recalculate resulting label
2505 * - path_info sub_type changed -> switch to/from implicit-null
2506 * - no valid label (due to removed static label binding) -> get new one
2508 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2511 || bgp_label_index_differs(new_select
, old_select
)
2512 || new_select
->sub_type
!= old_select
->sub_type
2513 || !bgp_is_valid_label(&rn
->local_label
)) {
2514 /* Enforced penultimate hop popping:
2515 * implicit-null for local routes, aggregate
2516 * and redistributed routes
2518 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2519 || new_select
->sub_type
2520 == BGP_ROUTE_AGGREGATE
2521 || new_select
->sub_type
2522 == BGP_ROUTE_REDISTRIBUTE
) {
2525 BGP_NODE_REGISTERED_FOR_LABEL
))
2526 bgp_unregister_for_label(rn
);
2527 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2529 bgp_set_valid_label(&rn
->local_label
);
2531 bgp_register_for_label(rn
, new_select
);
2533 } else if (CHECK_FLAG(rn
->flags
,
2534 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2535 bgp_unregister_for_label(rn
);
2537 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2538 bgp_unregister_for_label(rn
);
2542 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2544 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2545 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2546 old_select
, new_select
);
2549 /* If best route remains the same and this is not due to user-initiated
2550 * clear, see exactly what needs to be done.
2552 if (old_select
&& old_select
== new_select
2553 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2554 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2555 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2556 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2558 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2559 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2561 if (bgp_fibupd_safi(safi
)
2562 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2564 if (new_select
->type
== ZEBRA_ROUTE_BGP
2565 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2566 || new_select
->sub_type
2567 == BGP_ROUTE_IMPORTED
))
2569 bgp_zebra_announce(rn
, p
, old_select
,
2573 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2574 bgp_zebra_clear_route_change_flags(rn
);
2576 /* If there is a change of interest to peers, reannounce the
2578 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2579 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2580 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2582 /* unicast routes must also be annouced to
2583 * labeled-unicast update-groups */
2584 if (safi
== SAFI_UNICAST
)
2585 group_announce_route(bgp
, afi
,
2586 SAFI_LABELED_UNICAST
, rn
,
2589 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2590 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2593 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2597 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2599 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2601 /* bestpath has changed; bump version */
2602 if (old_select
|| new_select
) {
2603 bgp_bump_version(rn
);
2605 if (!bgp
->t_rmap_def_originate_eval
) {
2609 update_group_refresh_default_originate_route_map
,
2610 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2611 &bgp
->t_rmap_def_originate_eval
);
2616 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2619 zlog_debug("%s: setting SELECTED flag", __func__
);
2620 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2621 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2622 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2626 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2627 if (old_select
!= new_select
) {
2629 vnc_import_bgp_exterior_del_route(bgp
, p
,
2631 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2634 vnc_import_bgp_exterior_add_route(bgp
, p
,
2636 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2642 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2644 /* unicast routes must also be annouced to labeled-unicast update-groups
2646 if (safi
== SAFI_UNICAST
)
2647 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2651 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2652 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2653 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2654 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2655 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2656 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2658 /* if this is an evpn imported type-5 prefix,
2659 * we need to withdraw the route first to clear
2660 * the nh neigh and the RMAC entry.
2663 is_route_parent_evpn(old_select
))
2664 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2666 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2668 /* Withdraw the route from the kernel. */
2669 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2670 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2671 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2672 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2674 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2678 /* advertise/withdraw type-5 routes */
2679 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2680 if (advertise_type5_routes(bgp
, afi
) &&
2682 is_route_injectable_into_evpn(new_select
)) {
2684 /* apply the route-map */
2685 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2686 route_map_result_t ret
;
2688 ret
= route_map_apply(
2689 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2690 &rn
->p
, RMAP_BGP
, new_select
);
2691 if (ret
== RMAP_PERMITMATCH
)
2692 bgp_evpn_advertise_type5_route(
2693 bgp
, &rn
->p
, new_select
->attr
,
2696 bgp_evpn_withdraw_type5_route(
2697 bgp
, &rn
->p
, afi
, safi
);
2699 bgp_evpn_advertise_type5_route(bgp
,
2705 } else if (advertise_type5_routes(bgp
, afi
) &&
2707 is_route_injectable_into_evpn(old_select
))
2708 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2711 /* Clear any route change flags. */
2712 bgp_zebra_clear_route_change_flags(rn
);
2714 /* Reap old select bgp_path_info, if it has been removed */
2715 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2716 bgp_path_info_reap(rn
, old_select
);
2718 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2722 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2723 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2725 struct bgp_node
*rn
;
2727 struct afi_safi_info
*thread_info
;
2728 struct listnode
*node
= NULL
, *nnode
= NULL
;
2730 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2731 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2733 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2734 zlog_debug("%s: processing route for %s : cnt %d", __func__
,
2735 get_afi_safi_str(afi
, safi
, false),
2736 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2739 /* Process the route list */
2740 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2742 rn
= listgetdata(node
);
2744 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2747 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2748 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
2749 bgp_process_main_one(bgp
, rn
, afi
, safi
);
2751 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2757 /* Send EOR message when all routes are processed */
2758 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2759 bgp_send_delayed_eor(bgp
);
2760 /* Send route processing complete message to RIB */
2761 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2762 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2766 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2768 thread_info
->afi
= afi
;
2769 thread_info
->safi
= safi
;
2770 thread_info
->bgp
= bgp
;
2772 /* If there are more routes to be processed, start the
2775 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2776 BGP_ROUTE_SELECT_DELAY
,
2777 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2781 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2783 struct bgp_process_queue
*pqnode
= data
;
2784 struct bgp
*bgp
= pqnode
->bgp
;
2785 struct bgp_table
*table
;
2786 struct bgp_node
*rn
;
2789 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2790 bgp_process_main_one(bgp
, NULL
, 0, 0);
2791 /* should always have dedicated wq call */
2792 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2796 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2797 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2798 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2799 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2800 table
= bgp_node_table(rn
);
2801 /* note, new RNs may be added as part of processing */
2802 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2804 bgp_unlock_node(rn
);
2805 bgp_table_unlock(table
);
2811 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2813 struct bgp_process_queue
*pqnode
= data
;
2815 bgp_unlock(pqnode
->bgp
);
2817 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2820 void bgp_process_queue_init(void)
2822 if (!bm
->process_main_queue
)
2823 bm
->process_main_queue
=
2824 work_queue_new(bm
->master
, "process_main_queue");
2826 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2827 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2828 bm
->process_main_queue
->spec
.max_retries
= 0;
2829 bm
->process_main_queue
->spec
.hold
= 50;
2830 /* Use a higher yield value of 50ms for main queue processing */
2831 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2834 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2836 struct bgp_process_queue
*pqnode
;
2838 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2839 sizeof(struct bgp_process_queue
));
2841 /* unlocked in bgp_processq_del */
2842 pqnode
->bgp
= bgp_lock(bgp
);
2843 STAILQ_INIT(&pqnode
->pqueue
);
2848 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2850 #define ARBITRARY_PROCESS_QLEN 10000
2851 struct work_queue
*wq
= bm
->process_main_queue
;
2852 struct bgp_process_queue
*pqnode
;
2853 int pqnode_reuse
= 0;
2855 /* already scheduled for processing? */
2856 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2859 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2862 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2863 if (BGP_DEBUG(update
, UPDATE_OUT
))
2864 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2872 /* Add route nodes to an existing work queue item until reaching the
2873 limit only if is from the same BGP view and it's not an EOIU marker
2875 if (work_queue_item_count(wq
)) {
2876 struct work_queue_item
*item
= work_queue_last_item(wq
);
2877 pqnode
= item
->data
;
2879 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2880 || pqnode
->bgp
!= bgp
2881 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2882 pqnode
= bgp_processq_alloc(bgp
);
2886 pqnode
= bgp_processq_alloc(bgp
);
2887 /* all unlocked in bgp_process_wq */
2888 bgp_table_lock(bgp_node_table(rn
));
2890 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2893 /* can't be enqueued twice */
2894 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2895 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2899 work_queue_add(wq
, pqnode
);
2904 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2906 struct bgp_process_queue
*pqnode
;
2908 if (bm
->process_main_queue
== NULL
)
2911 pqnode
= bgp_processq_alloc(bgp
);
2913 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2914 work_queue_add(bm
->process_main_queue
, pqnode
);
2917 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2921 peer
= THREAD_ARG(thread
);
2922 peer
->t_pmax_restart
= NULL
;
2924 if (bgp_debug_neighbor_events(peer
))
2926 "%s Maximum-prefix restart timer expired, restore peering",
2929 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2930 zlog_debug("%s: %s peer_clear failed",
2931 __PRETTY_FUNCTION__
, peer
->host
);
2936 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2940 iana_safi_t pkt_safi
;
2942 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2945 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2946 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2947 PEER_STATUS_PREFIX_LIMIT
)
2952 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2953 " exceed, limit %" PRIu32
,
2954 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2955 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2956 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2958 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2959 PEER_FLAG_MAX_PREFIX_WARNING
))
2962 /* Convert AFI, SAFI to values for packet. */
2963 pkt_afi
= afi_int2iana(afi
);
2964 pkt_safi
= safi_int2iana(safi
);
2968 ndata
[0] = (pkt_afi
>> 8);
2970 ndata
[2] = pkt_safi
;
2971 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2972 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2973 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2974 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2976 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2977 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2978 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2982 /* Dynamic peers will just close their connection. */
2983 if (peer_dynamic_neighbor(peer
))
2986 /* restart timer start */
2987 if (peer
->pmax_restart
[afi
][safi
]) {
2988 peer
->v_pmax_restart
=
2989 peer
->pmax_restart
[afi
][safi
] * 60;
2991 if (bgp_debug_neighbor_events(peer
))
2993 "%s Maximum-prefix restart timer started for %d secs",
2994 peer
->host
, peer
->v_pmax_restart
);
2996 BGP_TIMER_ON(peer
->t_pmax_restart
,
2997 bgp_maximum_prefix_restart_timer
,
2998 peer
->v_pmax_restart
);
3003 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3004 PEER_STATUS_PREFIX_LIMIT
);
3006 if (peer
->pcount
[afi
][safi
]
3007 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3008 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3009 PEER_STATUS_PREFIX_THRESHOLD
)
3014 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3016 get_afi_safi_str(afi
, safi
, false), peer
->host
,
3017 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
3018 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3019 PEER_STATUS_PREFIX_THRESHOLD
);
3021 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3022 PEER_STATUS_PREFIX_THRESHOLD
);
3026 /* Unconditionally remove the route from the RIB, without taking
3027 * damping into consideration (eg, because the session went down)
3029 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3030 struct peer
*peer
, afi_t afi
, safi_t safi
)
3033 struct bgp
*bgp
= NULL
;
3034 bool delete_route
= false;
3036 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
3038 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3039 bgp_path_info_delete(rn
, pi
); /* keep historical info */
3041 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3044 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3045 delete_route
= true;
3046 else if (bgp_node_set_defer_flag(rn
, true) < 0)
3047 delete_route
= true;
3049 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
3050 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
3051 bgp
= pi
->peer
->bgp
;
3053 && (bgp
->gr_info
[afi
][safi
].route_list
)) {
3054 list_delete_node(bgp
->gr_info
[afi
][safi
]
3063 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
3064 bgp_process(peer
->bgp
, rn
, afi
, safi
);
3067 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3068 struct peer
*peer
, afi_t afi
, safi_t safi
,
3069 struct prefix_rd
*prd
)
3071 /* apply dampening, if result is suppressed, we'll be retaining
3072 * the bgp_path_info in the RIB for historical reference.
3074 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3075 && peer
->sort
== BGP_PEER_EBGP
)
3076 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
3077 == BGP_DAMP_SUPPRESSED
) {
3078 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
3084 if (safi
== SAFI_MPLS_VPN
) {
3085 struct bgp_node
*prn
= NULL
;
3086 struct bgp_table
*table
= NULL
;
3088 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3089 (struct prefix
*)prd
);
3090 if (bgp_node_has_bgp_path_info_data(prn
)) {
3091 table
= bgp_node_get_bgp_table_info(prn
);
3093 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3094 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
3096 bgp_unlock_node(prn
);
3098 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3099 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3101 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
3102 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
3108 /* If this is an EVPN route, process for un-import. */
3109 if (safi
== SAFI_EVPN
)
3110 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
3112 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3115 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3116 struct peer
*peer
, struct attr
*attr
,
3117 struct bgp_node
*rn
)
3119 struct bgp_path_info
*new;
3121 /* Make new BGP info. */
3122 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3124 new->instance
= instance
;
3125 new->sub_type
= sub_type
;
3128 new->uptime
= bgp_clock();
3133 static void overlay_index_update(struct attr
*attr
,
3134 struct eth_segment_id
*eth_s_id
,
3135 union gw_addr
*gw_ip
)
3140 if (eth_s_id
== NULL
) {
3141 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
3142 sizeof(struct eth_segment_id
));
3144 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
3145 sizeof(struct eth_segment_id
));
3147 if (gw_ip
== NULL
) {
3148 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3150 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3151 sizeof(union gw_addr
));
3155 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3156 struct eth_segment_id
*eth_s_id
,
3157 union gw_addr
*gw_ip
)
3159 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
3160 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3162 struct eth_segment_id esi
;
3166 if (afi
!= AFI_L2VPN
)
3169 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
3170 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3172 if (gw_ip
== NULL
) {
3173 memset(&temp
, 0, sizeof(temp
));
3174 path_gw_ip_remote
= &temp
.ip
;
3176 path_gw_ip_remote
= gw_ip
;
3178 if (eth_s_id
== NULL
) {
3179 memset(&temp
, 0, sizeof(temp
));
3180 path_eth_s_id_remote
= &temp
.esi
;
3182 path_eth_s_id_remote
= eth_s_id
;
3184 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
3187 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
3188 sizeof(struct eth_segment_id
));
3191 /* Check if received nexthop is valid or not. */
3192 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3193 uint8_t type
, uint8_t stype
,
3194 struct attr
*attr
, struct bgp_node
*rn
)
3198 /* Only validated for unicast and multicast currently. */
3199 /* Also valid for EVPN where the nexthop is an IP address. */
3200 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3203 /* If NEXT_HOP is present, validate it. */
3204 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3205 if (attr
->nexthop
.s_addr
== 0
3206 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3207 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3212 /* If MP_NEXTHOP is present, validate it. */
3213 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3214 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3215 * it is not an IPv6 link-local address.
3217 if (attr
->mp_nexthop_len
) {
3218 switch (attr
->mp_nexthop_len
) {
3219 case BGP_ATTR_NHLEN_IPV4
:
3220 case BGP_ATTR_NHLEN_VPNV4
:
3221 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3222 || IPV4_CLASS_DE(ntohl(
3223 attr
->mp_nexthop_global_in
.s_addr
))
3224 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3228 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3229 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3230 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3231 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3232 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3233 || IN6_IS_ADDR_MULTICAST(
3234 &attr
->mp_nexthop_global
)
3235 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3248 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3249 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3250 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3251 uint32_t num_labels
, int soft_reconfig
,
3252 struct bgp_route_evpn
*evpn
)
3255 int aspath_loop_count
= 0;
3256 struct bgp_node
*rn
;
3258 struct attr new_attr
;
3259 struct attr
*attr_new
;
3260 struct bgp_path_info
*pi
;
3261 struct bgp_path_info
*new;
3262 struct bgp_path_info_extra
*extra
;
3264 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3266 int do_loop_check
= 1;
3267 int has_valid_label
= 0;
3269 uint8_t pi_type
= 0;
3270 uint8_t pi_sub_type
= 0;
3273 int vnc_implicit_withdraw
= 0;
3277 memset(&new_attr
, 0, sizeof(struct attr
));
3278 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3279 new_attr
.label
= MPLS_INVALID_LABEL
;
3282 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3283 /* TODO: Check to see if we can get rid of "is_valid_label" */
3284 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3285 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3287 has_valid_label
= bgp_is_valid_label(label
);
3289 /* When peer's soft reconfiguration enabled. Record input packet in
3292 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3293 && peer
!= bgp
->peer_self
)
3294 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3296 /* Check previously received route. */
3297 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3298 if (pi
->peer
== peer
&& pi
->type
== type
3299 && pi
->sub_type
== sub_type
3300 && pi
->addpath_rx_id
== addpath_id
)
3303 /* AS path local-as loop check. */
3304 if (peer
->change_local_as
) {
3305 if (peer
->allowas_in
[afi
][safi
])
3306 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3307 else if (!CHECK_FLAG(peer
->flags
,
3308 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3309 aspath_loop_count
= 1;
3311 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3312 > aspath_loop_count
) {
3313 peer
->stat_pfx_aspath_loop
++;
3314 reason
= "as-path contains our own AS;";
3319 /* If the peer is configured for "allowas-in origin" and the last ASN in
3321 * as-path is our ASN then we do not need to call aspath_loop_check
3323 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3324 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3327 /* AS path loop check. */
3328 if (do_loop_check
) {
3329 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3330 > peer
->allowas_in
[afi
][safi
]
3331 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3332 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3333 > peer
->allowas_in
[afi
][safi
])) {
3334 peer
->stat_pfx_aspath_loop
++;
3335 reason
= "as-path contains our own AS;";
3340 /* Route reflector originator ID check. */
3341 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3342 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3343 peer
->stat_pfx_originator_loop
++;
3344 reason
= "originator is us;";
3348 /* Route reflector cluster ID check. */
3349 if (bgp_cluster_filter(peer
, attr
)) {
3350 peer
->stat_pfx_cluster_loop
++;
3351 reason
= "reflected from the same cluster;";
3355 /* Apply incoming filter. */
3356 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3357 peer
->stat_pfx_filter
++;
3362 /* RFC 8212 to prevent route leaks.
3363 * This specification intends to improve this situation by requiring the
3364 * explicit configuration of both BGP Import and Export Policies for any
3365 * External BGP (EBGP) session such as customers, peers, or
3366 * confederation boundaries for all enabled address families. Through
3367 * codification of the aforementioned requirement, operators will
3368 * benefit from consistent behavior across different BGP
3371 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3372 if (!bgp_inbound_policy_exists(peer
,
3373 &peer
->filter
[afi
][safi
])) {
3374 reason
= "inbound policy missing";
3378 /* draft-ietf-idr-deprecate-as-set-confed-set
3379 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3380 * Eventually, This document (if approved) updates RFC 4271
3381 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3382 * and obsoletes RFC 6472.
3384 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3385 if (aspath_check_as_sets(attr
->aspath
)) {
3387 "as-path contains AS_SET or AS_CONFED_SET type;";
3393 /* Apply incoming route-map.
3394 * NB: new_attr may now contain newly allocated values from route-map
3396 * commands, so we need bgp_attr_flush in the error paths, until we
3398 * the attr (which takes over the memory references) */
3399 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3400 label
, num_labels
, rn
) == RMAP_DENY
) {
3401 peer
->stat_pfx_filter
++;
3402 reason
= "route-map;";
3403 bgp_attr_flush(&new_attr
);
3407 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3408 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3409 /* remove from RIB previous entry */
3410 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3413 if (peer
->sort
== BGP_PEER_EBGP
) {
3415 /* If we receive the graceful-shutdown community from an eBGP
3416 * peer we must lower local-preference */
3417 if (new_attr
.community
3418 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3419 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3420 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3422 /* If graceful-shutdown is configured then add the GSHUT
3423 * community to all paths received from eBGP peers */
3424 } else if (bgp_flag_check(peer
->bgp
,
3425 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3426 bgp_attr_add_gshut_community(&new_attr
);
3432 pi_sub_type
= pi
->sub_type
;
3435 /* next hop check. */
3436 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3437 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3438 pi_sub_type
, &new_attr
, rn
)) {
3439 peer
->stat_pfx_nh_invalid
++;
3440 reason
= "martian or self next-hop;";
3441 bgp_attr_flush(&new_attr
);
3445 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3446 peer
->stat_pfx_nh_invalid
++;
3447 reason
= "self mac;";
3451 attr_new
= bgp_attr_intern(&new_attr
);
3453 /* If the update is implicit withdraw. */
3455 pi
->uptime
= bgp_clock();
3456 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3458 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3460 /* Same attribute comes in. */
3461 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3462 && attrhash_cmp(pi
->attr
, attr_new
)
3463 && (!has_valid_label
3464 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3465 num_labels
* sizeof(mpls_label_t
))
3467 && (overlay_index_equal(
3468 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3469 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3470 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3471 BGP_CONFIG_DAMPENING
)
3472 && peer
->sort
== BGP_PEER_EBGP
3473 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3474 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3475 bgp_debug_rdpfxpath2str(
3476 afi
, safi
, prd
, p
, label
,
3477 num_labels
, addpath_id
? 1 : 0,
3478 addpath_id
, pfx_buf
,
3480 zlog_debug("%s rcvd %s", peer
->host
,
3484 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3485 != BGP_DAMP_SUPPRESSED
) {
3486 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3488 bgp_process(bgp
, rn
, afi
, safi
);
3490 } else /* Duplicate - odd */
3492 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3493 if (!peer
->rcvd_attr_printed
) {
3495 "%s rcvd UPDATE w/ attr: %s",
3497 peer
->rcvd_attr_str
);
3498 peer
->rcvd_attr_printed
= 1;
3501 bgp_debug_rdpfxpath2str(
3502 afi
, safi
, prd
, p
, label
,
3503 num_labels
, addpath_id
? 1 : 0,
3504 addpath_id
, pfx_buf
,
3507 "%s rcvd %s...duplicate ignored",
3508 peer
->host
, pfx_buf
);
3511 /* graceful restart STALE flag unset. */
3512 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3513 bgp_path_info_unset_flag(
3514 rn
, pi
, BGP_PATH_STALE
);
3515 bgp_node_set_defer_flag(rn
, false);
3516 bgp_process(bgp
, rn
, afi
, safi
);
3520 bgp_unlock_node(rn
);
3521 bgp_attr_unintern(&attr_new
);
3526 /* Withdraw/Announce before we fully processed the withdraw */
3527 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3528 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3529 bgp_debug_rdpfxpath2str(
3530 afi
, safi
, prd
, p
, label
, num_labels
,
3531 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3534 "%s rcvd %s, flapped quicker than processing",
3535 peer
->host
, pfx_buf
);
3538 bgp_path_info_restore(rn
, pi
);
3541 /* Received Logging. */
3542 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3543 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3544 num_labels
, addpath_id
? 1 : 0,
3545 addpath_id
, pfx_buf
,
3547 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3550 /* graceful restart STALE flag unset. */
3551 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3552 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3553 bgp_node_set_defer_flag(rn
, false);
3556 /* The attribute is changed. */
3557 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3559 /* implicit withdraw, decrement aggregate and pcount here.
3560 * only if update is accepted, they'll increment below.
3562 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3564 /* Update bgp route dampening information. */
3565 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3566 && peer
->sort
== BGP_PEER_EBGP
) {
3567 /* This is implicit withdraw so we should update
3570 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3571 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3574 if (safi
== SAFI_MPLS_VPN
) {
3575 struct bgp_node
*prn
= NULL
;
3576 struct bgp_table
*table
= NULL
;
3578 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3579 (struct prefix
*)prd
);
3580 if (bgp_node_has_bgp_path_info_data(prn
)) {
3581 table
= bgp_node_get_bgp_table_info(prn
);
3583 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3584 bgp
, prd
, table
, p
, pi
);
3586 bgp_unlock_node(prn
);
3588 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3589 && (safi
== SAFI_UNICAST
)) {
3590 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3592 * Implicit withdraw case.
3594 ++vnc_implicit_withdraw
;
3595 vnc_import_bgp_del_route(bgp
, p
, pi
);
3596 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3601 /* Special handling for EVPN update of an existing route. If the
3602 * extended community attribute has changed, we need to
3604 * the route using its existing extended community. It will be
3605 * subsequently processed for import with the new extended
3608 if (safi
== SAFI_EVPN
&& !same_attr
) {
3610 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3612 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3615 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3616 attr_new
->ecommunity
);
3618 if (bgp_debug_update(peer
, p
, NULL
, 1))
3620 "Change in EXT-COMM, existing %s new %s",
3622 pi
->attr
->ecommunity
),
3624 attr_new
->ecommunity
));
3625 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3631 /* Update to new attribute. */
3632 bgp_attr_unintern(&pi
->attr
);
3633 pi
->attr
= attr_new
;
3635 /* Update MPLS label */
3636 if (has_valid_label
) {
3637 extra
= bgp_path_info_extra_get(pi
);
3638 if (extra
->label
!= label
) {
3639 memcpy(&extra
->label
, label
,
3640 num_labels
* sizeof(mpls_label_t
));
3641 extra
->num_labels
= num_labels
;
3643 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3644 bgp_set_valid_label(&extra
->label
[0]);
3647 /* Update SRv6 SID */
3648 if (attr
->srv6_l3vpn
) {
3649 extra
= bgp_path_info_extra_get(pi
);
3650 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3651 sid_copy(&extra
->sid
[0],
3652 &attr
->srv6_l3vpn
->sid
);
3653 extra
->num_sids
= 1;
3655 } else if (attr
->srv6_vpn
) {
3656 extra
= bgp_path_info_extra_get(pi
);
3657 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3658 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3659 extra
->num_sids
= 1;
3664 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3665 && (safi
== SAFI_UNICAST
)) {
3666 if (vnc_implicit_withdraw
) {
3668 * Add back the route with its new attributes
3670 * The route is still selected, until the route
3672 * queued by bgp_process actually runs. We have
3674 * update to the VNC side immediately to avoid
3676 * configuration changes (e.g., route-map
3678 * trigger re-importation of the entire RIB.
3680 vnc_import_bgp_add_route(bgp
, p
, pi
);
3681 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3685 /* Update Overlay Index */
3686 if (afi
== AFI_L2VPN
) {
3687 overlay_index_update(
3688 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3689 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3692 /* Update bgp route dampening information. */
3693 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3694 && peer
->sort
== BGP_PEER_EBGP
) {
3695 /* Now we do normal update dampening. */
3696 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3697 if (ret
== BGP_DAMP_SUPPRESSED
) {
3698 bgp_unlock_node(rn
);
3703 /* Nexthop reachability check - for unicast and
3704 * labeled-unicast.. */
3705 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3706 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3707 || (safi
== SAFI_EVPN
&&
3708 bgp_evpn_is_prefix_nht_supported(p
))) {
3709 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3710 && peer
->ttl
== BGP_DEFAULT_TTL
3711 && !CHECK_FLAG(peer
->flags
,
3712 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3714 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3719 struct bgp
*bgp_nexthop
= bgp
;
3721 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3722 bgp_nexthop
= pi
->extra
->bgp_orig
;
3724 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3726 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3727 pi
, NULL
, connected
)
3728 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3729 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3731 if (BGP_DEBUG(nht
, NHT
)) {
3732 char buf1
[INET6_ADDRSTRLEN
];
3734 (const void *)&attr_new
3736 buf1
, INET6_ADDRSTRLEN
);
3737 zlog_debug("%s(%s): NH unresolved",
3738 __FUNCTION__
, buf1
);
3740 bgp_path_info_unset_flag(rn
, pi
,
3744 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3747 if (safi
== SAFI_MPLS_VPN
) {
3748 struct bgp_node
*prn
= NULL
;
3749 struct bgp_table
*table
= NULL
;
3751 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3752 (struct prefix
*)prd
);
3753 if (bgp_node_has_bgp_path_info_data(prn
)) {
3754 table
= bgp_node_get_bgp_table_info(prn
);
3756 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3757 bgp
, prd
, table
, p
, pi
);
3759 bgp_unlock_node(prn
);
3763 /* If this is an EVPN route and some attribute has changed,
3765 * route for import. If the extended community has changed, we
3767 * have done the un-import earlier and the import would result
3769 * route getting injected into appropriate L2 VNIs. If it is
3771 * some other attribute change, the import will result in
3773 * the attributes for the route in the VNI(s).
3775 if (safi
== SAFI_EVPN
&& !same_attr
&&
3776 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3777 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3779 /* Process change. */
3780 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3782 bgp_process(bgp
, rn
, afi
, safi
);
3783 bgp_unlock_node(rn
);
3785 if (SAFI_UNICAST
== safi
3786 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3787 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3789 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3791 if ((SAFI_MPLS_VPN
== safi
)
3792 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3794 vpn_leak_to_vrf_update(bgp
, pi
);
3798 if (SAFI_MPLS_VPN
== safi
) {
3799 mpls_label_t label_decoded
= decode_label(label
);
3801 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3802 type
, sub_type
, &label_decoded
);
3804 if (SAFI_ENCAP
== safi
) {
3805 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3806 type
, sub_type
, NULL
);
3811 } // End of implicit withdraw
3813 /* Received Logging. */
3814 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3815 if (!peer
->rcvd_attr_printed
) {
3816 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3817 peer
->rcvd_attr_str
);
3818 peer
->rcvd_attr_printed
= 1;
3821 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3822 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3824 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3827 /* Make new BGP info. */
3828 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3830 /* Update MPLS label */
3831 if (has_valid_label
) {
3832 extra
= bgp_path_info_extra_get(new);
3833 if (extra
->label
!= label
) {
3834 memcpy(&extra
->label
, label
,
3835 num_labels
* sizeof(mpls_label_t
));
3836 extra
->num_labels
= num_labels
;
3838 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3839 bgp_set_valid_label(&extra
->label
[0]);
3842 /* Update SRv6 SID */
3843 if (safi
== SAFI_MPLS_VPN
) {
3844 extra
= bgp_path_info_extra_get(new);
3845 if (attr
->srv6_l3vpn
) {
3846 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
3847 extra
->num_sids
= 1;
3848 } else if (attr
->srv6_vpn
) {
3849 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3850 extra
->num_sids
= 1;
3854 /* Update Overlay Index */
3855 if (afi
== AFI_L2VPN
) {
3856 overlay_index_update(new->attr
,
3857 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3858 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3860 /* Nexthop reachability check. */
3861 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3862 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3863 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3864 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3865 && peer
->ttl
== BGP_DEFAULT_TTL
3866 && !CHECK_FLAG(peer
->flags
,
3867 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3868 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3873 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3875 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3877 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3878 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3880 if (BGP_DEBUG(nht
, NHT
)) {
3881 char buf1
[INET6_ADDRSTRLEN
];
3883 (const void *)&attr_new
->nexthop
,
3884 buf1
, INET6_ADDRSTRLEN
);
3885 zlog_debug("%s(%s): NH unresolved",
3886 __FUNCTION__
, buf1
);
3888 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3891 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3894 new->addpath_rx_id
= addpath_id
;
3896 /* Increment prefix */
3897 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3899 /* Register new BGP information. */
3900 bgp_path_info_add(rn
, new);
3902 /* route_node_get lock */
3903 bgp_unlock_node(rn
);
3906 if (safi
== SAFI_MPLS_VPN
) {
3907 struct bgp_node
*prn
= NULL
;
3908 struct bgp_table
*table
= NULL
;
3910 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3911 if (bgp_node_has_bgp_path_info_data(prn
)) {
3912 table
= bgp_node_get_bgp_table_info(prn
);
3914 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3915 bgp
, prd
, table
, p
, new);
3917 bgp_unlock_node(prn
);
3921 /* If maximum prefix count is configured and current prefix
3923 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3926 /* If this is an EVPN route, process for import. */
3927 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3928 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3930 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3932 /* Process change. */
3933 bgp_process(bgp
, rn
, afi
, safi
);
3935 if (SAFI_UNICAST
== safi
3936 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3937 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3938 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3940 if ((SAFI_MPLS_VPN
== safi
)
3941 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3943 vpn_leak_to_vrf_update(bgp
, new);
3946 if (SAFI_MPLS_VPN
== safi
) {
3947 mpls_label_t label_decoded
= decode_label(label
);
3949 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3950 sub_type
, &label_decoded
);
3952 if (SAFI_ENCAP
== safi
) {
3953 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3960 /* This BGP update is filtered. Log the reason then update BGP
3963 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3965 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3966 if (!peer
->rcvd_attr_printed
) {
3967 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3968 peer
->rcvd_attr_str
);
3969 peer
->rcvd_attr_printed
= 1;
3972 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3973 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3975 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3976 peer
->host
, pfx_buf
, reason
);
3980 /* If this is an EVPN route, un-import it as it is now filtered.
3982 if (safi
== SAFI_EVPN
)
3983 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3985 if (SAFI_UNICAST
== safi
3986 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3987 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3989 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3991 if ((SAFI_MPLS_VPN
== safi
)
3992 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3994 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3997 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4000 bgp_unlock_node(rn
);
4004 * Filtered update is treated as an implicit withdrawal (see
4006 * a few lines above)
4008 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4009 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4017 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
4018 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4019 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4020 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4023 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4024 struct bgp_node
*rn
;
4025 struct bgp_path_info
*pi
;
4028 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4029 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4037 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4039 /* If peer is soft reconfiguration enabled. Record input packet for
4040 * further calculation.
4042 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4043 * routes that are filtered. This tanks out Quagga RS pretty badly due
4045 * the iteration over all RS clients.
4046 * Since we need to remove the entry from adj_in anyway, do that first
4048 * if there was no entry, we don't need to do anything more.
4050 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4051 && peer
!= bgp
->peer_self
)
4052 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
4053 peer
->stat_pfx_dup_withdraw
++;
4055 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4056 bgp_debug_rdpfxpath2str(
4057 afi
, safi
, prd
, p
, label
, num_labels
,
4058 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4061 "%s withdrawing route %s not in adj-in",
4062 peer
->host
, pfx_buf
);
4064 bgp_unlock_node(rn
);
4068 /* Lookup withdrawn route. */
4069 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4070 if (pi
->peer
== peer
&& pi
->type
== type
4071 && pi
->sub_type
== sub_type
4072 && pi
->addpath_rx_id
== addpath_id
)
4076 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4077 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4078 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4080 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4084 /* Withdraw specified route from routing table. */
4085 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4086 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
4087 if (SAFI_UNICAST
== safi
4088 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4089 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4090 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4092 if ((SAFI_MPLS_VPN
== safi
)
4093 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4095 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4097 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4098 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4099 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4101 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4104 /* Unlock bgp_node_get() lock. */
4105 bgp_unlock_node(rn
);
4110 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4113 struct update_subgroup
*subgrp
;
4114 subgrp
= peer_subgroup(peer
, afi
, safi
);
4115 subgroup_default_originate(subgrp
, withdraw
);
4120 * bgp_stop_announce_route_timer
4122 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4124 if (!paf
->t_announce_route
)
4127 THREAD_TIMER_OFF(paf
->t_announce_route
);
4131 * bgp_announce_route_timer_expired
4133 * Callback that is invoked when the route announcement timer for a
4136 static int bgp_announce_route_timer_expired(struct thread
*t
)
4138 struct peer_af
*paf
;
4141 paf
= THREAD_ARG(t
);
4144 if (peer
->status
!= Established
)
4147 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4150 peer_af_announce_route(paf
, 1);
4155 * bgp_announce_route
4157 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4159 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4161 struct peer_af
*paf
;
4162 struct update_subgroup
*subgrp
;
4164 paf
= peer_af_find(peer
, afi
, safi
);
4167 subgrp
= PAF_SUBGRP(paf
);
4170 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4171 * or a refresh has already been triggered.
4173 if (!subgrp
|| paf
->t_announce_route
)
4177 * Start a timer to stagger/delay the announce. This serves
4178 * two purposes - announcement can potentially be combined for
4179 * multiple peers and the announcement doesn't happen in the
4182 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4183 (subgrp
->peer_count
== 1)
4184 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4185 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4186 &paf
->t_announce_route
);
4190 * Announce routes from all AF tables to a peer.
4192 * This should ONLY be called when there is a need to refresh the
4193 * routes to the peer based on a policy change for this peer alone
4194 * or a route refresh request received from the peer.
4195 * The operation will result in splitting the peer from its existing
4196 * subgroups and putting it in new subgroups.
4198 void bgp_announce_route_all(struct peer
*peer
)
4203 FOREACH_AFI_SAFI (afi
, safi
)
4204 bgp_announce_route(peer
, afi
, safi
);
4207 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4208 struct bgp_table
*table
,
4209 struct prefix_rd
*prd
)
4212 struct bgp_node
*rn
;
4213 struct bgp_adj_in
*ain
;
4216 table
= peer
->bgp
->rib
[afi
][safi
];
4218 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4219 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
4220 if (ain
->peer
!= peer
)
4223 struct bgp_path_info
*pi
;
4224 uint32_t num_labels
= 0;
4225 mpls_label_t
*label_pnt
= NULL
;
4226 struct bgp_route_evpn evpn
;
4228 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4230 if (pi
->peer
== peer
)
4233 if (pi
&& pi
->extra
)
4234 num_labels
= pi
->extra
->num_labels
;
4236 label_pnt
= &pi
->extra
->label
[0];
4238 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4241 memset(&evpn
, 0, sizeof(evpn
));
4243 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
4244 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4245 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4246 num_labels
, 1, &evpn
);
4249 bgp_unlock_node(rn
);
4255 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4257 struct bgp_node
*rn
;
4258 struct bgp_table
*table
;
4260 if (peer
->status
!= Established
)
4263 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4264 && (safi
!= SAFI_EVPN
))
4265 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4267 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4268 rn
= bgp_route_next(rn
)) {
4269 table
= bgp_node_get_bgp_table_info(rn
);
4270 if (table
!= NULL
) {
4271 struct prefix_rd prd
;
4273 prd
.family
= AF_UNSPEC
;
4275 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4277 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4284 struct bgp_clear_node_queue
{
4285 struct bgp_node
*rn
;
4288 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4290 struct bgp_clear_node_queue
*cnq
= data
;
4291 struct bgp_node
*rn
= cnq
->rn
;
4292 struct peer
*peer
= wq
->spec
.data
;
4293 struct bgp_path_info
*pi
;
4295 afi_t afi
= bgp_node_table(rn
)->afi
;
4296 safi_t safi
= bgp_node_table(rn
)->safi
;
4301 /* It is possible that we have multiple paths for a prefix from a peer
4302 * if that peer is using AddPath.
4304 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4305 if (pi
->peer
!= peer
)
4308 /* graceful restart STALE flag set. */
4309 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4310 && peer
->nsf
[afi
][safi
]
4311 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4312 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4313 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4315 /* If this is an EVPN route, process for
4317 if (safi
== SAFI_EVPN
)
4318 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4320 /* Handle withdraw for VRF route-leaking and L3VPN */
4321 if (SAFI_UNICAST
== safi
4322 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4323 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4324 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4327 if (SAFI_MPLS_VPN
== safi
&&
4328 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4329 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4332 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4338 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4340 struct bgp_clear_node_queue
*cnq
= data
;
4341 struct bgp_node
*rn
= cnq
->rn
;
4342 struct bgp_table
*table
= bgp_node_table(rn
);
4344 bgp_unlock_node(rn
);
4345 bgp_table_unlock(table
);
4346 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4349 static void bgp_clear_node_complete(struct work_queue
*wq
)
4351 struct peer
*peer
= wq
->spec
.data
;
4353 /* Tickle FSM to start moving again */
4354 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4356 peer_unlock(peer
); /* bgp_clear_route */
4359 static void bgp_clear_node_queue_init(struct peer
*peer
)
4361 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4363 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4364 #undef CLEAR_QUEUE_NAME_LEN
4366 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4367 peer
->clear_node_queue
->spec
.hold
= 10;
4368 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4369 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4370 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4371 peer
->clear_node_queue
->spec
.max_retries
= 0;
4373 /* we only 'lock' this peer reference when the queue is actually active
4375 peer
->clear_node_queue
->spec
.data
= peer
;
4378 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4379 struct bgp_table
*table
)
4381 struct bgp_node
*rn
;
4382 int force
= bm
->process_main_queue
? 0 : 1;
4385 table
= peer
->bgp
->rib
[afi
][safi
];
4387 /* If still no table => afi/safi isn't configured at all or smth. */
4391 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4392 struct bgp_path_info
*pi
, *next
;
4393 struct bgp_adj_in
*ain
;
4394 struct bgp_adj_in
*ain_next
;
4396 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4397 * queued for every clearing peer, regardless of whether it is
4398 * relevant to the peer at hand.
4400 * Overview: There are 3 different indices which need to be
4401 * scrubbed, potentially, when a peer is removed:
4403 * 1 peer's routes visible via the RIB (ie accepted routes)
4404 * 2 peer's routes visible by the (optional) peer's adj-in index
4405 * 3 other routes visible by the peer's adj-out index
4407 * 3 there is no hurry in scrubbing, once the struct peer is
4408 * removed from bgp->peer, we could just GC such deleted peer's
4409 * adj-outs at our leisure.
4411 * 1 and 2 must be 'scrubbed' in some way, at least made
4412 * invisible via RIB index before peer session is allowed to be
4413 * brought back up. So one needs to know when such a 'search' is
4418 * - there'd be a single global queue or a single RIB walker
4419 * - rather than tracking which route_nodes still need to be
4420 * examined on a peer basis, we'd track which peers still
4423 * Given that our per-peer prefix-counts now should be reliable,
4424 * this may actually be achievable. It doesn't seem to be a huge
4425 * problem at this time,
4427 * It is possible that we have multiple paths for a prefix from
4429 * if that peer is using AddPath.
4433 ain_next
= ain
->next
;
4435 if (ain
->peer
== peer
) {
4436 bgp_adj_in_remove(rn
, ain
);
4437 bgp_unlock_node(rn
);
4443 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4445 if (pi
->peer
!= peer
)
4449 bgp_path_info_reap(rn
, pi
);
4451 struct bgp_clear_node_queue
*cnq
;
4453 /* both unlocked in bgp_clear_node_queue_del */
4454 bgp_table_lock(bgp_node_table(rn
));
4457 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4458 sizeof(struct bgp_clear_node_queue
));
4460 work_queue_add(peer
->clear_node_queue
, cnq
);
4468 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4470 struct bgp_node
*rn
;
4471 struct bgp_table
*table
;
4473 if (peer
->clear_node_queue
== NULL
)
4474 bgp_clear_node_queue_init(peer
);
4476 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4477 * Idle until it receives a Clearing_Completed event. This protects
4478 * against peers which flap faster than we can we clear, which could
4481 * a) race with routes from the new session being installed before
4482 * clear_route_node visits the node (to delete the route of that
4484 * b) resource exhaustion, clear_route_node likely leads to an entry
4485 * on the process_main queue. Fast-flapping could cause that queue
4489 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4490 * the unlock will happen upon work-queue completion; other wise, the
4491 * unlock happens at the end of this function.
4493 if (!peer
->clear_node_queue
->thread
)
4496 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4497 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4499 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4500 rn
= bgp_route_next(rn
)) {
4501 table
= bgp_node_get_bgp_table_info(rn
);
4505 bgp_clear_route_table(peer
, afi
, safi
, table
);
4508 /* unlock if no nodes got added to the clear-node-queue. */
4509 if (!peer
->clear_node_queue
->thread
)
4513 void bgp_clear_route_all(struct peer
*peer
)
4518 FOREACH_AFI_SAFI (afi
, safi
)
4519 bgp_clear_route(peer
, afi
, safi
);
4522 rfapiProcessPeerDown(peer
);
4526 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4528 struct bgp_table
*table
;
4529 struct bgp_node
*rn
;
4530 struct bgp_adj_in
*ain
;
4531 struct bgp_adj_in
*ain_next
;
4533 table
= peer
->bgp
->rib
[afi
][safi
];
4535 /* It is possible that we have multiple paths for a prefix from a peer
4536 * if that peer is using AddPath.
4538 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4542 ain_next
= ain
->next
;
4544 if (ain
->peer
== peer
) {
4545 bgp_adj_in_remove(rn
, ain
);
4546 bgp_unlock_node(rn
);
4554 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4556 struct bgp_node
*rn
;
4557 struct bgp_path_info
*pi
;
4558 struct bgp_table
*table
;
4560 if (safi
== SAFI_MPLS_VPN
) {
4561 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4562 rn
= bgp_route_next(rn
)) {
4563 struct bgp_node
*rm
;
4565 /* look for neighbor in tables */
4566 table
= bgp_node_get_bgp_table_info(rn
);
4570 for (rm
= bgp_table_top(table
); rm
;
4571 rm
= bgp_route_next(rm
))
4572 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4574 if (pi
->peer
!= peer
)
4576 if (!CHECK_FLAG(pi
->flags
,
4580 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4585 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4586 rn
= bgp_route_next(rn
))
4587 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4589 if (pi
->peer
!= peer
)
4591 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4593 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4599 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4601 if (peer
->sort
== BGP_PEER_IBGP
)
4604 if (peer
->sort
== BGP_PEER_EBGP
4605 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4606 || FILTER_LIST_OUT_NAME(filter
)
4607 || DISTRIBUTE_OUT_NAME(filter
)))
4612 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4614 if (peer
->sort
== BGP_PEER_IBGP
)
4617 if (peer
->sort
== BGP_PEER_EBGP
4618 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4619 || FILTER_LIST_IN_NAME(filter
)
4620 || DISTRIBUTE_IN_NAME(filter
)))
4625 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4628 struct bgp_node
*rn
;
4629 struct bgp_path_info
*pi
;
4630 struct bgp_path_info
*next
;
4632 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4633 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4636 /* Unimport EVPN routes from VRFs */
4637 if (safi
== SAFI_EVPN
)
4638 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4642 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4643 && pi
->type
== ZEBRA_ROUTE_BGP
4644 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4645 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4646 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4648 if (bgp_fibupd_safi(safi
))
4649 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4651 bgp_path_info_reap(rn
, pi
);
4656 /* Delete all kernel routes. */
4657 void bgp_cleanup_routes(struct bgp
*bgp
)
4660 struct bgp_node
*rn
;
4661 struct bgp_table
*table
;
4663 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4664 if (afi
== AFI_L2VPN
)
4666 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4669 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4671 if (afi
!= AFI_L2VPN
) {
4673 safi
= SAFI_MPLS_VPN
;
4674 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4675 rn
= bgp_route_next(rn
)) {
4676 table
= bgp_node_get_bgp_table_info(rn
);
4677 if (table
!= NULL
) {
4678 bgp_cleanup_table(bgp
, table
, safi
);
4679 bgp_table_finish(&table
);
4680 bgp_node_set_bgp_table_info(rn
, NULL
);
4681 bgp_unlock_node(rn
);
4685 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4686 rn
= bgp_route_next(rn
)) {
4687 table
= bgp_node_get_bgp_table_info(rn
);
4688 if (table
!= NULL
) {
4689 bgp_cleanup_table(bgp
, table
, safi
);
4690 bgp_table_finish(&table
);
4691 bgp_node_set_bgp_table_info(rn
, NULL
);
4692 bgp_unlock_node(rn
);
4697 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); 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_EVPN
);
4702 bgp_table_finish(&table
);
4703 bgp_node_set_bgp_table_info(rn
, NULL
);
4704 bgp_unlock_node(rn
);
4709 void bgp_reset(void)
4712 bgp_zclient_reset();
4713 access_list_reset();
4714 prefix_list_reset();
4717 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4719 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4720 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4721 PEER_CAP_ADDPATH_AF_TX_RCV
));
4724 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4726 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4727 struct bgp_nlri
*packet
)
4736 int addpath_encoded
;
4737 uint32_t addpath_id
;
4740 lim
= pnt
+ packet
->length
;
4742 safi
= packet
->safi
;
4744 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4746 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4747 syntactic validity. If the field is syntactically incorrect,
4748 then the Error Subcode is set to Invalid Network Field. */
4749 for (; pnt
< lim
; pnt
+= psize
) {
4750 /* Clear prefix structure. */
4751 memset(&p
, 0, sizeof(struct prefix
));
4753 if (addpath_encoded
) {
4755 /* When packet overflow occurs return immediately. */
4756 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4757 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4759 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4760 addpath_id
= ntohl(addpath_id
);
4761 pnt
+= BGP_ADDPATH_ID_LEN
;
4764 /* Fetch prefix length. */
4765 p
.prefixlen
= *pnt
++;
4766 /* afi/safi validity already verified by caller,
4767 * bgp_update_receive */
4768 p
.family
= afi2family(afi
);
4770 /* Prefix length check. */
4771 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4774 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4775 peer
->host
, p
.prefixlen
, packet
->afi
);
4776 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4779 /* Packet size overflow check. */
4780 psize
= PSIZE(p
.prefixlen
);
4782 /* When packet overflow occur return immediately. */
4783 if (pnt
+ psize
> lim
) {
4786 "%s [Error] Update packet error (prefix length %d overflows packet)",
4787 peer
->host
, p
.prefixlen
);
4788 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4791 /* Defensive coding, double-check the psize fits in a struct
4793 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4796 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4797 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4798 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4801 /* Fetch prefix from NLRI packet. */
4802 memcpy(p
.u
.val
, pnt
, psize
);
4804 /* Check address. */
4805 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4806 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4807 /* From RFC4271 Section 6.3:
4809 * If a prefix in the NLRI field is semantically
4811 * (e.g., an unexpected multicast IP address),
4813 * be logged locally, and the prefix SHOULD be
4818 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4819 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4824 /* Check address. */
4825 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4826 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4831 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4833 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4838 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4843 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4845 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4852 /* Normal process. */
4854 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4855 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4856 NULL
, NULL
, 0, 0, NULL
);
4858 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4859 safi
, ZEBRA_ROUTE_BGP
,
4860 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4863 /* Do not send BGP notification twice when maximum-prefix count
4865 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4866 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4868 /* Address family configuration mismatch. */
4870 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4873 /* Packet length consistency check. */
4877 "%s [Error] Update packet error (prefix length mismatch with total length)",
4879 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4882 return BGP_NLRI_PARSE_OK
;
4885 static struct bgp_static
*bgp_static_new(void)
4887 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4890 static void bgp_static_free(struct bgp_static
*bgp_static
)
4892 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4893 route_map_counter_decrement(bgp_static
->rmap
.map
);
4895 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4896 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4899 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4900 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4902 struct bgp_node
*rn
;
4903 struct bgp_path_info
*pi
;
4904 struct bgp_path_info
*new;
4905 struct bgp_path_info rmap_path
;
4907 struct attr
*attr_new
;
4908 route_map_result_t ret
;
4910 int vnc_implicit_withdraw
= 0;
4917 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4919 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4921 attr
.nexthop
= bgp_static
->igpnexthop
;
4922 attr
.med
= bgp_static
->igpmetric
;
4923 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4925 if (bgp_static
->atomic
)
4926 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4928 /* Store label index, if required. */
4929 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4930 attr
.label_index
= bgp_static
->label_index
;
4931 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4934 /* Apply route-map. */
4935 if (bgp_static
->rmap
.name
) {
4936 struct attr attr_tmp
= attr
;
4938 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4939 rmap_path
.peer
= bgp
->peer_self
;
4940 rmap_path
.attr
= &attr_tmp
;
4942 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4944 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4947 bgp
->peer_self
->rmap_type
= 0;
4949 if (ret
== RMAP_DENYMATCH
) {
4950 /* Free uninterned attribute. */
4951 bgp_attr_flush(&attr_tmp
);
4953 /* Unintern original. */
4954 aspath_unintern(&attr
.aspath
);
4955 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4959 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4960 bgp_attr_add_gshut_community(&attr_tmp
);
4962 attr_new
= bgp_attr_intern(&attr_tmp
);
4965 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4966 bgp_attr_add_gshut_community(&attr
);
4968 attr_new
= bgp_attr_intern(&attr
);
4971 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4972 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4973 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4977 if (attrhash_cmp(pi
->attr
, attr_new
)
4978 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4979 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4980 bgp_unlock_node(rn
);
4981 bgp_attr_unintern(&attr_new
);
4982 aspath_unintern(&attr
.aspath
);
4985 /* The attribute is changed. */
4986 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4988 /* Rewrite BGP route information. */
4989 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4990 bgp_path_info_restore(rn
, pi
);
4992 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4994 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4995 && (safi
== SAFI_UNICAST
)) {
4996 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4998 * Implicit withdraw case.
4999 * We have to do this before pi is
5002 ++vnc_implicit_withdraw
;
5003 vnc_import_bgp_del_route(bgp
, p
, pi
);
5004 vnc_import_bgp_exterior_del_route(
5009 bgp_attr_unintern(&pi
->attr
);
5010 pi
->attr
= attr_new
;
5011 pi
->uptime
= bgp_clock();
5013 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5014 && (safi
== SAFI_UNICAST
)) {
5015 if (vnc_implicit_withdraw
) {
5016 vnc_import_bgp_add_route(bgp
, p
, pi
);
5017 vnc_import_bgp_exterior_add_route(
5023 /* Nexthop reachability check. */
5024 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5025 && (safi
== SAFI_UNICAST
5026 || safi
== SAFI_LABELED_UNICAST
)) {
5028 struct bgp
*bgp_nexthop
= bgp
;
5030 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5031 bgp_nexthop
= pi
->extra
->bgp_orig
;
5033 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5035 bgp_path_info_set_flag(rn
, pi
,
5038 if (BGP_DEBUG(nht
, NHT
)) {
5039 char buf1
[INET6_ADDRSTRLEN
];
5040 inet_ntop(p
->family
,
5044 "%s(%s): Route not in table, not advertising",
5045 __FUNCTION__
, buf1
);
5047 bgp_path_info_unset_flag(
5048 rn
, pi
, BGP_PATH_VALID
);
5051 /* Delete the NHT structure if any, if we're
5053 * enabling/disabling import check. We
5054 * deregister the route
5055 * from NHT to avoid overloading NHT and the
5056 * process interaction
5058 bgp_unlink_nexthop(pi
);
5059 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
5061 /* Process change. */
5062 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5063 bgp_process(bgp
, rn
, afi
, safi
);
5065 if (SAFI_UNICAST
== safi
5066 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5068 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5069 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5073 bgp_unlock_node(rn
);
5074 aspath_unintern(&attr
.aspath
);
5079 /* Make new BGP info. */
5080 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5082 /* Nexthop reachability check. */
5083 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5084 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5085 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5086 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5088 if (BGP_DEBUG(nht
, NHT
)) {
5089 char buf1
[INET6_ADDRSTRLEN
];
5090 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5093 "%s(%s): Route not in table, not advertising",
5094 __FUNCTION__
, buf1
);
5096 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
5099 /* Delete the NHT structure if any, if we're toggling between
5100 * enabling/disabling import check. We deregister the route
5101 * from NHT to avoid overloading NHT and the process interaction
5103 bgp_unlink_nexthop(new);
5105 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5108 /* Aggregate address increment. */
5109 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5111 /* Register new BGP information. */
5112 bgp_path_info_add(rn
, new);
5114 /* route_node_get lock */
5115 bgp_unlock_node(rn
);
5117 /* Process change. */
5118 bgp_process(bgp
, rn
, afi
, safi
);
5120 if (SAFI_UNICAST
== safi
5121 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5122 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5123 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5126 /* Unintern original. */
5127 aspath_unintern(&attr
.aspath
);
5130 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5133 struct bgp_node
*rn
;
5134 struct bgp_path_info
*pi
;
5136 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5138 /* Check selected route and self inserted route. */
5139 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5140 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5141 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5144 /* Withdraw static BGP route from routing table. */
5146 if (SAFI_UNICAST
== safi
5147 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5148 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5149 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5151 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5152 bgp_unlink_nexthop(pi
);
5153 bgp_path_info_delete(rn
, pi
);
5154 bgp_process(bgp
, rn
, afi
, safi
);
5157 /* Unlock bgp_node_lookup. */
5158 bgp_unlock_node(rn
);
5162 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5164 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
5165 afi_t afi
, safi_t safi
,
5166 struct prefix_rd
*prd
)
5168 struct bgp_node
*rn
;
5169 struct bgp_path_info
*pi
;
5171 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5173 /* Check selected route and self inserted route. */
5174 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5175 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5176 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5179 /* Withdraw static BGP route from routing table. */
5182 rfapiProcessWithdraw(
5183 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5184 1); /* Kill, since it is an administrative change */
5186 if (SAFI_MPLS_VPN
== safi
5187 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5188 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5190 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5191 bgp_path_info_delete(rn
, pi
);
5192 bgp_process(bgp
, rn
, afi
, safi
);
5195 /* Unlock bgp_node_lookup. */
5196 bgp_unlock_node(rn
);
5199 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
5200 struct bgp_static
*bgp_static
, afi_t afi
,
5203 struct bgp_node
*rn
;
5204 struct bgp_path_info
*new;
5205 struct attr
*attr_new
;
5206 struct attr attr
= {0};
5207 struct bgp_path_info
*pi
;
5209 mpls_label_t label
= 0;
5211 uint32_t num_labels
= 0;
5216 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5218 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5221 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5223 attr
.nexthop
= bgp_static
->igpnexthop
;
5224 attr
.med
= bgp_static
->igpmetric
;
5225 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5227 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5228 || (safi
== SAFI_ENCAP
)) {
5229 if (afi
== AFI_IP
) {
5230 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5231 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5234 if (afi
== AFI_L2VPN
) {
5235 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5237 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5238 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5239 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5240 sizeof(struct in6_addr
));
5241 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5242 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5243 struct bgp_encap_type_vxlan bet
;
5244 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5245 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5246 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5248 if (bgp_static
->router_mac
) {
5249 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5252 /* Apply route-map. */
5253 if (bgp_static
->rmap
.name
) {
5254 struct attr attr_tmp
= attr
;
5255 struct bgp_path_info rmap_path
;
5256 route_map_result_t ret
;
5258 rmap_path
.peer
= bgp
->peer_self
;
5259 rmap_path
.attr
= &attr_tmp
;
5261 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5263 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5266 bgp
->peer_self
->rmap_type
= 0;
5268 if (ret
== RMAP_DENYMATCH
) {
5269 /* Free uninterned attribute. */
5270 bgp_attr_flush(&attr_tmp
);
5272 /* Unintern original. */
5273 aspath_unintern(&attr
.aspath
);
5274 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5279 attr_new
= bgp_attr_intern(&attr_tmp
);
5281 attr_new
= bgp_attr_intern(&attr
);
5284 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5285 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5286 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5290 memset(&add
, 0, sizeof(union gw_addr
));
5291 if (attrhash_cmp(pi
->attr
, attr_new
)
5292 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5293 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5294 bgp_unlock_node(rn
);
5295 bgp_attr_unintern(&attr_new
);
5296 aspath_unintern(&attr
.aspath
);
5299 /* The attribute is changed. */
5300 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5302 /* Rewrite BGP route information. */
5303 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5304 bgp_path_info_restore(rn
, pi
);
5306 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5307 bgp_attr_unintern(&pi
->attr
);
5308 pi
->attr
= attr_new
;
5309 pi
->uptime
= bgp_clock();
5312 label
= decode_label(&pi
->extra
->label
[0]);
5315 /* Process change. */
5316 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5317 bgp_process(bgp
, rn
, afi
, safi
);
5319 if (SAFI_MPLS_VPN
== safi
5320 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5321 vpn_leak_to_vrf_update(bgp
, pi
);
5324 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5325 pi
->attr
, afi
, safi
, pi
->type
,
5326 pi
->sub_type
, &label
);
5328 bgp_unlock_node(rn
);
5329 aspath_unintern(&attr
.aspath
);
5335 /* Make new BGP info. */
5336 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5338 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5339 new->extra
= bgp_path_info_extra_new();
5341 new->extra
->label
[0] = bgp_static
->label
;
5342 new->extra
->num_labels
= num_labels
;
5345 label
= decode_label(&bgp_static
->label
);
5348 /* Aggregate address increment. */
5349 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5351 /* Register new BGP information. */
5352 bgp_path_info_add(rn
, new);
5353 /* route_node_get lock */
5354 bgp_unlock_node(rn
);
5356 /* Process change. */
5357 bgp_process(bgp
, rn
, afi
, safi
);
5359 if (SAFI_MPLS_VPN
== safi
5360 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5361 vpn_leak_to_vrf_update(bgp
, new);
5364 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5365 safi
, new->type
, new->sub_type
, &label
);
5368 /* Unintern original. */
5369 aspath_unintern(&attr
.aspath
);
5372 /* Configure static BGP network. When user don't run zebra, static
5373 route should be installed as valid. */
5374 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5375 const char *ip_str
, afi_t afi
, safi_t safi
,
5376 const char *rmap
, int backdoor
, uint32_t label_index
)
5378 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5381 struct bgp_static
*bgp_static
;
5382 struct bgp_node
*rn
;
5383 uint8_t need_update
= 0;
5385 /* Convert IP prefix string to struct prefix. */
5386 ret
= str2prefix(ip_str
, &p
);
5388 vty_out(vty
, "%% Malformed prefix\n");
5389 return CMD_WARNING_CONFIG_FAILED
;
5391 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5392 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5393 return CMD_WARNING_CONFIG_FAILED
;
5400 /* Set BGP static route configuration. */
5401 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5404 vty_out(vty
, "%% Can't find static route specified\n");
5405 return CMD_WARNING_CONFIG_FAILED
;
5408 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5410 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5411 && (label_index
!= bgp_static
->label_index
)) {
5413 "%% label-index doesn't match static route\n");
5414 return CMD_WARNING_CONFIG_FAILED
;
5417 if ((rmap
&& bgp_static
->rmap
.name
)
5418 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5420 "%% route-map name doesn't match static route\n");
5421 return CMD_WARNING_CONFIG_FAILED
;
5424 /* Update BGP RIB. */
5425 if (!bgp_static
->backdoor
)
5426 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5428 /* Clear configuration. */
5429 bgp_static_free(bgp_static
);
5430 bgp_node_set_bgp_static_info(rn
, NULL
);
5431 bgp_unlock_node(rn
);
5432 bgp_unlock_node(rn
);
5435 /* Set BGP static route configuration. */
5436 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5438 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5440 /* Configuration change. */
5441 /* Label index cannot be changed. */
5442 if (bgp_static
->label_index
!= label_index
) {
5443 vty_out(vty
, "%% cannot change label-index\n");
5444 return CMD_WARNING_CONFIG_FAILED
;
5447 /* Check previous routes are installed into BGP. */
5448 if (bgp_static
->valid
5449 && bgp_static
->backdoor
!= backdoor
)
5452 bgp_static
->backdoor
= backdoor
;
5455 XFREE(MTYPE_ROUTE_MAP_NAME
,
5456 bgp_static
->rmap
.name
);
5457 route_map_counter_decrement(
5458 bgp_static
->rmap
.map
);
5459 bgp_static
->rmap
.name
=
5460 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5461 bgp_static
->rmap
.map
=
5462 route_map_lookup_by_name(rmap
);
5463 route_map_counter_increment(
5464 bgp_static
->rmap
.map
);
5466 XFREE(MTYPE_ROUTE_MAP_NAME
,
5467 bgp_static
->rmap
.name
);
5468 route_map_counter_decrement(
5469 bgp_static
->rmap
.map
);
5470 bgp_static
->rmap
.name
= NULL
;
5471 bgp_static
->rmap
.map
= NULL
;
5472 bgp_static
->valid
= 0;
5474 bgp_unlock_node(rn
);
5476 /* New configuration. */
5477 bgp_static
= bgp_static_new();
5478 bgp_static
->backdoor
= backdoor
;
5479 bgp_static
->valid
= 0;
5480 bgp_static
->igpmetric
= 0;
5481 bgp_static
->igpnexthop
.s_addr
= 0;
5482 bgp_static
->label_index
= label_index
;
5485 XFREE(MTYPE_ROUTE_MAP_NAME
,
5486 bgp_static
->rmap
.name
);
5487 route_map_counter_decrement(
5488 bgp_static
->rmap
.map
);
5489 bgp_static
->rmap
.name
=
5490 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5491 bgp_static
->rmap
.map
=
5492 route_map_lookup_by_name(rmap
);
5493 route_map_counter_increment(
5494 bgp_static
->rmap
.map
);
5496 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5499 bgp_static
->valid
= 1;
5501 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5503 if (!bgp_static
->backdoor
)
5504 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5510 void bgp_static_add(struct bgp
*bgp
)
5514 struct bgp_node
*rn
;
5515 struct bgp_node
*rm
;
5516 struct bgp_table
*table
;
5517 struct bgp_static
*bgp_static
;
5519 FOREACH_AFI_SAFI (afi
, safi
)
5520 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5521 rn
= bgp_route_next(rn
)) {
5522 if (!bgp_node_has_bgp_path_info_data(rn
))
5525 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5526 || (safi
== SAFI_EVPN
)) {
5527 table
= bgp_node_get_bgp_table_info(rn
);
5529 for (rm
= bgp_table_top(table
); rm
;
5530 rm
= bgp_route_next(rm
)) {
5532 bgp_node_get_bgp_static_info(
5534 bgp_static_update_safi(bgp
, &rm
->p
,
5541 bgp_node_get_bgp_static_info(rn
), afi
,
5547 /* Called from bgp_delete(). Delete all static routes from the BGP
5549 void bgp_static_delete(struct bgp
*bgp
)
5553 struct bgp_node
*rn
;
5554 struct bgp_node
*rm
;
5555 struct bgp_table
*table
;
5556 struct bgp_static
*bgp_static
;
5558 FOREACH_AFI_SAFI (afi
, safi
)
5559 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5560 rn
= bgp_route_next(rn
)) {
5561 if (!bgp_node_has_bgp_path_info_data(rn
))
5564 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5565 || (safi
== SAFI_EVPN
)) {
5566 table
= bgp_node_get_bgp_table_info(rn
);
5568 for (rm
= bgp_table_top(table
); rm
;
5569 rm
= bgp_route_next(rm
)) {
5571 bgp_node_get_bgp_static_info(
5576 bgp_static_withdraw_safi(
5577 bgp
, &rm
->p
, AFI_IP
, safi
,
5578 (struct prefix_rd
*)&rn
->p
);
5579 bgp_static_free(bgp_static
);
5580 bgp_node_set_bgp_static_info(rn
, NULL
);
5581 bgp_unlock_node(rn
);
5584 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5585 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5586 bgp_static_free(bgp_static
);
5587 bgp_node_set_bgp_static_info(rn
, NULL
);
5588 bgp_unlock_node(rn
);
5593 void bgp_static_redo_import_check(struct bgp
*bgp
)
5597 struct bgp_node
*rn
;
5598 struct bgp_node
*rm
;
5599 struct bgp_table
*table
;
5600 struct bgp_static
*bgp_static
;
5602 /* Use this flag to force reprocessing of the route */
5603 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5604 FOREACH_AFI_SAFI (afi
, safi
) {
5605 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5606 rn
= bgp_route_next(rn
)) {
5607 if (!bgp_node_has_bgp_path_info_data(rn
))
5610 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5611 || (safi
== SAFI_EVPN
)) {
5612 table
= bgp_node_get_bgp_table_info(rn
);
5614 for (rm
= bgp_table_top(table
); rm
;
5615 rm
= bgp_route_next(rm
)) {
5617 bgp_node_get_bgp_static_info(
5619 bgp_static_update_safi(bgp
, &rm
->p
,
5624 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5625 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5630 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5633 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5636 struct bgp_table
*table
;
5637 struct bgp_node
*rn
;
5638 struct bgp_path_info
*pi
;
5640 /* Do not install the aggregate route if BGP is in the
5641 * process of termination.
5643 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5644 (bgp
->peer_self
== NULL
))
5647 table
= bgp
->rib
[afi
][safi
];
5648 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5649 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5650 if (pi
->peer
== bgp
->peer_self
5651 && ((pi
->type
== ZEBRA_ROUTE_BGP
5652 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5653 || (pi
->type
!= ZEBRA_ROUTE_BGP
5655 == BGP_ROUTE_REDISTRIBUTE
))) {
5656 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5658 bgp_unlink_nexthop(pi
);
5659 bgp_path_info_delete(rn
, pi
);
5660 bgp_process(bgp
, rn
, afi
, safi
);
5667 * Purge all networks and redistributed routes from routing table.
5668 * Invoked upon the instance going down.
5670 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5675 FOREACH_AFI_SAFI (afi
, safi
)
5676 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5681 * Currently this is used to set static routes for VPN and ENCAP.
5682 * I think it can probably be factored with bgp_static_set.
5684 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5685 const char *ip_str
, const char *rd_str
,
5686 const char *label_str
, const char *rmap_str
,
5687 int evpn_type
, const char *esi
, const char *gwip
,
5688 const char *ethtag
, const char *routermac
)
5690 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5693 struct prefix_rd prd
;
5694 struct bgp_node
*prn
;
5695 struct bgp_node
*rn
;
5696 struct bgp_table
*table
;
5697 struct bgp_static
*bgp_static
;
5698 mpls_label_t label
= MPLS_INVALID_LABEL
;
5699 struct prefix gw_ip
;
5701 /* validate ip prefix */
5702 ret
= str2prefix(ip_str
, &p
);
5704 vty_out(vty
, "%% Malformed prefix\n");
5705 return CMD_WARNING_CONFIG_FAILED
;
5708 if ((afi
== AFI_L2VPN
)
5709 && (bgp_build_evpn_prefix(evpn_type
,
5710 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5711 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5712 return CMD_WARNING_CONFIG_FAILED
;
5715 ret
= str2prefix_rd(rd_str
, &prd
);
5717 vty_out(vty
, "%% Malformed rd\n");
5718 return CMD_WARNING_CONFIG_FAILED
;
5722 unsigned long label_val
;
5723 label_val
= strtoul(label_str
, NULL
, 10);
5724 encode_label(label_val
, &label
);
5727 if (safi
== SAFI_EVPN
) {
5728 if (esi
&& str2esi(esi
, NULL
) == 0) {
5729 vty_out(vty
, "%% Malformed ESI\n");
5730 return CMD_WARNING_CONFIG_FAILED
;
5732 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5733 vty_out(vty
, "%% Malformed Router MAC\n");
5734 return CMD_WARNING_CONFIG_FAILED
;
5737 memset(&gw_ip
, 0, sizeof(struct prefix
));
5738 ret
= str2prefix(gwip
, &gw_ip
);
5740 vty_out(vty
, "%% Malformed GatewayIp\n");
5741 return CMD_WARNING_CONFIG_FAILED
;
5743 if ((gw_ip
.family
== AF_INET
5744 && is_evpn_prefix_ipaddr_v6(
5745 (struct prefix_evpn
*)&p
))
5746 || (gw_ip
.family
== AF_INET6
5747 && is_evpn_prefix_ipaddr_v4(
5748 (struct prefix_evpn
*)&p
))) {
5750 "%% GatewayIp family differs with IP prefix\n");
5751 return CMD_WARNING_CONFIG_FAILED
;
5755 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5756 if (!bgp_node_has_bgp_path_info_data(prn
))
5757 bgp_node_set_bgp_table_info(prn
,
5758 bgp_table_init(bgp
, afi
, safi
));
5759 table
= bgp_node_get_bgp_table_info(prn
);
5761 rn
= bgp_node_get(table
, &p
);
5763 if (bgp_node_has_bgp_path_info_data(rn
)) {
5764 vty_out(vty
, "%% Same network configuration exists\n");
5765 bgp_unlock_node(rn
);
5767 /* New configuration. */
5768 bgp_static
= bgp_static_new();
5769 bgp_static
->backdoor
= 0;
5770 bgp_static
->valid
= 0;
5771 bgp_static
->igpmetric
= 0;
5772 bgp_static
->igpnexthop
.s_addr
= 0;
5773 bgp_static
->label
= label
;
5774 bgp_static
->prd
= prd
;
5777 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5778 route_map_counter_decrement(bgp_static
->rmap
.map
);
5779 bgp_static
->rmap
.name
=
5780 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5781 bgp_static
->rmap
.map
=
5782 route_map_lookup_by_name(rmap_str
);
5783 route_map_counter_increment(bgp_static
->rmap
.map
);
5786 if (safi
== SAFI_EVPN
) {
5788 bgp_static
->eth_s_id
=
5790 sizeof(struct eth_segment_id
));
5791 str2esi(esi
, bgp_static
->eth_s_id
);
5794 bgp_static
->router_mac
=
5795 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5796 (void)prefix_str2mac(routermac
,
5797 bgp_static
->router_mac
);
5800 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5802 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5804 bgp_static
->valid
= 1;
5805 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5811 /* Configure static BGP network. */
5812 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5813 const char *ip_str
, const char *rd_str
,
5814 const char *label_str
, int evpn_type
, const char *esi
,
5815 const char *gwip
, const char *ethtag
)
5817 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5820 struct prefix_rd prd
;
5821 struct bgp_node
*prn
;
5822 struct bgp_node
*rn
;
5823 struct bgp_table
*table
;
5824 struct bgp_static
*bgp_static
;
5825 mpls_label_t label
= MPLS_INVALID_LABEL
;
5827 /* Convert IP prefix string to struct prefix. */
5828 ret
= str2prefix(ip_str
, &p
);
5830 vty_out(vty
, "%% Malformed prefix\n");
5831 return CMD_WARNING_CONFIG_FAILED
;
5834 if ((afi
== AFI_L2VPN
)
5835 && (bgp_build_evpn_prefix(evpn_type
,
5836 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5837 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5838 return CMD_WARNING_CONFIG_FAILED
;
5840 ret
= str2prefix_rd(rd_str
, &prd
);
5842 vty_out(vty
, "%% Malformed rd\n");
5843 return CMD_WARNING_CONFIG_FAILED
;
5847 unsigned long label_val
;
5848 label_val
= strtoul(label_str
, NULL
, 10);
5849 encode_label(label_val
, &label
);
5852 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5853 if (!bgp_node_has_bgp_path_info_data(prn
))
5854 bgp_node_set_bgp_table_info(prn
,
5855 bgp_table_init(bgp
, afi
, safi
));
5857 bgp_unlock_node(prn
);
5858 table
= bgp_node_get_bgp_table_info(prn
);
5860 rn
= bgp_node_lookup(table
, &p
);
5863 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5865 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5866 bgp_static_free(bgp_static
);
5867 bgp_node_set_bgp_static_info(rn
, NULL
);
5868 bgp_unlock_node(rn
);
5869 bgp_unlock_node(rn
);
5871 vty_out(vty
, "%% Can't find the route\n");
5876 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5877 const char *rmap_name
)
5879 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5880 struct bgp_rmap
*rmap
;
5882 rmap
= &bgp
->table_map
[afi
][safi
];
5884 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5885 route_map_counter_decrement(rmap
->map
);
5886 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5887 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5888 route_map_counter_increment(rmap
->map
);
5890 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5891 route_map_counter_decrement(rmap
->map
);
5896 if (bgp_fibupd_safi(safi
))
5897 bgp_zebra_announce_table(bgp
, afi
, safi
);
5902 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5903 const char *rmap_name
)
5905 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5906 struct bgp_rmap
*rmap
;
5908 rmap
= &bgp
->table_map
[afi
][safi
];
5909 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5910 route_map_counter_decrement(rmap
->map
);
5914 if (bgp_fibupd_safi(safi
))
5915 bgp_zebra_announce_table(bgp
, afi
, safi
);
5920 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5923 if (bgp
->table_map
[afi
][safi
].name
) {
5924 vty_out(vty
, " table-map %s\n",
5925 bgp
->table_map
[afi
][safi
].name
);
5929 DEFUN (bgp_table_map
,
5932 "BGP table to RIB route download filter\n"
5933 "Name of the route map\n")
5936 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5937 argv
[idx_word
]->arg
);
5939 DEFUN (no_bgp_table_map
,
5940 no_bgp_table_map_cmd
,
5941 "no table-map WORD",
5943 "BGP table to RIB route download filter\n"
5944 "Name of the route map\n")
5947 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5948 argv
[idx_word
]->arg
);
5954 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5955 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5956 backdoor$backdoor}]",
5958 "Specify a network to announce via BGP\n"
5963 "Route-map to modify the attributes\n"
5964 "Name of the route map\n"
5965 "Label index to associate with the prefix\n"
5966 "Label index value\n"
5967 "Specify a BGP backdoor route\n")
5969 char addr_prefix_str
[BUFSIZ
];
5974 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5977 vty_out(vty
, "%% Inconsistent address and mask\n");
5978 return CMD_WARNING_CONFIG_FAILED
;
5982 return bgp_static_set(
5983 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5984 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5985 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5988 DEFPY(ipv6_bgp_network
,
5989 ipv6_bgp_network_cmd
,
5990 "[no] network X:X::X:X/M$prefix \
5991 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5993 "Specify a network to announce via BGP\n"
5995 "Route-map to modify the attributes\n"
5996 "Name of the route map\n"
5997 "Label index to associate with the prefix\n"
5998 "Label index value\n")
6000 return bgp_static_set(
6001 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6002 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6005 static struct bgp_aggregate
*bgp_aggregate_new(void)
6007 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6010 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6012 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6013 route_map_counter_decrement(aggregate
->rmap
.map
);
6014 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6017 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6018 struct aspath
*aspath
,
6019 struct community
*comm
,
6020 struct ecommunity
*ecomm
,
6021 struct lcommunity
*lcomm
)
6023 static struct aspath
*ae
= NULL
;
6026 ae
= aspath_empty();
6031 if (origin
!= pi
->attr
->origin
)
6034 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6037 if (!community_cmp(pi
->attr
->community
, comm
))
6040 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6043 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6046 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6052 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
6053 struct prefix
*p
, uint8_t origin
,
6054 struct aspath
*aspath
,
6055 struct community
*community
,
6056 struct ecommunity
*ecommunity
,
6057 struct lcommunity
*lcommunity
,
6058 uint8_t atomic_aggregate
,
6059 struct bgp_aggregate
*aggregate
)
6061 struct bgp_node
*rn
;
6062 struct bgp_table
*table
;
6063 struct bgp_path_info
*pi
, *orig
, *new;
6066 table
= bgp
->rib
[afi
][safi
];
6068 rn
= bgp_node_get(table
, p
);
6070 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6071 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6072 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6075 if (aggregate
->count
> 0) {
6077 * If the aggregate information has not changed
6078 * no need to re-install it again.
6080 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6081 ecommunity
, lcommunity
)) {
6082 bgp_unlock_node(rn
);
6085 aspath_free(aspath
);
6087 community_free(&community
);
6089 ecommunity_free(&ecommunity
);
6091 lcommunity_free(&lcommunity
);
6097 * Mark the old as unusable
6100 bgp_path_info_delete(rn
, pi
);
6102 attr
= bgp_attr_aggregate_intern(
6103 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6104 aggregate
, atomic_aggregate
, p
);
6107 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6111 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6112 bgp
->peer_self
, attr
, rn
);
6114 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6116 bgp_path_info_add(rn
, new);
6117 bgp_process(bgp
, rn
, afi
, safi
);
6119 for (pi
= orig
; pi
; pi
= pi
->next
)
6120 if (pi
->peer
== bgp
->peer_self
6121 && pi
->type
== ZEBRA_ROUTE_BGP
6122 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6125 /* Withdraw static BGP route from routing table. */
6127 bgp_path_info_delete(rn
, pi
);
6128 bgp_process(bgp
, rn
, afi
, safi
);
6132 bgp_unlock_node(rn
);
6135 /* Update an aggregate as routes are added/removed from the BGP table */
6136 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
6137 afi_t afi
, safi_t safi
,
6138 struct bgp_aggregate
*aggregate
)
6140 struct bgp_table
*table
;
6141 struct bgp_node
*top
;
6142 struct bgp_node
*rn
;
6144 struct aspath
*aspath
= NULL
;
6145 struct community
*community
= NULL
;
6146 struct ecommunity
*ecommunity
= NULL
;
6147 struct lcommunity
*lcommunity
= NULL
;
6148 struct bgp_path_info
*pi
;
6149 unsigned long match
= 0;
6150 uint8_t atomic_aggregate
= 0;
6152 /* If the bgp instance is being deleted or self peer is deleted
6153 * then do not create aggregate route
6155 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
6156 (bgp
->peer_self
== NULL
))
6159 /* ORIGIN attribute: If at least one route among routes that are
6160 aggregated has ORIGIN with the value INCOMPLETE, then the
6161 aggregated route must have the ORIGIN attribute with the value
6162 INCOMPLETE. Otherwise, if at least one route among routes that
6163 are aggregated has ORIGIN with the value EGP, then the aggregated
6164 route must have the origin attribute with the value EGP. In all
6165 other case the value of the ORIGIN attribute of the aggregated
6166 route is INTERNAL. */
6167 origin
= BGP_ORIGIN_IGP
;
6169 table
= bgp
->rib
[afi
][safi
];
6171 top
= bgp_node_get(table
, p
);
6172 for (rn
= bgp_node_get(table
, p
); rn
;
6173 rn
= bgp_route_next_until(rn
, top
)) {
6174 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6179 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6180 if (BGP_PATH_HOLDDOWN(pi
))
6184 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6185 atomic_aggregate
= 1;
6187 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6191 * summary-only aggregate route suppress
6192 * aggregated route announcements.
6194 if (aggregate
->summary_only
) {
6195 (bgp_path_info_extra_get(pi
))->suppress
++;
6196 bgp_path_info_set_flag(rn
, pi
,
6197 BGP_PATH_ATTR_CHANGED
);
6204 * If at least one route among routes that are
6205 * aggregated has ORIGIN with the value INCOMPLETE,
6206 * then the aggregated route MUST have the ORIGIN
6207 * attribute with the value INCOMPLETE. Otherwise, if
6208 * at least one route among routes that are aggregated
6209 * has ORIGIN with the value EGP, then the aggregated
6210 * route MUST have the ORIGIN attribute with the value
6213 switch (pi
->attr
->origin
) {
6214 case BGP_ORIGIN_INCOMPLETE
:
6215 aggregate
->incomplete_origin_count
++;
6217 case BGP_ORIGIN_EGP
:
6218 aggregate
->egp_origin_count
++;
6226 if (!aggregate
->as_set
)
6230 * as-set aggregate route generate origin, as path,
6231 * and community aggregation.
6233 /* Compute aggregate route's as-path.
6235 bgp_compute_aggregate_aspath_hash(aggregate
,
6238 /* Compute aggregate route's community.
6240 if (pi
->attr
->community
)
6241 bgp_compute_aggregate_community_hash(
6243 pi
->attr
->community
);
6245 /* Compute aggregate route's extended community.
6247 if (pi
->attr
->ecommunity
)
6248 bgp_compute_aggregate_ecommunity_hash(
6250 pi
->attr
->ecommunity
);
6252 /* Compute aggregate route's large community.
6254 if (pi
->attr
->lcommunity
)
6255 bgp_compute_aggregate_lcommunity_hash(
6257 pi
->attr
->lcommunity
);
6260 bgp_process(bgp
, rn
, afi
, safi
);
6262 if (aggregate
->as_set
) {
6263 bgp_compute_aggregate_aspath_val(aggregate
);
6264 bgp_compute_aggregate_community_val(aggregate
);
6265 bgp_compute_aggregate_ecommunity_val(aggregate
);
6266 bgp_compute_aggregate_lcommunity_val(aggregate
);
6270 bgp_unlock_node(top
);
6273 if (aggregate
->incomplete_origin_count
> 0)
6274 origin
= BGP_ORIGIN_INCOMPLETE
;
6275 else if (aggregate
->egp_origin_count
> 0)
6276 origin
= BGP_ORIGIN_EGP
;
6278 if (aggregate
->as_set
) {
6279 if (aggregate
->aspath
)
6280 /* Retrieve aggregate route's as-path.
6282 aspath
= aspath_dup(aggregate
->aspath
);
6284 if (aggregate
->community
)
6285 /* Retrieve aggregate route's community.
6287 community
= community_dup(aggregate
->community
);
6289 if (aggregate
->ecommunity
)
6290 /* Retrieve aggregate route's ecommunity.
6292 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6294 if (aggregate
->lcommunity
)
6295 /* Retrieve aggregate route's lcommunity.
6297 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6300 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6301 ecommunity
, lcommunity
, atomic_aggregate
,
6305 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6306 safi_t safi
, struct bgp_aggregate
*aggregate
)
6308 struct bgp_table
*table
;
6309 struct bgp_node
*top
;
6310 struct bgp_node
*rn
;
6311 struct bgp_path_info
*pi
;
6312 unsigned long match
;
6314 table
= bgp
->rib
[afi
][safi
];
6316 /* If routes exists below this node, generate aggregate routes. */
6317 top
= bgp_node_get(table
, p
);
6318 for (rn
= bgp_node_get(table
, p
); rn
;
6319 rn
= bgp_route_next_until(rn
, top
)) {
6320 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6324 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6325 if (BGP_PATH_HOLDDOWN(pi
))
6328 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6331 if (aggregate
->summary_only
&& pi
->extra
) {
6332 pi
->extra
->suppress
--;
6334 if (pi
->extra
->suppress
== 0) {
6335 bgp_path_info_set_flag(
6336 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6342 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6343 aggregate
->incomplete_origin_count
--;
6344 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6345 aggregate
->egp_origin_count
--;
6347 if (aggregate
->as_set
) {
6348 /* Remove as-path from aggregate.
6350 bgp_remove_aspath_from_aggregate_hash(
6354 if (pi
->attr
->community
)
6355 /* Remove community from aggregate.
6357 bgp_remove_comm_from_aggregate_hash(
6359 pi
->attr
->community
);
6361 if (pi
->attr
->ecommunity
)
6362 /* Remove ecommunity from aggregate.
6364 bgp_remove_ecomm_from_aggregate_hash(
6366 pi
->attr
->ecommunity
);
6368 if (pi
->attr
->lcommunity
)
6369 /* Remove lcommunity from aggregate.
6371 bgp_remove_lcomm_from_aggregate_hash(
6373 pi
->attr
->lcommunity
);
6378 /* If this node was suppressed, process the change. */
6380 bgp_process(bgp
, rn
, afi
, safi
);
6382 if (aggregate
->as_set
) {
6383 aspath_free(aggregate
->aspath
);
6384 aggregate
->aspath
= NULL
;
6385 if (aggregate
->community
)
6386 community_free(&aggregate
->community
);
6387 if (aggregate
->ecommunity
)
6388 ecommunity_free(&aggregate
->ecommunity
);
6389 if (aggregate
->lcommunity
)
6390 lcommunity_free(&aggregate
->lcommunity
);
6393 bgp_unlock_node(top
);
6396 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6397 struct bgp_path_info
*pinew
, afi_t afi
,
6399 struct bgp_aggregate
*aggregate
)
6402 struct aspath
*aspath
= NULL
;
6403 uint8_t atomic_aggregate
= 0;
6404 struct community
*community
= NULL
;
6405 struct ecommunity
*ecommunity
= NULL
;
6406 struct lcommunity
*lcommunity
= NULL
;
6408 /* ORIGIN attribute: If at least one route among routes that are
6409 * aggregated has ORIGIN with the value INCOMPLETE, then the
6410 * aggregated route must have the ORIGIN attribute with the value
6411 * INCOMPLETE. Otherwise, if at least one route among routes that
6412 * are aggregated has ORIGIN with the value EGP, then the aggregated
6413 * route must have the origin attribute with the value EGP. In all
6414 * other case the value of the ORIGIN attribute of the aggregated
6415 * route is INTERNAL.
6417 origin
= BGP_ORIGIN_IGP
;
6421 if (aggregate
->summary_only
)
6422 (bgp_path_info_extra_get(pinew
))->suppress
++;
6424 switch (pinew
->attr
->origin
) {
6425 case BGP_ORIGIN_INCOMPLETE
:
6426 aggregate
->incomplete_origin_count
++;
6428 case BGP_ORIGIN_EGP
:
6429 aggregate
->egp_origin_count
++;
6437 if (aggregate
->incomplete_origin_count
> 0)
6438 origin
= BGP_ORIGIN_INCOMPLETE
;
6439 else if (aggregate
->egp_origin_count
> 0)
6440 origin
= BGP_ORIGIN_EGP
;
6442 if (aggregate
->as_set
) {
6443 /* Compute aggregate route's as-path.
6445 bgp_compute_aggregate_aspath(aggregate
,
6446 pinew
->attr
->aspath
);
6448 /* Compute aggregate route's community.
6450 if (pinew
->attr
->community
)
6451 bgp_compute_aggregate_community(
6453 pinew
->attr
->community
);
6455 /* Compute aggregate route's extended community.
6457 if (pinew
->attr
->ecommunity
)
6458 bgp_compute_aggregate_ecommunity(
6460 pinew
->attr
->ecommunity
);
6462 /* Compute aggregate route's large community.
6464 if (pinew
->attr
->lcommunity
)
6465 bgp_compute_aggregate_lcommunity(
6467 pinew
->attr
->lcommunity
);
6469 /* Retrieve aggregate route's as-path.
6471 if (aggregate
->aspath
)
6472 aspath
= aspath_dup(aggregate
->aspath
);
6474 /* Retrieve aggregate route's community.
6476 if (aggregate
->community
)
6477 community
= community_dup(aggregate
->community
);
6479 /* Retrieve aggregate route's ecommunity.
6481 if (aggregate
->ecommunity
)
6482 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6484 /* Retrieve aggregate route's lcommunity.
6486 if (aggregate
->lcommunity
)
6487 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6490 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6491 aspath
, community
, ecommunity
,
6492 lcommunity
, atomic_aggregate
, aggregate
);
6495 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6497 struct bgp_path_info
*pi
,
6498 struct bgp_aggregate
*aggregate
,
6499 struct prefix
*aggr_p
)
6502 struct aspath
*aspath
= NULL
;
6503 uint8_t atomic_aggregate
= 0;
6504 struct community
*community
= NULL
;
6505 struct ecommunity
*ecommunity
= NULL
;
6506 struct lcommunity
*lcommunity
= NULL
;
6507 unsigned long match
= 0;
6509 if (BGP_PATH_HOLDDOWN(pi
))
6512 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6515 if (aggregate
->summary_only
6517 && pi
->extra
->suppress
> 0) {
6518 pi
->extra
->suppress
--;
6520 if (pi
->extra
->suppress
== 0) {
6521 bgp_path_info_set_flag(pi
->net
, pi
,
6522 BGP_PATH_ATTR_CHANGED
);
6527 if (aggregate
->count
> 0)
6530 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6531 aggregate
->incomplete_origin_count
--;
6532 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6533 aggregate
->egp_origin_count
--;
6535 if (aggregate
->as_set
) {
6536 /* Remove as-path from aggregate.
6538 bgp_remove_aspath_from_aggregate(aggregate
,
6541 if (pi
->attr
->community
)
6542 /* Remove community from aggregate.
6544 bgp_remove_community_from_aggregate(
6546 pi
->attr
->community
);
6548 if (pi
->attr
->ecommunity
)
6549 /* Remove ecommunity from aggregate.
6551 bgp_remove_ecommunity_from_aggregate(
6553 pi
->attr
->ecommunity
);
6555 if (pi
->attr
->lcommunity
)
6556 /* Remove lcommunity from aggregate.
6558 bgp_remove_lcommunity_from_aggregate(
6560 pi
->attr
->lcommunity
);
6563 /* If this node was suppressed, process the change. */
6565 bgp_process(bgp
, pi
->net
, afi
, safi
);
6567 origin
= BGP_ORIGIN_IGP
;
6568 if (aggregate
->incomplete_origin_count
> 0)
6569 origin
= BGP_ORIGIN_INCOMPLETE
;
6570 else if (aggregate
->egp_origin_count
> 0)
6571 origin
= BGP_ORIGIN_EGP
;
6573 if (aggregate
->as_set
) {
6574 /* Retrieve aggregate route's as-path.
6576 if (aggregate
->aspath
)
6577 aspath
= aspath_dup(aggregate
->aspath
);
6579 /* Retrieve aggregate route's community.
6581 if (aggregate
->community
)
6582 community
= community_dup(aggregate
->community
);
6584 /* Retrieve aggregate route's ecommunity.
6586 if (aggregate
->ecommunity
)
6587 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6589 /* Retrieve aggregate route's lcommunity.
6591 if (aggregate
->lcommunity
)
6592 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6595 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6596 aspath
, community
, ecommunity
,
6597 lcommunity
, atomic_aggregate
, aggregate
);
6600 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6601 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6603 struct bgp_node
*child
;
6604 struct bgp_node
*rn
;
6605 struct bgp_aggregate
*aggregate
;
6606 struct bgp_table
*table
;
6608 table
= bgp
->aggregate
[afi
][safi
];
6610 /* No aggregates configured. */
6611 if (bgp_table_top_nolock(table
) == NULL
)
6614 if (p
->prefixlen
== 0)
6617 if (BGP_PATH_HOLDDOWN(pi
))
6620 child
= bgp_node_get(table
, p
);
6622 /* Aggregate address configuration check. */
6623 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6624 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6625 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6626 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6630 bgp_unlock_node(child
);
6633 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6634 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6636 struct bgp_node
*child
;
6637 struct bgp_node
*rn
;
6638 struct bgp_aggregate
*aggregate
;
6639 struct bgp_table
*table
;
6641 table
= bgp
->aggregate
[afi
][safi
];
6643 /* No aggregates configured. */
6644 if (bgp_table_top_nolock(table
) == NULL
)
6647 if (p
->prefixlen
== 0)
6650 child
= bgp_node_get(table
, p
);
6652 /* Aggregate address configuration check. */
6653 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6654 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6655 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6656 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6657 del
, aggregate
, &rn
->p
);
6660 bgp_unlock_node(child
);
6663 /* Aggregate route attribute. */
6664 #define AGGREGATE_SUMMARY_ONLY 1
6665 #define AGGREGATE_AS_SET 1
6666 #define AGGREGATE_AS_UNSET 0
6668 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6669 afi_t afi
, safi_t safi
)
6671 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6674 struct bgp_node
*rn
;
6675 struct bgp_aggregate
*aggregate
;
6677 /* Convert string to prefix structure. */
6678 ret
= str2prefix(prefix_str
, &p
);
6680 vty_out(vty
, "Malformed prefix\n");
6681 return CMD_WARNING_CONFIG_FAILED
;
6685 /* Old configuration check. */
6686 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6689 "%% There is no aggregate-address configuration.\n");
6690 return CMD_WARNING_CONFIG_FAILED
;
6693 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6694 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6695 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6696 NULL
, NULL
, 0, aggregate
);
6698 /* Unlock aggregate address configuration. */
6699 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6701 if (aggregate
->community
)
6702 community_free(&aggregate
->community
);
6704 if (aggregate
->community_hash
) {
6705 /* Delete all communities in the hash.
6707 hash_clean(aggregate
->community_hash
,
6708 bgp_aggr_community_remove
);
6709 /* Free up the community_hash.
6711 hash_free(aggregate
->community_hash
);
6714 if (aggregate
->ecommunity
)
6715 ecommunity_free(&aggregate
->ecommunity
);
6717 if (aggregate
->ecommunity_hash
) {
6718 /* Delete all ecommunities in the hash.
6720 hash_clean(aggregate
->ecommunity_hash
,
6721 bgp_aggr_ecommunity_remove
);
6722 /* Free up the ecommunity_hash.
6724 hash_free(aggregate
->ecommunity_hash
);
6727 if (aggregate
->lcommunity
)
6728 lcommunity_free(&aggregate
->lcommunity
);
6730 if (aggregate
->lcommunity_hash
) {
6731 /* Delete all lcommunities in the hash.
6733 hash_clean(aggregate
->lcommunity_hash
,
6734 bgp_aggr_lcommunity_remove
);
6735 /* Free up the lcommunity_hash.
6737 hash_free(aggregate
->lcommunity_hash
);
6740 if (aggregate
->aspath
)
6741 aspath_free(aggregate
->aspath
);
6743 if (aggregate
->aspath_hash
) {
6744 /* Delete all as-paths in the hash.
6746 hash_clean(aggregate
->aspath_hash
,
6747 bgp_aggr_aspath_remove
);
6748 /* Free up the aspath_hash.
6750 hash_free(aggregate
->aspath_hash
);
6753 bgp_aggregate_free(aggregate
);
6754 bgp_unlock_node(rn
);
6755 bgp_unlock_node(rn
);
6760 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6761 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6764 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6767 struct bgp_node
*rn
;
6768 struct bgp_aggregate
*aggregate
;
6769 uint8_t as_set_new
= as_set
;
6771 /* Convert string to prefix structure. */
6772 ret
= str2prefix(prefix_str
, &p
);
6774 vty_out(vty
, "Malformed prefix\n");
6775 return CMD_WARNING_CONFIG_FAILED
;
6779 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6780 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6781 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6783 return CMD_WARNING_CONFIG_FAILED
;
6786 /* Old configuration check. */
6787 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6788 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6791 vty_out(vty
, "There is already same aggregate network.\n");
6792 /* try to remove the old entry */
6793 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6795 vty_out(vty
, "Error deleting aggregate.\n");
6796 bgp_unlock_node(rn
);
6797 return CMD_WARNING_CONFIG_FAILED
;
6801 /* Make aggregate address structure. */
6802 aggregate
= bgp_aggregate_new();
6803 aggregate
->summary_only
= summary_only
;
6805 /* Network operators MUST NOT locally generate any new
6806 * announcements containing AS_SET or AS_CONFED_SET. If they have
6807 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6808 * SHOULD withdraw those routes and re-announce routes for the
6809 * aggregate or component prefixes (i.e., the more-specific routes
6810 * subsumed by the previously aggregated route) without AS_SET
6811 * or AS_CONFED_SET in the updates.
6813 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6814 if (as_set
== AGGREGATE_AS_SET
) {
6815 as_set_new
= AGGREGATE_AS_UNSET
;
6817 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6820 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6824 aggregate
->as_set
= as_set_new
;
6825 aggregate
->safi
= safi
;
6828 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6829 route_map_counter_decrement(aggregate
->rmap
.map
);
6830 aggregate
->rmap
.name
=
6831 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6832 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6833 route_map_counter_increment(aggregate
->rmap
.map
);
6835 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6837 /* Aggregate address insert into BGP routing table. */
6838 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6843 DEFUN (aggregate_address
,
6844 aggregate_address_cmd
,
6845 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6846 "Configure BGP aggregate entries\n"
6847 "Aggregate prefix\n"
6848 "Generate AS set path information\n"
6849 "Filter more specific routes from updates\n"
6850 "Filter more specific routes from updates\n"
6851 "Generate AS set path information\n"
6852 "Apply route map to aggregate network\n"
6853 "Name of route map\n")
6856 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6857 char *prefix
= argv
[idx
]->arg
;
6859 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6860 : AGGREGATE_AS_UNSET
;
6862 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6863 ? AGGREGATE_SUMMARY_ONLY
6867 argv_find(argv
, argc
, "WORD", &idx
);
6869 rmap
= argv
[idx
]->arg
;
6871 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6872 rmap
, summary_only
, as_set
);
6875 DEFUN (aggregate_address_mask
,
6876 aggregate_address_mask_cmd
,
6877 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6878 "Configure BGP aggregate entries\n"
6879 "Aggregate address\n"
6881 "Generate AS set path information\n"
6882 "Filter more specific routes from updates\n"
6883 "Filter more specific routes from updates\n"
6884 "Generate AS set path information\n"
6885 "Apply route map to aggregate network\n"
6886 "Name of route map\n")
6889 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6890 char *prefix
= argv
[idx
]->arg
;
6891 char *mask
= argv
[idx
+ 1]->arg
;
6894 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6895 : AGGREGATE_AS_UNSET
;
6897 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6898 ? AGGREGATE_SUMMARY_ONLY
6901 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6903 rmap
= argv
[idx
]->arg
;
6905 char prefix_str
[BUFSIZ
];
6906 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6909 vty_out(vty
, "%% Inconsistent address and mask\n");
6910 return CMD_WARNING_CONFIG_FAILED
;
6913 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6914 rmap
, summary_only
, as_set
);
6917 DEFUN (no_aggregate_address
,
6918 no_aggregate_address_cmd
,
6919 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6921 "Configure BGP aggregate entries\n"
6922 "Aggregate prefix\n"
6923 "Generate AS set path information\n"
6924 "Filter more specific routes from updates\n"
6925 "Filter more specific routes from updates\n"
6926 "Generate AS set path information\n"
6927 "Apply route map to aggregate network\n"
6928 "Name of route map\n")
6931 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6932 char *prefix
= argv
[idx
]->arg
;
6933 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6936 DEFUN (no_aggregate_address_mask
,
6937 no_aggregate_address_mask_cmd
,
6938 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6940 "Configure BGP aggregate entries\n"
6941 "Aggregate address\n"
6943 "Generate AS set path information\n"
6944 "Filter more specific routes from updates\n"
6945 "Filter more specific routes from updates\n"
6946 "Generate AS set path information\n"
6947 "Apply route map to aggregate network\n"
6948 "Name of route map\n")
6951 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6952 char *prefix
= argv
[idx
]->arg
;
6953 char *mask
= argv
[idx
+ 1]->arg
;
6955 char prefix_str
[BUFSIZ
];
6956 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6959 vty_out(vty
, "%% Inconsistent address and mask\n");
6960 return CMD_WARNING_CONFIG_FAILED
;
6963 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6966 DEFUN (ipv6_aggregate_address
,
6967 ipv6_aggregate_address_cmd
,
6968 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6969 "Configure BGP aggregate entries\n"
6970 "Aggregate prefix\n"
6971 "Generate AS set path information\n"
6972 "Filter more specific routes from updates\n"
6973 "Filter more specific routes from updates\n"
6974 "Generate AS set path information\n"
6975 "Apply route map to aggregate network\n"
6976 "Name of route map\n")
6979 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6980 char *prefix
= argv
[idx
]->arg
;
6983 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6984 : AGGREGATE_AS_UNSET
;
6987 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6988 ? AGGREGATE_SUMMARY_ONLY
6991 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6993 rmap
= argv
[idx
]->arg
;
6995 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6999 DEFUN (no_ipv6_aggregate_address
,
7000 no_ipv6_aggregate_address_cmd
,
7001 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
7003 "Configure BGP aggregate entries\n"
7004 "Aggregate prefix\n"
7005 "Generate AS set path information\n"
7006 "Filter more specific routes from updates\n"
7007 "Filter more specific routes from updates\n"
7008 "Generate AS set path information\n"
7009 "Apply route map to aggregate network\n"
7010 "Name of route map\n")
7013 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7014 char *prefix
= argv
[idx
]->arg
;
7015 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7018 /* Redistribute route treatment. */
7019 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7020 const union g_addr
*nexthop
, ifindex_t ifindex
,
7021 enum nexthop_types_t nhtype
, uint32_t metric
,
7022 uint8_t type
, unsigned short instance
,
7025 struct bgp_path_info
*new;
7026 struct bgp_path_info
*bpi
;
7027 struct bgp_path_info rmap_path
;
7028 struct bgp_node
*bn
;
7030 struct attr
*new_attr
;
7032 route_map_result_t ret
;
7033 struct bgp_redist
*red
;
7035 /* Make default attribute. */
7036 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7038 * This must not be NULL to satisfy Coverity SA
7040 assert(attr
.aspath
);
7043 case NEXTHOP_TYPE_IFINDEX
:
7045 case NEXTHOP_TYPE_IPV4
:
7046 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7047 attr
.nexthop
= nexthop
->ipv4
;
7049 case NEXTHOP_TYPE_IPV6
:
7050 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7051 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7052 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7054 case NEXTHOP_TYPE_BLACKHOLE
:
7055 switch (p
->family
) {
7057 attr
.nexthop
.s_addr
= INADDR_ANY
;
7060 memset(&attr
.mp_nexthop_global
, 0,
7061 sizeof(attr
.mp_nexthop_global
));
7062 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7067 attr
.nh_ifindex
= ifindex
;
7070 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7073 afi
= family2afi(p
->family
);
7075 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7077 struct attr attr_new
;
7079 /* Copy attribute for modification. */
7082 if (red
->redist_metric_flag
)
7083 attr_new
.med
= red
->redist_metric
;
7085 /* Apply route-map. */
7086 if (red
->rmap
.name
) {
7087 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7088 rmap_path
.peer
= bgp
->peer_self
;
7089 rmap_path
.attr
= &attr_new
;
7091 SET_FLAG(bgp
->peer_self
->rmap_type
,
7092 PEER_RMAP_TYPE_REDISTRIBUTE
);
7094 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7097 bgp
->peer_self
->rmap_type
= 0;
7099 if (ret
== RMAP_DENYMATCH
) {
7100 /* Free uninterned attribute. */
7101 bgp_attr_flush(&attr_new
);
7103 /* Unintern original. */
7104 aspath_unintern(&attr
.aspath
);
7105 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7110 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7111 bgp_attr_add_gshut_community(&attr_new
);
7113 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7114 SAFI_UNICAST
, p
, NULL
);
7116 new_attr
= bgp_attr_intern(&attr_new
);
7118 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
7120 if (bpi
->peer
== bgp
->peer_self
7121 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7125 /* Ensure the (source route) type is updated. */
7127 if (attrhash_cmp(bpi
->attr
, new_attr
)
7128 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7129 bgp_attr_unintern(&new_attr
);
7130 aspath_unintern(&attr
.aspath
);
7131 bgp_unlock_node(bn
);
7134 /* The attribute is changed. */
7135 bgp_path_info_set_flag(bn
, bpi
,
7136 BGP_PATH_ATTR_CHANGED
);
7138 /* Rewrite BGP route information. */
7139 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7140 bgp_path_info_restore(bn
, bpi
);
7142 bgp_aggregate_decrement(
7143 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7144 bgp_attr_unintern(&bpi
->attr
);
7145 bpi
->attr
= new_attr
;
7146 bpi
->uptime
= bgp_clock();
7148 /* Process change. */
7149 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7151 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7152 bgp_unlock_node(bn
);
7153 aspath_unintern(&attr
.aspath
);
7155 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7157 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7159 vpn_leak_from_vrf_update(
7160 bgp_get_default(), bgp
, bpi
);
7166 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7167 bgp
->peer_self
, new_attr
, bn
);
7168 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7170 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7171 bgp_path_info_add(bn
, new);
7172 bgp_unlock_node(bn
);
7173 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7175 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7176 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7178 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7182 /* Unintern original. */
7183 aspath_unintern(&attr
.aspath
);
7186 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7187 unsigned short instance
)
7190 struct bgp_node
*rn
;
7191 struct bgp_path_info
*pi
;
7192 struct bgp_redist
*red
;
7194 afi
= family2afi(p
->family
);
7196 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7198 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7199 SAFI_UNICAST
, p
, NULL
);
7201 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7202 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7206 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7207 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7209 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7212 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7213 bgp_path_info_delete(rn
, pi
);
7214 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7216 bgp_unlock_node(rn
);
7220 /* Withdraw specified route type's route. */
7221 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7222 unsigned short instance
)
7224 struct bgp_node
*rn
;
7225 struct bgp_path_info
*pi
;
7226 struct bgp_table
*table
;
7228 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7230 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7231 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7232 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7233 && pi
->instance
== instance
)
7237 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7238 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7240 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7243 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7245 bgp_path_info_delete(rn
, pi
);
7246 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7251 /* Static function to display route. */
7252 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7259 if (p
->family
== AF_INET
) {
7263 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7266 json_object_string_add(json
, "prefix",
7267 inet_ntop(p
->family
,
7270 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7271 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7272 json_object_string_add(json
, "network", buf2
);
7274 } else if (p
->family
== AF_ETHERNET
) {
7275 prefix2str(p
, buf
, PREFIX_STRLEN
);
7276 len
= vty_out(vty
, "%s", buf
);
7277 } else if (p
->family
== AF_EVPN
) {
7281 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7284 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7285 } else if (p
->family
== AF_FLOWSPEC
) {
7286 route_vty_out_flowspec(vty
, p
, NULL
,
7288 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7289 NLRI_STRING_FORMAT_MIN
, json
);
7294 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7297 json_object_string_add(json
, "prefix",
7298 inet_ntop(p
->family
,
7301 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7302 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7303 json_object_string_add(json
, "network", buf2
);
7310 vty_out(vty
, "\n%*s", 20, " ");
7312 vty_out(vty
, "%*s", len
, " ");
7316 enum bgp_display_type
{
7320 /* Print the short form route status for a bgp_path_info */
7321 static void route_vty_short_status_out(struct vty
*vty
,
7322 struct bgp_path_info
*path
,
7323 json_object
*json_path
)
7327 /* Route status display. */
7328 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7329 json_object_boolean_true_add(json_path
, "removed");
7331 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7332 json_object_boolean_true_add(json_path
, "stale");
7334 if (path
->extra
&& path
->extra
->suppress
)
7335 json_object_boolean_true_add(json_path
, "suppressed");
7337 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7338 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7339 json_object_boolean_true_add(json_path
, "valid");
7342 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7343 json_object_boolean_true_add(json_path
, "history");
7345 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7346 json_object_boolean_true_add(json_path
, "damped");
7348 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7349 json_object_boolean_true_add(json_path
, "bestpath");
7351 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7352 json_object_boolean_true_add(json_path
, "multipath");
7354 /* Internal route. */
7355 if ((path
->peer
->as
)
7356 && (path
->peer
->as
== path
->peer
->local_as
))
7357 json_object_string_add(json_path
, "pathFrom",
7360 json_object_string_add(json_path
, "pathFrom",
7366 /* Route status display. */
7367 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7369 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7371 else if (path
->extra
&& path
->extra
->suppress
)
7373 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7374 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7380 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7382 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7384 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7386 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7391 /* Internal route. */
7392 if (path
->peer
&& (path
->peer
->as
)
7393 && (path
->peer
->as
== path
->peer
->local_as
))
7399 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7401 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7402 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7403 return peer
->hostname
;
7407 /* called from terminal list command */
7408 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7409 struct bgp_path_info
*path
, int display
, safi_t safi
,
7410 json_object
*json_paths
)
7412 struct attr
*attr
= path
->attr
;
7413 json_object
*json_path
= NULL
;
7414 json_object
*json_nexthops
= NULL
;
7415 json_object
*json_nexthop_global
= NULL
;
7416 json_object
*json_nexthop_ll
= NULL
;
7417 json_object
*json_ext_community
= NULL
;
7418 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7420 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7421 bool nexthop_othervrf
= false;
7422 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7423 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7424 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7427 json_path
= json_object_new_object();
7429 /* short status lead text */
7430 route_vty_short_status_out(vty
, path
, json_path
);
7433 /* print prefix and mask */
7435 route_vty_out_route(p
, vty
, json_path
);
7437 vty_out(vty
, "%*s", 17, " ");
7439 route_vty_out_route(p
, vty
, json_path
);
7443 * If vrf id of nexthop is different from that of prefix,
7444 * set up printable string to append
7446 if (path
->extra
&& path
->extra
->bgp_orig
) {
7447 const char *self
= "";
7452 nexthop_othervrf
= true;
7453 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7455 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7456 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7457 "@%s%s", VRFID_NONE_STR
, self
);
7459 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7460 path
->extra
->bgp_orig
->vrf_id
, self
);
7462 if (path
->extra
->bgp_orig
->inst_type
7463 != BGP_INSTANCE_TYPE_DEFAULT
)
7465 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7467 const char *self
= "";
7472 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7476 * For ENCAP and EVPN routes, nexthop address family is not
7477 * neccessarily the same as the prefix address family.
7478 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7479 * EVPN routes are also exchanged with a MP nexthop. Currently,
7481 * is only IPv4, the value will be present in either
7483 * attr->mp_nexthop_global_in
7485 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7488 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7492 sprintf(nexthop
, "%s",
7493 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7497 sprintf(nexthop
, "%s",
7498 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7502 sprintf(nexthop
, "?");
7507 json_nexthop_global
= json_object_new_object();
7509 json_object_string_add(json_nexthop_global
, "ip",
7512 if (nexthop_hostname
)
7513 json_object_string_add(json_nexthop_global
,
7517 json_object_string_add(json_nexthop_global
, "afi",
7518 (af
== AF_INET
) ? "ipv4"
7520 json_object_boolean_true_add(json_nexthop_global
,
7523 vty_out(vty
, "%s%s",
7524 nexthop_hostname
? nexthop_hostname
: nexthop
,
7526 } else if (safi
== SAFI_EVPN
) {
7528 json_nexthop_global
= json_object_new_object();
7530 json_object_string_add(json_nexthop_global
, "ip",
7531 inet_ntoa(attr
->nexthop
));
7533 if (nexthop_hostname
)
7534 json_object_string_add(json_nexthop_global
,
7538 json_object_string_add(json_nexthop_global
, "afi",
7540 json_object_boolean_true_add(json_nexthop_global
,
7543 vty_out(vty
, "%-16s%s",
7544 nexthop_hostname
? nexthop_hostname
7545 : inet_ntoa(attr
->nexthop
),
7547 } else if (safi
== SAFI_FLOWSPEC
) {
7548 if (attr
->nexthop
.s_addr
!= 0) {
7550 json_nexthop_global
= json_object_new_object();
7552 json_object_string_add(json_nexthop_global
,
7554 json_object_string_add(
7555 json_nexthop_global
, "ip",
7556 inet_ntoa(attr
->nexthop
));
7558 if (nexthop_hostname
)
7559 json_object_string_add(
7560 json_nexthop_global
, "hostname",
7563 json_object_boolean_true_add(
7564 json_nexthop_global
,
7567 vty_out(vty
, "%-16s",
7570 : inet_ntoa(attr
->nexthop
));
7573 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7575 json_nexthop_global
= json_object_new_object();
7577 json_object_string_add(json_nexthop_global
, "ip",
7578 inet_ntoa(attr
->nexthop
));
7580 if (nexthop_hostname
)
7581 json_object_string_add(json_nexthop_global
,
7585 json_object_string_add(json_nexthop_global
, "afi",
7587 json_object_boolean_true_add(json_nexthop_global
,
7592 snprintf(buf
, sizeof(buf
), "%s%s",
7593 nexthop_hostname
? nexthop_hostname
7594 : inet_ntoa(attr
->nexthop
),
7596 vty_out(vty
, "%-16s", buf
);
7601 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7606 json_nexthop_global
= json_object_new_object();
7607 json_object_string_add(
7608 json_nexthop_global
, "ip",
7609 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7612 if (nexthop_hostname
)
7613 json_object_string_add(json_nexthop_global
,
7617 json_object_string_add(json_nexthop_global
, "afi",
7619 json_object_string_add(json_nexthop_global
, "scope",
7622 /* We display both LL & GL if both have been
7624 if ((attr
->mp_nexthop_len
7625 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7626 || (path
->peer
->conf_if
)) {
7627 json_nexthop_ll
= json_object_new_object();
7628 json_object_string_add(
7629 json_nexthop_ll
, "ip",
7631 &attr
->mp_nexthop_local
, buf
,
7634 if (nexthop_hostname
)
7635 json_object_string_add(
7636 json_nexthop_ll
, "hostname",
7639 json_object_string_add(json_nexthop_ll
, "afi",
7641 json_object_string_add(json_nexthop_ll
, "scope",
7644 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7645 &attr
->mp_nexthop_local
)
7647 && !attr
->mp_nexthop_prefer_global
)
7648 json_object_boolean_true_add(
7649 json_nexthop_ll
, "used");
7651 json_object_boolean_true_add(
7652 json_nexthop_global
, "used");
7654 json_object_boolean_true_add(
7655 json_nexthop_global
, "used");
7657 /* Display LL if LL/Global both in table unless
7658 * prefer-global is set */
7659 if (((attr
->mp_nexthop_len
7660 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7661 && !attr
->mp_nexthop_prefer_global
)
7662 || (path
->peer
->conf_if
)) {
7663 if (path
->peer
->conf_if
) {
7664 len
= vty_out(vty
, "%s",
7665 path
->peer
->conf_if
);
7666 len
= 16 - len
; /* len of IPv6
7672 vty_out(vty
, "\n%*s", 36, " ");
7674 vty_out(vty
, "%*s", len
, " ");
7682 &attr
->mp_nexthop_local
,
7688 vty_out(vty
, "\n%*s", 36, " ");
7690 vty_out(vty
, "%*s", len
, " ");
7699 &attr
->mp_nexthop_global
,
7705 vty_out(vty
, "\n%*s", 36, " ");
7707 vty_out(vty
, "%*s", len
, " ");
7713 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7717 * Adding "metric" field to match with corresponding
7718 * CLI. "med" will be deprecated in future.
7720 json_object_int_add(json_path
, "med", attr
->med
);
7721 json_object_int_add(json_path
, "metric", attr
->med
);
7723 vty_out(vty
, "%10u", attr
->med
);
7724 else if (!json_paths
)
7728 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7732 * Adding "locPrf" field to match with corresponding
7733 * CLI. "localPref" will be deprecated in future.
7735 json_object_int_add(json_path
, "localpref",
7737 json_object_int_add(json_path
, "locPrf",
7740 vty_out(vty
, "%7u", attr
->local_pref
);
7741 else if (!json_paths
)
7745 json_object_int_add(json_path
, "weight", attr
->weight
);
7747 vty_out(vty
, "%7u ", attr
->weight
);
7751 json_object_string_add(
7752 json_path
, "peerId",
7753 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7761 * Adding "path" field to match with corresponding
7762 * CLI. "aspath" will be deprecated in future.
7764 json_object_string_add(json_path
, "aspath",
7766 json_object_string_add(json_path
, "path",
7769 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7774 json_object_string_add(json_path
, "origin",
7775 bgp_origin_long_str
[attr
->origin
]);
7777 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7780 if (safi
== SAFI_EVPN
&&
7781 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7782 json_ext_community
= json_object_new_object();
7783 json_object_string_add(json_ext_community
,
7785 attr
->ecommunity
->str
);
7786 json_object_object_add(json_path
,
7787 "extendedCommunity",
7788 json_ext_community
);
7792 json_object_boolean_true_add(json_path
,
7793 "announceNexthopSelf");
7794 if (nexthop_othervrf
) {
7795 json_object_string_add(json_path
, "nhVrfName",
7798 json_object_int_add(json_path
, "nhVrfId",
7799 ((nexthop_vrfid
== VRF_UNKNOWN
)
7801 : (int)nexthop_vrfid
));
7806 if (json_nexthop_global
|| json_nexthop_ll
) {
7807 json_nexthops
= json_object_new_array();
7809 if (json_nexthop_global
)
7810 json_object_array_add(json_nexthops
,
7811 json_nexthop_global
);
7813 if (json_nexthop_ll
)
7814 json_object_array_add(json_nexthops
,
7817 json_object_object_add(json_path
, "nexthops",
7821 json_object_array_add(json_paths
, json_path
);
7825 if (safi
== SAFI_EVPN
&&
7826 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7827 vty_out(vty
, "%*s", 20, " ");
7828 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7832 /* prints an additional line, indented, with VNC info, if
7834 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7835 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7840 /* called from terminal list command */
7841 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7842 safi_t safi
, bool use_json
, json_object
*json_ar
)
7844 json_object
*json_status
= NULL
;
7845 json_object
*json_net
= NULL
;
7848 /* Route status display. */
7850 json_status
= json_object_new_object();
7851 json_net
= json_object_new_object();
7858 /* print prefix and mask */
7860 if (safi
== SAFI_EVPN
)
7861 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7862 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7863 json_object_string_add(
7864 json_net
, "addrPrefix",
7865 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7867 json_object_int_add(json_net
, "prefixLen",
7869 prefix2str(p
, buff
, PREFIX_STRLEN
);
7870 json_object_string_add(json_net
, "network", buff
);
7873 route_vty_out_route(p
, vty
, NULL
);
7875 /* Print attribute */
7878 if (p
->family
== AF_INET
7879 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7880 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7881 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7882 json_object_string_add(
7883 json_net
, "nextHop",
7885 attr
->mp_nexthop_global_in
));
7887 json_object_string_add(
7888 json_net
, "nextHop",
7889 inet_ntoa(attr
->nexthop
));
7890 } else if (p
->family
== AF_INET6
7891 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7894 json_object_string_add(
7895 json_net
, "nextHopGlobal",
7897 &attr
->mp_nexthop_global
, buf
,
7899 } else if (p
->family
== AF_EVPN
&&
7900 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7901 json_object_string_add(json_net
,
7902 "nextHop", inet_ntoa(
7903 attr
->mp_nexthop_global_in
));
7906 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7907 json_object_int_add(json_net
, "metric",
7910 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7913 * Adding "locPrf" field to match with
7914 * corresponding CLI. "localPref" will be
7915 * deprecated in future.
7917 json_object_int_add(json_net
, "localPref",
7919 json_object_int_add(json_net
, "locPrf",
7923 json_object_int_add(json_net
, "weight", attr
->weight
);
7929 * Adding "path" field to match with
7930 * corresponding CLI. "localPref" will be
7931 * deprecated in future.
7933 json_object_string_add(json_net
, "asPath",
7935 json_object_string_add(json_net
, "path",
7940 json_object_string_add(json_net
, "bgpOriginCode",
7941 bgp_origin_str
[attr
->origin
]);
7943 if (p
->family
== AF_INET
7944 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7945 || safi
== SAFI_EVPN
7946 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7947 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7948 || safi
== SAFI_EVPN
)
7949 vty_out(vty
, "%-16s",
7951 attr
->mp_nexthop_global_in
));
7953 vty_out(vty
, "%-16s",
7954 inet_ntoa(attr
->nexthop
));
7955 } else if (p
->family
== AF_INET6
7956 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7963 &attr
->mp_nexthop_global
, buf
,
7967 vty_out(vty
, "\n%*s", 36, " ");
7969 vty_out(vty
, "%*s", len
, " ");
7972 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7973 vty_out(vty
, "%10u", attr
->med
);
7977 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7978 vty_out(vty
, "%7u", attr
->local_pref
);
7982 vty_out(vty
, "%7u ", attr
->weight
);
7986 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7989 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7993 json_object_boolean_true_add(json_status
, "*");
7994 json_object_boolean_true_add(json_status
, ">");
7995 json_object_object_add(json_net
, "appliedStatusSymbols",
7998 prefix2str(p
, buff
, PREFIX_STRLEN
);
7999 json_object_object_add(json_ar
, buff
, json_net
);
8004 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
8005 struct bgp_path_info
*path
, int display
, safi_t safi
,
8008 json_object
*json_out
= NULL
;
8010 mpls_label_t label
= MPLS_INVALID_LABEL
;
8016 json_out
= json_object_new_object();
8018 /* short status lead text */
8019 route_vty_short_status_out(vty
, path
, json_out
);
8021 /* print prefix and mask */
8024 route_vty_out_route(p
, vty
, NULL
);
8026 vty_out(vty
, "%*s", 17, " ");
8029 /* Print attribute */
8031 if (((p
->family
== AF_INET
)
8032 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8033 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8034 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8035 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8036 || safi
== SAFI_EVPN
) {
8038 json_object_string_add(
8039 json_out
, "mpNexthopGlobalIn",
8040 inet_ntoa(attr
->mp_nexthop_global_in
));
8042 vty_out(vty
, "%-16s",
8043 inet_ntoa(attr
->mp_nexthop_global_in
));
8046 json_object_string_add(
8047 json_out
, "nexthop",
8048 inet_ntoa(attr
->nexthop
));
8050 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8052 } else if (((p
->family
== AF_INET6
)
8053 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8054 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8055 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8058 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8060 json_object_string_add(
8061 json_out
, "mpNexthopGlobalIn",
8063 &attr
->mp_nexthop_global
,
8064 buf_a
, sizeof(buf_a
)));
8068 &attr
->mp_nexthop_global
,
8069 buf_a
, sizeof(buf_a
)));
8070 } else if (attr
->mp_nexthop_len
8071 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8072 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8073 &attr
->mp_nexthop_global
,
8074 &attr
->mp_nexthop_local
);
8076 json_object_string_add(json_out
,
8077 "mpNexthopGlobalLocal",
8080 vty_out(vty
, "%s", buf_a
);
8084 label
= decode_label(&path
->extra
->label
[0]);
8086 if (bgp_is_valid_label(&label
)) {
8088 json_object_int_add(json_out
, "notag", label
);
8089 json_object_array_add(json
, json_out
);
8091 vty_out(vty
, "notag/%d", label
);
8097 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
8098 struct bgp_path_info
*path
, int display
,
8099 json_object
*json_paths
)
8102 char buf
[BUFSIZ
] = {0};
8103 json_object
*json_path
= NULL
;
8104 json_object
*json_nexthop
= NULL
;
8105 json_object
*json_overlay
= NULL
;
8111 json_path
= json_object_new_object();
8112 json_overlay
= json_object_new_object();
8113 json_nexthop
= json_object_new_object();
8116 /* short status lead text */
8117 route_vty_short_status_out(vty
, path
, json_path
);
8119 /* print prefix and mask */
8121 route_vty_out_route(p
, vty
, json_path
);
8123 vty_out(vty
, "%*s", 17, " ");
8125 /* Print attribute */
8128 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8132 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8134 vty_out(vty
, "%-16s", buf
);
8136 json_object_string_add(json_nexthop
, "ip", buf
);
8138 json_object_string_add(json_nexthop
, "afi", "ipv4");
8140 json_object_object_add(json_path
, "nexthop",
8145 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8146 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8148 vty_out(vty
, "%s(%s)", buf
, buf1
);
8150 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8152 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8155 json_object_string_add(json_nexthop
, "afi", "ipv6");
8157 json_object_object_add(json_path
, "nexthop",
8165 json_object_string_add(json_nexthop
, "Error",
8166 "Unsupported address-family");
8170 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
8173 vty_out(vty
, "%s", str
);
8175 json_object_string_add(json_overlay
, "esi", str
);
8177 XFREE(MTYPE_TMP
, str
);
8179 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8180 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8182 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8183 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8188 vty_out(vty
, "/%s", buf
);
8190 json_object_string_add(json_overlay
, "gw", buf
);
8192 if (attr
->ecommunity
) {
8194 struct ecommunity_val
*routermac
= ecommunity_lookup(
8195 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8196 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8199 mac
= ecom_mac2str((char *)routermac
->val
);
8202 vty_out(vty
, "/%s", (char *)mac
);
8204 json_object_string_add(json_overlay
, "rmac",
8207 XFREE(MTYPE_TMP
, mac
);
8214 json_object_object_add(json_path
, "overlay", json_overlay
);
8216 json_object_array_add(json_paths
, json_path
);
8220 /* dampening route */
8221 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8222 struct bgp_path_info
*path
, int display
, afi_t afi
,
8223 safi_t safi
, bool use_json
, json_object
*json
)
8227 char timebuf
[BGP_UPTIME_LEN
];
8229 /* short status lead text */
8230 route_vty_short_status_out(vty
, path
, json
);
8232 /* print prefix and mask */
8235 route_vty_out_route(p
, vty
, NULL
);
8237 vty_out(vty
, "%*s", 17, " ");
8240 len
= vty_out(vty
, "%s", path
->peer
->host
);
8244 vty_out(vty
, "\n%*s", 34, " ");
8247 json_object_int_add(json
, "peerHost", len
);
8249 vty_out(vty
, "%*s", len
, " ");
8253 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8254 safi
, use_json
, json
);
8257 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8258 BGP_UPTIME_LEN
, afi
, safi
,
8261 /* Print attribute */
8267 json_object_string_add(json
, "asPath",
8270 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8275 json_object_string_add(json
, "origin",
8276 bgp_origin_str
[attr
->origin
]);
8278 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8285 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8286 struct bgp_path_info
*path
, int display
, afi_t afi
,
8287 safi_t safi
, bool use_json
, json_object
*json
)
8290 struct bgp_damp_info
*bdi
;
8291 char timebuf
[BGP_UPTIME_LEN
];
8297 bdi
= path
->extra
->damp_info
;
8299 /* short status lead text */
8300 route_vty_short_status_out(vty
, path
, json
);
8302 /* print prefix and mask */
8305 route_vty_out_route(p
, vty
, NULL
);
8307 vty_out(vty
, "%*s", 17, " ");
8310 len
= vty_out(vty
, "%s", path
->peer
->host
);
8314 vty_out(vty
, "\n%*s", 33, " ");
8317 json_object_int_add(json
, "peerHost", len
);
8319 vty_out(vty
, "%*s", len
, " ");
8322 len
= vty_out(vty
, "%d", bdi
->flap
);
8329 json_object_int_add(json
, "bdiFlap", len
);
8331 vty_out(vty
, "%*s", len
, " ");
8335 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8338 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8339 BGP_UPTIME_LEN
, 0, NULL
));
8341 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8342 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8344 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8345 BGP_UPTIME_LEN
, afi
, safi
,
8349 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8350 BGP_UPTIME_LEN
, afi
,
8351 safi
, use_json
, json
));
8354 vty_out(vty
, "%*s ", 8, " ");
8357 /* Print attribute */
8363 json_object_string_add(json
, "asPath",
8366 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8371 json_object_string_add(json
, "origin",
8372 bgp_origin_str
[attr
->origin
]);
8374 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8380 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8381 int *first
, const char *header
,
8382 json_object
*json_adv_to
)
8384 char buf1
[INET6_ADDRSTRLEN
];
8385 json_object
*json_peer
= NULL
;
8388 /* 'advertised-to' is a dictionary of peers we have advertised
8390 * prefix too. The key is the peer's IP or swpX, the value is
8392 * hostname if we know it and "" if not.
8394 json_peer
= json_object_new_object();
8397 json_object_string_add(json_peer
, "hostname",
8401 json_object_object_add(json_adv_to
, peer
->conf_if
,
8404 json_object_object_add(
8406 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8410 vty_out(vty
, "%s", header
);
8415 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8417 vty_out(vty
, " %s(%s)", peer
->hostname
,
8420 vty_out(vty
, " %s(%s)", peer
->hostname
,
8421 sockunion2str(&peer
->su
, buf1
,
8425 vty_out(vty
, " %s", peer
->conf_if
);
8428 sockunion2str(&peer
->su
, buf1
,
8434 static void route_vty_out_tx_ids(struct vty
*vty
,
8435 struct bgp_addpath_info_data
*d
)
8439 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8440 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8441 d
->addpath_tx_id
[i
],
8442 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8446 static const char *bgp_path_selection_reason2str(
8447 enum bgp_path_selection_reason reason
)
8450 case bgp_path_selection_none
:
8451 return "Nothing to Select";
8453 case bgp_path_selection_first
:
8454 return "First path received";
8456 case bgp_path_selection_evpn_sticky_mac
:
8457 return "EVPN Sticky Mac";
8459 case bgp_path_selection_evpn_seq
:
8460 return "EVPN sequence number";
8462 case bgp_path_selection_evpn_lower_ip
:
8463 return "EVPN lower IP";
8465 case bgp_path_selection_weight
:
8468 case bgp_path_selection_local_pref
:
8469 return "Local Pref";
8471 case bgp_path_selection_local_route
:
8472 return "Local Route";
8474 case bgp_path_selection_confed_as_path
:
8475 return "Confederation based AS Path";
8477 case bgp_path_selection_as_path
:
8480 case bgp_path_selection_origin
:
8483 case bgp_path_selection_med
:
8486 case bgp_path_selection_peer
:
8489 case bgp_path_selection_confed
:
8490 return "Confed Peer Type";
8492 case bgp_path_selection_igp_metric
:
8493 return "IGP Metric";
8495 case bgp_path_selection_older
:
8496 return "Older Path";
8498 case bgp_path_selection_router_id
:
8501 case bgp_path_selection_cluster_length
:
8502 return "Cluser length";
8504 case bgp_path_selection_stale
:
8505 return "Path Staleness";
8507 case bgp_path_selection_local_configured
:
8508 return "Locally configured route";
8510 case bgp_path_selection_neighbor_ip
:
8511 return "Neighbor IP";
8513 case bgp_path_selection_default
:
8514 return "Nothing left to compare";
8517 return "Invalid (internal error)";
8520 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8521 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8522 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8524 char buf
[INET6_ADDRSTRLEN
];
8526 char buf2
[EVPN_ROUTE_STRLEN
];
8527 struct attr
*attr
= path
->attr
;
8528 int sockunion_vty_out(struct vty
*, union sockunion
*);
8530 json_object
*json_bestpath
= NULL
;
8531 json_object
*json_cluster_list
= NULL
;
8532 json_object
*json_cluster_list_list
= NULL
;
8533 json_object
*json_ext_community
= NULL
;
8534 json_object
*json_last_update
= NULL
;
8535 json_object
*json_pmsi
= NULL
;
8536 json_object
*json_nexthop_global
= NULL
;
8537 json_object
*json_nexthop_ll
= NULL
;
8538 json_object
*json_nexthops
= NULL
;
8539 json_object
*json_path
= NULL
;
8540 json_object
*json_peer
= NULL
;
8541 json_object
*json_string
= NULL
;
8542 json_object
*json_adv_to
= NULL
;
8544 struct listnode
*node
, *nnode
;
8546 int addpath_capable
;
8548 unsigned int first_as
;
8550 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8552 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8555 json_path
= json_object_new_object();
8556 json_peer
= json_object_new_object();
8557 json_nexthop_global
= json_object_new_object();
8565 if (path
->extra
&& path
->extra
->num_labels
) {
8566 bgp_evpn_label2str(path
->extra
->label
,
8567 path
->extra
->num_labels
, tag_buf
,
8570 if (safi
== SAFI_EVPN
) {
8572 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8573 buf2
, sizeof(buf2
));
8574 vty_out(vty
, " Route %s", buf2
);
8575 if (tag_buf
[0] != '\0')
8576 vty_out(vty
, " VNI %s", tag_buf
);
8580 json_object_string_add(json_path
, "VNI",
8585 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8586 struct bgp_path_info
*parent_ri
;
8587 struct bgp_node
*rn
, *prn
;
8589 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8590 rn
= parent_ri
->net
;
8591 if (rn
&& rn
->prn
) {
8593 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8594 buf1
, sizeof(buf1
));
8595 if (is_pi_family_evpn(parent_ri
)) {
8596 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8597 buf2
, sizeof(buf2
));
8598 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8600 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8605 /* Line1 display AS-path, Aggregator */
8608 if (!attr
->aspath
->json
)
8609 aspath_str_update(attr
->aspath
, true);
8610 json_object_lock(attr
->aspath
->json
);
8611 json_object_object_add(json_path
, "aspath",
8612 attr
->aspath
->json
);
8614 if (attr
->aspath
->segments
)
8615 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8617 vty_out(vty
, " Local");
8621 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8623 json_object_boolean_true_add(json_path
, "removed");
8625 vty_out(vty
, ", (removed)");
8628 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8630 json_object_boolean_true_add(json_path
, "stale");
8632 vty_out(vty
, ", (stale)");
8635 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8637 json_object_int_add(json_path
, "aggregatorAs",
8638 attr
->aggregator_as
);
8639 json_object_string_add(
8640 json_path
, "aggregatorId",
8641 inet_ntoa(attr
->aggregator_addr
));
8643 vty_out(vty
, ", (aggregated by %u %s)",
8644 attr
->aggregator_as
,
8645 inet_ntoa(attr
->aggregator_addr
));
8649 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8650 PEER_FLAG_REFLECTOR_CLIENT
)) {
8652 json_object_boolean_true_add(json_path
,
8653 "rxedFromRrClient");
8655 vty_out(vty
, ", (Received from a RR-client)");
8658 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8659 PEER_FLAG_RSERVER_CLIENT
)) {
8661 json_object_boolean_true_add(json_path
,
8662 "rxedFromRsClient");
8664 vty_out(vty
, ", (Received from a RS-client)");
8667 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8669 json_object_boolean_true_add(json_path
,
8670 "dampeningHistoryEntry");
8672 vty_out(vty
, ", (history entry)");
8673 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8675 json_object_boolean_true_add(json_path
,
8676 "dampeningSuppressed");
8678 vty_out(vty
, ", (suppressed due to dampening)");
8684 /* Line2 display Next-hop, Neighbor, Router-id */
8685 /* Display the nexthop */
8686 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8687 || bn
->p
.family
== AF_EVPN
)
8688 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8689 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8690 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8691 || safi
== SAFI_EVPN
) {
8693 json_object_string_add(
8694 json_nexthop_global
, "ip",
8695 inet_ntoa(attr
->mp_nexthop_global_in
));
8697 if (nexthop_hostname
)
8698 json_object_string_add(
8699 json_nexthop_global
, "hostname",
8706 attr
->mp_nexthop_global_in
));
8709 json_object_string_add(
8710 json_nexthop_global
, "ip",
8711 inet_ntoa(attr
->nexthop
));
8713 if (nexthop_hostname
)
8714 json_object_string_add(
8715 json_nexthop_global
, "hostname",
8721 : inet_ntoa(attr
->nexthop
));
8725 json_object_string_add(json_nexthop_global
, "afi",
8729 json_object_string_add(
8730 json_nexthop_global
, "ip",
8731 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8732 buf
, INET6_ADDRSTRLEN
));
8734 if (nexthop_hostname
)
8735 json_object_string_add(json_nexthop_global
,
8739 json_object_string_add(json_nexthop_global
, "afi",
8741 json_object_string_add(json_nexthop_global
, "scope",
8747 : inet_ntop(AF_INET6
,
8748 &attr
->mp_nexthop_global
,
8749 buf
, INET6_ADDRSTRLEN
));
8753 /* Display the IGP cost or 'inaccessible' */
8754 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8756 json_object_boolean_false_add(json_nexthop_global
,
8759 vty_out(vty
, " (inaccessible)");
8761 if (path
->extra
&& path
->extra
->igpmetric
) {
8763 json_object_int_add(json_nexthop_global
,
8765 path
->extra
->igpmetric
);
8767 vty_out(vty
, " (metric %u)",
8768 path
->extra
->igpmetric
);
8771 /* IGP cost is 0, display this only for json */
8774 json_object_int_add(json_nexthop_global
,
8779 json_object_boolean_true_add(json_nexthop_global
,
8783 /* Display peer "from" output */
8784 /* This path was originated locally */
8785 if (path
->peer
== bgp
->peer_self
) {
8787 if (safi
== SAFI_EVPN
8788 || (bn
->p
.family
== AF_INET
8789 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8791 json_object_string_add(json_peer
, "peerId",
8794 vty_out(vty
, " from 0.0.0.0 ");
8797 json_object_string_add(json_peer
, "peerId",
8800 vty_out(vty
, " from :: ");
8804 json_object_string_add(json_peer
, "routerId",
8805 inet_ntoa(bgp
->router_id
));
8807 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8810 /* We RXed this path from one of our peers */
8814 json_object_string_add(json_peer
, "peerId",
8815 sockunion2str(&path
->peer
->su
,
8818 json_object_string_add(json_peer
, "routerId",
8820 &path
->peer
->remote_id
,
8821 buf1
, sizeof(buf1
)));
8823 if (path
->peer
->hostname
)
8824 json_object_string_add(json_peer
, "hostname",
8825 path
->peer
->hostname
);
8827 if (path
->peer
->domainname
)
8828 json_object_string_add(json_peer
, "domainname",
8829 path
->peer
->domainname
);
8831 if (path
->peer
->conf_if
)
8832 json_object_string_add(json_peer
, "interface",
8833 path
->peer
->conf_if
);
8835 if (path
->peer
->conf_if
) {
8836 if (path
->peer
->hostname
8837 && bgp_flag_check(path
->peer
->bgp
,
8838 BGP_FLAG_SHOW_HOSTNAME
))
8839 vty_out(vty
, " from %s(%s)",
8840 path
->peer
->hostname
,
8841 path
->peer
->conf_if
);
8843 vty_out(vty
, " from %s",
8844 path
->peer
->conf_if
);
8846 if (path
->peer
->hostname
8847 && bgp_flag_check(path
->peer
->bgp
,
8848 BGP_FLAG_SHOW_HOSTNAME
))
8849 vty_out(vty
, " from %s(%s)",
8850 path
->peer
->hostname
,
8853 vty_out(vty
, " from %s",
8854 sockunion2str(&path
->peer
->su
,
8859 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8860 vty_out(vty
, " (%s)",
8861 inet_ntoa(attr
->originator_id
));
8863 vty_out(vty
, " (%s)",
8865 &path
->peer
->remote_id
, buf1
,
8871 * Note when vrfid of nexthop is different from that of prefix
8873 if (path
->extra
&& path
->extra
->bgp_orig
) {
8874 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8879 if (path
->extra
->bgp_orig
->inst_type
8880 == BGP_INSTANCE_TYPE_DEFAULT
)
8881 vn
= VRF_DEFAULT_NAME
;
8883 vn
= path
->extra
->bgp_orig
->name
;
8885 json_object_string_add(json_path
, "nhVrfName", vn
);
8887 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8888 json_object_int_add(json_path
, "nhVrfId", -1);
8890 json_object_int_add(json_path
, "nhVrfId",
8891 (int)nexthop_vrfid
);
8894 if (nexthop_vrfid
== VRF_UNKNOWN
)
8895 vty_out(vty
, " vrf ?");
8897 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8903 json_object_boolean_true_add(json_path
,
8904 "announceNexthopSelf");
8906 vty_out(vty
, " announce-nh-self");
8913 /* display the link-local nexthop */
8914 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8916 json_nexthop_ll
= json_object_new_object();
8917 json_object_string_add(
8918 json_nexthop_ll
, "ip",
8919 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8920 buf
, INET6_ADDRSTRLEN
));
8922 if (nexthop_hostname
)
8923 json_object_string_add(json_nexthop_ll
,
8927 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8928 json_object_string_add(json_nexthop_ll
, "scope",
8931 json_object_boolean_true_add(json_nexthop_ll
,
8934 if (!attr
->mp_nexthop_prefer_global
)
8935 json_object_boolean_true_add(json_nexthop_ll
,
8938 json_object_boolean_true_add(
8939 json_nexthop_global
, "used");
8941 vty_out(vty
, " (%s) %s\n",
8942 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8943 buf
, INET6_ADDRSTRLEN
),
8944 attr
->mp_nexthop_prefer_global
8949 /* If we do not have a link-local nexthop then we must flag the
8953 json_object_boolean_true_add(json_nexthop_global
,
8957 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8958 * Int/Ext/Local, Atomic, best */
8960 json_object_string_add(json_path
, "origin",
8961 bgp_origin_long_str
[attr
->origin
]);
8963 vty_out(vty
, " Origin %s",
8964 bgp_origin_long_str
[attr
->origin
]);
8966 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8969 * Adding "metric" field to match with
8970 * corresponding CLI. "med" will be
8971 * deprecated in future.
8973 json_object_int_add(json_path
, "med", attr
->med
);
8974 json_object_int_add(json_path
, "metric", attr
->med
);
8976 vty_out(vty
, ", metric %u", attr
->med
);
8979 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8981 json_object_int_add(json_path
, "localpref",
8984 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8987 if (attr
->weight
!= 0) {
8989 json_object_int_add(json_path
, "weight", attr
->weight
);
8991 vty_out(vty
, ", weight %u", attr
->weight
);
8994 if (attr
->tag
!= 0) {
8996 json_object_int_add(json_path
, "tag", attr
->tag
);
8998 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9001 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9003 json_object_boolean_false_add(json_path
, "valid");
9005 vty_out(vty
, ", invalid");
9006 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9008 json_object_boolean_true_add(json_path
, "valid");
9010 vty_out(vty
, ", valid");
9013 if (path
->peer
!= bgp
->peer_self
) {
9014 if (path
->peer
->as
== path
->peer
->local_as
) {
9015 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9017 json_object_string_add(
9021 vty_out(vty
, ", confed-internal");
9024 json_object_string_add(
9025 json_peer
, "type", "internal");
9027 vty_out(vty
, ", internal");
9030 if (bgp_confederation_peers_check(bgp
,
9033 json_object_string_add(
9037 vty_out(vty
, ", confed-external");
9040 json_object_string_add(
9041 json_peer
, "type", "external");
9043 vty_out(vty
, ", external");
9046 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9048 json_object_boolean_true_add(json_path
, "aggregated");
9049 json_object_boolean_true_add(json_path
, "local");
9051 vty_out(vty
, ", aggregated, local");
9053 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9055 json_object_boolean_true_add(json_path
, "sourced");
9057 vty_out(vty
, ", sourced");
9060 json_object_boolean_true_add(json_path
, "sourced");
9061 json_object_boolean_true_add(json_path
, "local");
9063 vty_out(vty
, ", sourced, local");
9067 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9069 json_object_boolean_true_add(json_path
,
9072 vty_out(vty
, ", atomic-aggregate");
9075 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9076 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9077 && bgp_path_info_mpath_count(path
))) {
9079 json_object_boolean_true_add(json_path
, "multipath");
9081 vty_out(vty
, ", multipath");
9084 // Mark the bestpath(s)
9085 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9086 first_as
= aspath_get_first_as(attr
->aspath
);
9090 json_bestpath
= json_object_new_object();
9091 json_object_int_add(json_bestpath
, "bestpathFromAs",
9095 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9097 vty_out(vty
, ", bestpath-from-AS Local");
9101 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9104 json_bestpath
= json_object_new_object();
9105 json_object_boolean_true_add(json_bestpath
, "overall");
9106 json_object_string_add(
9107 json_bestpath
, "selectionReason",
9108 bgp_path_selection_reason2str(bn
->reason
));
9110 vty_out(vty
, ", best");
9111 vty_out(vty
, " (%s)",
9112 bgp_path_selection_reason2str(bn
->reason
));
9117 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9122 /* Line 4 display Community */
9123 if (attr
->community
) {
9125 if (!attr
->community
->json
)
9126 community_str(attr
->community
, true);
9127 json_object_lock(attr
->community
->json
);
9128 json_object_object_add(json_path
, "community",
9129 attr
->community
->json
);
9131 vty_out(vty
, " Community: %s\n",
9132 attr
->community
->str
);
9136 /* Line 5 display Extended-community */
9137 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9139 json_ext_community
= json_object_new_object();
9140 json_object_string_add(json_ext_community
, "string",
9141 attr
->ecommunity
->str
);
9142 json_object_object_add(json_path
, "extendedCommunity",
9143 json_ext_community
);
9145 vty_out(vty
, " Extended Community: %s\n",
9146 attr
->ecommunity
->str
);
9150 /* Line 6 display Large community */
9151 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9153 if (!attr
->lcommunity
->json
)
9154 lcommunity_str(attr
->lcommunity
, true);
9155 json_object_lock(attr
->lcommunity
->json
);
9156 json_object_object_add(json_path
, "largeCommunity",
9157 attr
->lcommunity
->json
);
9159 vty_out(vty
, " Large Community: %s\n",
9160 attr
->lcommunity
->str
);
9164 /* Line 7 display Originator, Cluster-id */
9165 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9166 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9167 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9169 json_object_string_add(
9170 json_path
, "originatorId",
9171 inet_ntoa(attr
->originator_id
));
9173 vty_out(vty
, " Originator: %s",
9174 inet_ntoa(attr
->originator_id
));
9177 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9181 json_cluster_list
= json_object_new_object();
9182 json_cluster_list_list
=
9183 json_object_new_array();
9185 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9187 json_string
= json_object_new_string(
9188 inet_ntoa(attr
->cluster
9190 json_object_array_add(
9191 json_cluster_list_list
,
9196 * struct cluster_list does not have
9197 * "str" variable like aspath and community
9198 * do. Add this someday if someone asks
9200 * json_object_string_add(json_cluster_list,
9201 * "string", attr->cluster->str);
9203 json_object_object_add(json_cluster_list
,
9205 json_cluster_list_list
);
9206 json_object_object_add(json_path
, "clusterList",
9209 vty_out(vty
, ", Cluster list: ");
9211 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9214 inet_ntoa(attr
->cluster
9224 if (path
->extra
&& path
->extra
->damp_info
)
9225 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9228 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9229 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9230 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9233 json_object_int_add(json_path
, "remoteLabel", label
);
9235 vty_out(vty
, " Remote label: %d\n", label
);
9239 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9240 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9242 json_object_string_add(json_path
, "remoteSid", buf
);
9244 vty_out(vty
, " Remote SID: %s\n", buf
);
9248 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9250 json_object_int_add(json_path
, "labelIndex",
9253 vty_out(vty
, " Label Index: %d\n",
9257 /* Line 8 display Addpath IDs */
9258 if (path
->addpath_rx_id
9259 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9261 json_object_int_add(json_path
, "addpathRxId",
9262 path
->addpath_rx_id
);
9264 /* Keep backwards compatibility with the old API
9265 * by putting TX All's ID in the old field
9267 json_object_int_add(
9268 json_path
, "addpathTxId",
9270 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9272 /* ... but create a specific field for each
9275 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9276 json_object_int_add(
9278 bgp_addpath_names(i
)->id_json_name
,
9279 path
->tx_addpath
.addpath_tx_id
[i
]);
9282 vty_out(vty
, " AddPath ID: RX %u, ",
9283 path
->addpath_rx_id
);
9285 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9289 /* If we used addpath to TX a non-bestpath we need to display
9290 * "Advertised to" on a path-by-path basis
9292 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9295 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9297 bgp_addpath_encode_tx(peer
, afi
, safi
);
9298 has_adj
= bgp_adj_out_lookup(
9300 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9301 &path
->tx_addpath
));
9303 if ((addpath_capable
&& has_adj
)
9304 || (!addpath_capable
&& has_adj
9305 && CHECK_FLAG(path
->flags
,
9306 BGP_PATH_SELECTED
))) {
9307 if (json_path
&& !json_adv_to
)
9308 json_adv_to
= json_object_new_object();
9310 route_vty_out_advertised_to(
9312 " Advertised to:", json_adv_to
);
9318 json_object_object_add(
9319 json_path
, "advertisedTo", json_adv_to
);
9328 /* Line 9 display Uptime */
9329 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9331 json_last_update
= json_object_new_object();
9332 json_object_int_add(json_last_update
, "epoch", tbuf
);
9333 json_object_string_add(json_last_update
, "string",
9335 json_object_object_add(json_path
, "lastUpdate",
9338 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9340 /* Line 10 display PMSI tunnel attribute, if present */
9341 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9343 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9344 PMSI_TNLTYPE_STR_DEFAULT
);
9347 json_pmsi
= json_object_new_object();
9348 json_object_string_add(json_pmsi
, "tunnelType", str
);
9349 json_object_int_add(json_pmsi
, "label",
9350 label2vni(&attr
->label
));
9351 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9353 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9354 str
, label2vni(&attr
->label
));
9357 /* We've constructed the json object for this path, add it to the json
9361 if (json_nexthop_global
|| json_nexthop_ll
) {
9362 json_nexthops
= json_object_new_array();
9364 if (json_nexthop_global
)
9365 json_object_array_add(json_nexthops
,
9366 json_nexthop_global
);
9368 if (json_nexthop_ll
)
9369 json_object_array_add(json_nexthops
,
9372 json_object_object_add(json_path
, "nexthops",
9376 json_object_object_add(json_path
, "peer", json_peer
);
9377 json_object_array_add(json_paths
, json_path
);
9381 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9382 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9383 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9385 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9386 const char *prefix_list_str
, afi_t afi
,
9387 safi_t safi
, enum bgp_show_type type
);
9388 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9389 const char *filter
, afi_t afi
, safi_t safi
,
9390 enum bgp_show_type type
);
9391 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9392 const char *rmap_str
, afi_t afi
, safi_t safi
,
9393 enum bgp_show_type type
);
9394 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9395 const char *com
, int exact
, afi_t afi
,
9397 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9398 const char *prefix
, afi_t afi
, safi_t safi
,
9399 enum bgp_show_type type
);
9400 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9401 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9403 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9404 const char *comstr
, int exact
, afi_t afi
,
9405 safi_t safi
, bool use_json
);
9408 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9409 struct bgp_table
*table
, enum bgp_show_type type
,
9410 void *output_arg
, bool use_json
, char *rd
,
9411 int is_last
, unsigned long *output_cum
,
9412 unsigned long *total_cum
,
9413 unsigned long *json_header_depth
)
9415 struct bgp_path_info
*pi
;
9416 struct bgp_node
*rn
;
9419 unsigned long output_count
= 0;
9420 unsigned long total_count
= 0;
9423 json_object
*json_paths
= NULL
;
9426 if (output_cum
&& *output_cum
!= 0)
9429 if (use_json
&& !*json_header_depth
) {
9431 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9432 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9433 " \"localAS\": %u,\n \"routes\": { ",
9434 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9435 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9438 table
->version
, inet_ntoa(bgp
->router_id
),
9439 bgp
->default_local_pref
, bgp
->as
);
9440 *json_header_depth
= 2;
9442 vty_out(vty
, " \"routeDistinguishers\" : {");
9443 ++*json_header_depth
;
9447 if (use_json
&& rd
) {
9448 vty_out(vty
, " \"%s\" : { ", rd
);
9451 /* Start processing of routes. */
9452 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9453 pi
= bgp_node_get_bgp_path_info(rn
);
9459 json_paths
= json_object_new_array();
9463 for (; pi
; pi
= pi
->next
) {
9465 if (type
== bgp_show_type_flap_statistics
9466 || type
== bgp_show_type_flap_neighbor
9467 || type
== bgp_show_type_dampend_paths
9468 || type
== bgp_show_type_damp_neighbor
) {
9469 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9472 if (type
== bgp_show_type_regexp
) {
9473 regex_t
*regex
= output_arg
;
9475 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9479 if (type
== bgp_show_type_prefix_list
) {
9480 struct prefix_list
*plist
= output_arg
;
9482 if (prefix_list_apply(plist
, &rn
->p
)
9486 if (type
== bgp_show_type_filter_list
) {
9487 struct as_list
*as_list
= output_arg
;
9489 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9490 != AS_FILTER_PERMIT
)
9493 if (type
== bgp_show_type_route_map
) {
9494 struct route_map
*rmap
= output_arg
;
9495 struct bgp_path_info path
;
9496 struct attr dummy_attr
;
9497 route_map_result_t ret
;
9499 dummy_attr
= *pi
->attr
;
9501 path
.peer
= pi
->peer
;
9502 path
.attr
= &dummy_attr
;
9504 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9506 if (ret
== RMAP_DENYMATCH
)
9509 if (type
== bgp_show_type_neighbor
9510 || type
== bgp_show_type_flap_neighbor
9511 || type
== bgp_show_type_damp_neighbor
) {
9512 union sockunion
*su
= output_arg
;
9514 if (pi
->peer
== NULL
9515 || pi
->peer
->su_remote
== NULL
9516 || !sockunion_same(pi
->peer
->su_remote
, su
))
9519 if (type
== bgp_show_type_cidr_only
) {
9520 uint32_t destination
;
9522 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9523 if (IN_CLASSC(destination
)
9524 && rn
->p
.prefixlen
== 24)
9526 if (IN_CLASSB(destination
)
9527 && rn
->p
.prefixlen
== 16)
9529 if (IN_CLASSA(destination
)
9530 && rn
->p
.prefixlen
== 8)
9533 if (type
== bgp_show_type_prefix_longer
) {
9535 if (!prefix_match(p
, &rn
->p
))
9538 if (type
== bgp_show_type_community_all
) {
9539 if (!pi
->attr
->community
)
9542 if (type
== bgp_show_type_community
) {
9543 struct community
*com
= output_arg
;
9545 if (!pi
->attr
->community
9546 || !community_match(pi
->attr
->community
,
9550 if (type
== bgp_show_type_community_exact
) {
9551 struct community
*com
= output_arg
;
9553 if (!pi
->attr
->community
9554 || !community_cmp(pi
->attr
->community
, com
))
9557 if (type
== bgp_show_type_community_list
) {
9558 struct community_list
*list
= output_arg
;
9560 if (!community_list_match(pi
->attr
->community
,
9564 if (type
== bgp_show_type_community_list_exact
) {
9565 struct community_list
*list
= output_arg
;
9567 if (!community_list_exact_match(
9568 pi
->attr
->community
, list
))
9571 if (type
== bgp_show_type_lcommunity
) {
9572 struct lcommunity
*lcom
= output_arg
;
9574 if (!pi
->attr
->lcommunity
9575 || !lcommunity_match(pi
->attr
->lcommunity
,
9580 if (type
== bgp_show_type_lcommunity_exact
) {
9581 struct lcommunity
*lcom
= output_arg
;
9583 if (!pi
->attr
->lcommunity
9584 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9588 if (type
== bgp_show_type_lcommunity_list
) {
9589 struct community_list
*list
= output_arg
;
9591 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9596 == bgp_show_type_lcommunity_list_exact
) {
9597 struct community_list
*list
= output_arg
;
9599 if (!lcommunity_list_exact_match(
9600 pi
->attr
->lcommunity
, list
))
9603 if (type
== bgp_show_type_lcommunity_all
) {
9604 if (!pi
->attr
->lcommunity
)
9607 if (type
== bgp_show_type_dampend_paths
9608 || type
== bgp_show_type_damp_neighbor
) {
9609 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9610 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9614 if (!use_json
&& header
) {
9615 vty_out(vty
, "BGP table version is %" PRIu64
9616 ", local router ID is %s, vrf id ",
9618 inet_ntoa(bgp
->router_id
));
9619 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9620 vty_out(vty
, "%s", VRFID_NONE_STR
);
9622 vty_out(vty
, "%u", bgp
->vrf_id
);
9624 vty_out(vty
, "Default local pref %u, ",
9625 bgp
->default_local_pref
);
9626 vty_out(vty
, "local AS %u\n", bgp
->as
);
9627 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9628 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9629 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9630 if (type
== bgp_show_type_dampend_paths
9631 || type
== bgp_show_type_damp_neighbor
)
9632 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9633 else if (type
== bgp_show_type_flap_statistics
9634 || type
== bgp_show_type_flap_neighbor
)
9635 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9637 vty_out(vty
, BGP_SHOW_HEADER
);
9640 if (rd
!= NULL
&& !display
&& !output_count
) {
9643 "Route Distinguisher: %s\n",
9646 if (type
== bgp_show_type_dampend_paths
9647 || type
== bgp_show_type_damp_neighbor
)
9648 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9649 safi
, use_json
, json_paths
);
9650 else if (type
== bgp_show_type_flap_statistics
9651 || type
== bgp_show_type_flap_neighbor
)
9652 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9653 safi
, use_json
, json_paths
);
9655 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9667 if (p
->family
== AF_FLOWSPEC
) {
9668 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9670 bgp_fs_nlri_get_string((unsigned char *)
9671 p
->u
.prefix_flowspec
.ptr
,
9672 p
->u
.prefix_flowspec
9675 NLRI_STRING_FORMAT_MIN
,
9678 vty_out(vty
, "\"%s/%d\": ",
9680 p
->u
.prefix_flowspec
.prefixlen
);
9682 vty_out(vty
, ",\"%s/%d\": ",
9684 p
->u
.prefix_flowspec
.prefixlen
);
9686 prefix2str(p
, buf2
, sizeof(buf2
));
9688 vty_out(vty
, "\"%s\": ", buf2
);
9690 vty_out(vty
, ",\"%s\": ", buf2
);
9693 json_object_to_json_string_ext(
9694 json_paths
, JSON_C_TO_STRING_PRETTY
));
9695 json_object_free(json_paths
);
9699 json_object_free(json_paths
);
9703 output_count
+= *output_cum
;
9704 *output_cum
= output_count
;
9707 total_count
+= *total_cum
;
9708 *total_cum
= total_count
;
9712 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9716 for (i
= 0; i
< *json_header_depth
; ++i
)
9717 vty_out(vty
, " } ");
9722 /* No route is displayed */
9723 if (output_count
== 0) {
9724 if (type
== bgp_show_type_normal
)
9726 "No BGP prefixes displayed, %ld exist\n",
9730 "\nDisplayed %ld routes and %ld total paths\n",
9731 output_count
, total_count
);
9738 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9739 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9740 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9742 struct bgp_node
*rn
, *next
;
9743 unsigned long output_cum
= 0;
9744 unsigned long total_cum
= 0;
9745 unsigned long json_header_depth
= 0;
9746 struct bgp_table
*itable
;
9749 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9751 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9752 next
= bgp_route_next(rn
);
9753 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9756 itable
= bgp_node_get_bgp_table_info(rn
);
9757 if (itable
!= NULL
) {
9758 struct prefix_rd prd
;
9759 char rd
[RD_ADDRSTRLEN
];
9761 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9762 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9763 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9764 use_json
, rd
, next
== NULL
, &output_cum
,
9765 &total_cum
, &json_header_depth
);
9771 if (output_cum
== 0)
9772 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9776 "\nDisplayed %ld routes and %ld total paths\n",
9777 output_cum
, total_cum
);
9781 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9782 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9784 struct bgp_table
*table
;
9785 unsigned long json_header_depth
= 0;
9788 bgp
= bgp_get_default();
9793 vty_out(vty
, "No BGP process is configured\n");
9795 vty_out(vty
, "{}\n");
9799 table
= bgp
->rib
[afi
][safi
];
9800 /* use MPLS and ENCAP specific shows until they are merged */
9801 if (safi
== SAFI_MPLS_VPN
) {
9802 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9803 output_arg
, use_json
);
9806 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9807 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9808 output_arg
, use_json
,
9811 /* labeled-unicast routes live in the unicast table */
9812 else if (safi
== SAFI_LABELED_UNICAST
)
9813 safi
= SAFI_UNICAST
;
9815 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9816 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9819 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9820 safi_t safi
, bool use_json
)
9822 struct listnode
*node
, *nnode
;
9825 bool route_output
= false;
9828 vty_out(vty
, "{\n");
9830 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9831 route_output
= true;
9834 vty_out(vty
, ",\n");
9838 vty_out(vty
, "\"%s\":",
9839 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9843 vty_out(vty
, "\nInstance %s:\n",
9844 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9848 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9853 vty_out(vty
, "}\n");
9854 else if (!route_output
)
9855 vty_out(vty
, "%% BGP instance not found\n");
9858 /* Header of detailed BGP route information */
9859 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9860 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9861 afi_t afi
, safi_t safi
, json_object
*json
)
9863 struct bgp_path_info
*pi
;
9866 struct listnode
*node
, *nnode
;
9867 char buf1
[RD_ADDRSTRLEN
];
9868 char buf2
[INET6_ADDRSTRLEN
];
9869 char buf3
[EVPN_ROUTE_STRLEN
];
9870 char prefix_str
[BUFSIZ
];
9875 int route_filter_translated_v4
= 0;
9876 int route_filter_v4
= 0;
9877 int route_filter_translated_v6
= 0;
9878 int route_filter_v6
= 0;
9881 int accept_own_nexthop
= 0;
9884 int no_advertise
= 0;
9888 int has_valid_label
= 0;
9889 mpls_label_t label
= 0;
9890 json_object
*json_adv_to
= NULL
;
9893 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9895 if (has_valid_label
)
9896 label
= label_pton(&rn
->local_label
);
9898 if (safi
== SAFI_EVPN
) {
9901 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9902 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9903 : "", prd
? ":" : "",
9904 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9905 buf3
, sizeof(buf3
)));
9907 json_object_string_add(json
, "rd",
9908 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9910 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9914 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9915 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9916 ? prefix_rd2str(prd
, buf1
,
9919 safi
== SAFI_MPLS_VPN
? ":" : "",
9920 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9925 json_object_string_add(json
, "prefix",
9926 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9929 if (has_valid_label
) {
9931 json_object_int_add(json
, "localLabel", label
);
9933 vty_out(vty
, "Local label: %d\n", label
);
9937 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9938 vty_out(vty
, "not allocated\n");
9940 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9942 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9944 if (pi
->extra
&& pi
->extra
->suppress
)
9947 if (pi
->attr
->community
== NULL
)
9950 no_advertise
+= community_include(
9951 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9952 no_export
+= community_include(pi
->attr
->community
,
9953 COMMUNITY_NO_EXPORT
);
9954 local_as
+= community_include(pi
->attr
->community
,
9955 COMMUNITY_LOCAL_AS
);
9956 accept_own
+= community_include(pi
->attr
->community
,
9957 COMMUNITY_ACCEPT_OWN
);
9958 route_filter_translated_v4
+= community_include(
9959 pi
->attr
->community
,
9960 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9961 route_filter_translated_v6
+= community_include(
9962 pi
->attr
->community
,
9963 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9964 route_filter_v4
+= community_include(
9965 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9966 route_filter_v6
+= community_include(
9967 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9968 llgr_stale
+= community_include(pi
->attr
->community
,
9969 COMMUNITY_LLGR_STALE
);
9970 no_llgr
+= community_include(pi
->attr
->community
,
9972 accept_own_nexthop
+=
9973 community_include(pi
->attr
->community
,
9974 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9975 blackhole
+= community_include(pi
->attr
->community
,
9976 COMMUNITY_BLACKHOLE
);
9977 no_peer
+= community_include(pi
->attr
->community
,
9983 vty_out(vty
, "Paths: (%d available", count
);
9985 vty_out(vty
, ", best #%d", best
);
9986 if (safi
== SAFI_UNICAST
) {
9987 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9988 vty_out(vty
, ", table %s",
9991 vty_out(vty
, ", vrf %s",
9995 vty_out(vty
, ", no best path");
9999 ", accept own local route exported and imported in different VRF");
10000 else if (route_filter_translated_v4
)
10002 ", mark translated RTs for VPNv4 route filtering");
10003 else if (route_filter_v4
)
10005 ", attach RT as-is for VPNv4 route filtering");
10006 else if (route_filter_translated_v6
)
10008 ", mark translated RTs for VPNv6 route filtering");
10009 else if (route_filter_v6
)
10011 ", attach RT as-is for VPNv6 route filtering");
10012 else if (llgr_stale
)
10014 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10017 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10018 else if (accept_own_nexthop
)
10020 ", accept local nexthop");
10021 else if (blackhole
)
10022 vty_out(vty
, ", inform peer to blackhole prefix");
10023 else if (no_export
)
10024 vty_out(vty
, ", not advertised to EBGP peer");
10025 else if (no_advertise
)
10026 vty_out(vty
, ", not advertised to any peer");
10028 vty_out(vty
, ", not advertised outside local AS");
10031 ", inform EBGP peer not to advertise to their EBGP peers");
10035 ", Advertisements suppressed by an aggregate.");
10036 vty_out(vty
, ")\n");
10039 /* If we are not using addpath then we can display Advertised to and
10041 * show what peers we advertised the bestpath to. If we are using
10043 * though then we must display Advertised to on a path-by-path basis. */
10044 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10045 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10046 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
10047 if (json
&& !json_adv_to
)
10048 json_adv_to
= json_object_new_object();
10050 route_vty_out_advertised_to(
10052 " Advertised to non peer-group peers:\n ",
10059 json_object_object_add(json
, "advertisedTo",
10064 vty_out(vty
, " Not advertised to any peer");
10065 vty_out(vty
, "\n");
10070 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10071 struct bgp_node
*bgp_node
, struct vty
*vty
,
10072 struct bgp
*bgp
, afi_t afi
,
10073 safi_t safi
, json_object
*json
,
10074 enum bgp_path_type pathtype
, int *display
)
10076 struct bgp_path_info
*pi
;
10078 char rdbuf
[RD_ADDRSTRLEN
];
10079 json_object
*json_header
= NULL
;
10080 json_object
*json_paths
= NULL
;
10082 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
10085 if (json
&& !json_paths
) {
10086 /* Instantiate json_paths only if path is valid */
10087 json_paths
= json_object_new_array();
10089 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10090 json_header
= json_object_new_object();
10092 json_header
= json
;
10096 route_vty_out_detail_header(
10097 vty
, bgp
, bgp_node
, pfx_rd
,
10098 AFI_IP
, safi
, json_header
);
10103 if (pathtype
== BGP_PATH_SHOW_ALL
10104 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10105 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10106 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10107 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10108 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10109 route_vty_out_detail(vty
, bgp
, bgp_node
,
10114 if (json
&& json_paths
) {
10115 json_object_object_add(json_header
, "paths", json_paths
);
10118 json_object_object_add(json
, rdbuf
, json_header
);
10122 /* Display specified route of BGP table. */
10123 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10124 struct bgp_table
*rib
, const char *ip_str
,
10125 afi_t afi
, safi_t safi
,
10126 struct prefix_rd
*prd
, int prefix_check
,
10127 enum bgp_path_type pathtype
, bool use_json
)
10131 struct prefix match
;
10132 struct bgp_node
*rn
;
10133 struct bgp_node
*rm
;
10134 struct bgp_table
*table
;
10135 json_object
*json
= NULL
;
10136 json_object
*json_paths
= NULL
;
10138 /* Check IP address argument. */
10139 ret
= str2prefix(ip_str
, &match
);
10141 vty_out(vty
, "address is malformed\n");
10142 return CMD_WARNING
;
10145 match
.family
= afi2family(afi
);
10148 json
= json_object_new_object();
10150 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10151 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10152 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10154 table
= bgp_node_get_bgp_table_info(rn
);
10158 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10162 && rm
->p
.prefixlen
!= match
.prefixlen
) {
10163 bgp_unlock_node(rm
);
10167 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10168 vty
, bgp
, afi
, safi
, json
,
10169 pathtype
, &display
);
10171 bgp_unlock_node(rm
);
10173 } else if (safi
== SAFI_EVPN
) {
10174 struct bgp_node
*longest_pfx
;
10175 bool is_exact_pfxlen_match
= FALSE
;
10177 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10178 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10180 table
= bgp_node_get_bgp_table_info(rn
);
10184 longest_pfx
= NULL
;
10185 is_exact_pfxlen_match
= FALSE
;
10187 * Search through all the prefixes for a match. The
10188 * pfx's are enumerated in ascending order of pfxlens.
10189 * So, the last pfx match is the longest match. Set
10190 * is_exact_pfxlen_match when we get exact pfxlen match
10192 for (rm
= bgp_table_top(table
); rm
;
10193 rm
= bgp_route_next(rm
)) {
10195 * Get prefixlen of the ip-prefix within type5
10198 if (evpn_type5_prefix_match(&rm
->p
,
10199 &match
) && rm
->info
) {
10202 bgp_evpn_get_type5_prefixlen(&rm
->p
);
10203 if (type5_pfxlen
== match
.prefixlen
) {
10204 is_exact_pfxlen_match
= TRUE
;
10205 bgp_unlock_node(rm
);
10214 if (prefix_check
&& !is_exact_pfxlen_match
)
10220 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10221 vty
, bgp
, afi
, safi
, json
,
10222 pathtype
, &display
);
10224 bgp_unlock_node(rm
);
10226 } else if (safi
== SAFI_FLOWSPEC
) {
10228 json_paths
= json_object_new_array();
10230 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10231 &match
, prefix_check
,
10235 if (use_json
&& display
)
10236 json_object_object_add(json
, "paths", json_paths
);
10238 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
10240 || rn
->p
.prefixlen
== match
.prefixlen
) {
10241 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
10243 pathtype
, &display
);
10246 bgp_unlock_node(rn
);
10251 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10252 json
, JSON_C_TO_STRING_PRETTY
|
10253 JSON_C_TO_STRING_NOSLASHESCAPE
));
10254 json_object_free(json
);
10257 vty_out(vty
, "%% Network not in table\n");
10258 return CMD_WARNING
;
10262 return CMD_SUCCESS
;
10265 /* Display specified route of Main RIB */
10266 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10267 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10268 int prefix_check
, enum bgp_path_type pathtype
,
10272 bgp
= bgp_get_default();
10275 vty_out(vty
, "No BGP process is configured\n");
10277 vty_out(vty
, "{}\n");
10278 return CMD_WARNING
;
10282 /* labeled-unicast routes live in the unicast table */
10283 if (safi
== SAFI_LABELED_UNICAST
)
10284 safi
= SAFI_UNICAST
;
10286 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10287 afi
, safi
, prd
, prefix_check
, pathtype
,
10291 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10292 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10293 safi_t safi
, bool uj
)
10295 struct lcommunity
*lcom
;
10301 b
= buffer_new(1024);
10302 for (i
= 0; i
< argc
; i
++) {
10304 buffer_putc(b
, ' ');
10306 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10308 buffer_putstr(b
, argv
[i
]->arg
);
10312 buffer_putc(b
, '\0');
10314 str
= buffer_getstr(b
);
10317 lcom
= lcommunity_str2com(str
);
10318 XFREE(MTYPE_TMP
, str
);
10320 vty_out(vty
, "%% Large-community malformed\n");
10321 return CMD_WARNING
;
10324 return bgp_show(vty
, bgp
, afi
, safi
,
10325 (exact
? bgp_show_type_lcommunity_exact
10326 : bgp_show_type_lcommunity
),
10330 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10331 const char *lcom
, bool exact
, afi_t afi
,
10332 safi_t safi
, bool uj
)
10334 struct community_list
*list
;
10336 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10337 LARGE_COMMUNITY_LIST_MASTER
);
10338 if (list
== NULL
) {
10339 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10341 return CMD_WARNING
;
10344 return bgp_show(vty
, bgp
, afi
, safi
,
10345 (exact
? bgp_show_type_lcommunity_list_exact
10346 : bgp_show_type_lcommunity_list
),
10350 DEFUN (show_ip_bgp_large_community_list
,
10351 show_ip_bgp_large_community_list_cmd
,
10352 "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]",
10356 BGP_INSTANCE_HELP_STR
10358 BGP_SAFI_WITH_LABEL_HELP_STR
10359 "Display routes matching the large-community-list\n"
10360 "large-community-list number\n"
10361 "large-community-list name\n"
10362 "Exact match of the large-communities\n"
10366 afi_t afi
= AFI_IP6
;
10367 safi_t safi
= SAFI_UNICAST
;
10369 bool exact_match
= 0;
10371 if (argv_find(argv
, argc
, "ip", &idx
))
10373 if (argv_find(argv
, argc
, "view", &idx
)
10374 || argv_find(argv
, argc
, "vrf", &idx
))
10375 vrf
= argv
[++idx
]->arg
;
10376 if (argv_find(argv
, argc
, "ipv4", &idx
)
10377 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10378 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10379 if (argv_find(argv
, argc
, "unicast", &idx
)
10380 || argv_find(argv
, argc
, "multicast", &idx
))
10381 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10384 bool uj
= use_json(argc
, argv
);
10386 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10388 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10389 return CMD_WARNING
;
10392 argv_find(argv
, argc
, "large-community-list", &idx
);
10394 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10396 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10399 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10400 exact_match
, afi
, safi
, uj
);
10402 DEFUN (show_ip_bgp_large_community
,
10403 show_ip_bgp_large_community_cmd
,
10404 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10408 BGP_INSTANCE_HELP_STR
10410 BGP_SAFI_WITH_LABEL_HELP_STR
10411 "Display routes matching the large-communities\n"
10412 "List of large-community numbers\n"
10413 "Exact match of the large-communities\n"
10417 afi_t afi
= AFI_IP6
;
10418 safi_t safi
= SAFI_UNICAST
;
10420 bool exact_match
= 0;
10422 if (argv_find(argv
, argc
, "ip", &idx
))
10424 if (argv_find(argv
, argc
, "view", &idx
)
10425 || argv_find(argv
, argc
, "vrf", &idx
))
10426 vrf
= argv
[++idx
]->arg
;
10427 if (argv_find(argv
, argc
, "ipv4", &idx
)
10428 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10429 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10430 if (argv_find(argv
, argc
, "unicast", &idx
)
10431 || argv_find(argv
, argc
, "multicast", &idx
))
10432 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10435 bool uj
= use_json(argc
, argv
);
10437 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10439 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10440 return CMD_WARNING
;
10443 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10444 if (argv_find(argv
, argc
, "exact-match", &idx
))
10446 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10447 exact_match
, afi
, safi
, uj
);
10449 return bgp_show(vty
, bgp
, afi
, safi
,
10450 bgp_show_type_lcommunity_all
, NULL
, uj
);
10453 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10457 /* BGP route print out function without JSON */
10458 DEFUN (show_ip_bgp
,
10460 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10461 <dampening <parameters>\
10466 |community-list <(1-500)|WORD> [exact-match]\
10467 |A.B.C.D/M longer-prefixes\
10468 |X:X::X:X/M longer-prefixes\
10473 BGP_INSTANCE_HELP_STR
10475 BGP_SAFI_WITH_LABEL_HELP_STR
10476 "Display detailed information about dampening\n"
10477 "Display detail of configured dampening parameters\n"
10478 "Display routes matching the route-map\n"
10479 "A route-map to match on\n"
10480 "Display routes conforming to the prefix-list\n"
10481 "Prefix-list name\n"
10482 "Display routes conforming to the filter-list\n"
10483 "Regular expression access list name\n"
10484 "BGP RIB advertisement statistics\n"
10485 "Display routes matching the community-list\n"
10486 "community-list number\n"
10487 "community-list name\n"
10488 "Exact match of the communities\n"
10490 "Display route and more specific routes\n"
10492 "Display route and more specific routes\n")
10494 afi_t afi
= AFI_IP6
;
10495 safi_t safi
= SAFI_UNICAST
;
10496 int exact_match
= 0;
10497 struct bgp
*bgp
= NULL
;
10500 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10503 return CMD_WARNING
;
10505 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10506 if (argv_find(argv
, argc
, "parameters", &idx
))
10507 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10510 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10511 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10512 safi
, bgp_show_type_prefix_list
);
10514 if (argv_find(argv
, argc
, "filter-list", &idx
))
10515 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10516 safi
, bgp_show_type_filter_list
);
10518 if (argv_find(argv
, argc
, "statistics", &idx
))
10519 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10521 if (argv_find(argv
, argc
, "route-map", &idx
))
10522 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10523 safi
, bgp_show_type_route_map
);
10525 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10526 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10527 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10529 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10530 exact_match
, afi
, safi
);
10532 /* prefix-longer */
10533 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10534 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10535 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10537 bgp_show_type_prefix_longer
);
10539 return CMD_WARNING
;
10542 /* BGP route print out function with JSON */
10543 DEFUN (show_ip_bgp_json
,
10544 show_ip_bgp_json_cmd
,
10545 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10547 |dampening <flap-statistics|dampened-paths>\
10548 |community [AA:NN|local-AS|no-advertise|no-export\
10549 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10550 |accept-own|accept-own-nexthop|route-filter-v6\
10551 |route-filter-v4|route-filter-translated-v6\
10552 |route-filter-translated-v4] [exact-match]\
10557 BGP_INSTANCE_HELP_STR
10559 BGP_SAFI_WITH_LABEL_HELP_STR
10560 "Display only routes with non-natural netmasks\n"
10561 "Display detailed information about dampening\n"
10562 "Display flap statistics of routes\n"
10563 "Display paths suppressed due to dampening\n"
10564 "Display routes matching the communities\n"
10566 "Do not send outside local AS (well-known community)\n"
10567 "Do not advertise to any peer (well-known community)\n"
10568 "Do not export to next AS (well-known community)\n"
10569 "Graceful shutdown (well-known community)\n"
10570 "Do not export to any peer (well-known community)\n"
10571 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10572 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10573 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10574 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10575 "Should accept VPN route with local nexthop (well-known community)\n"
10576 "RT VPNv6 route filtering (well-known community)\n"
10577 "RT VPNv4 route filtering (well-known community)\n"
10578 "RT translated VPNv6 route filtering (well-known community)\n"
10579 "RT translated VPNv4 route filtering (well-known community)\n"
10580 "Exact match of the communities\n"
10583 afi_t afi
= AFI_IP6
;
10584 safi_t safi
= SAFI_UNICAST
;
10585 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10586 struct bgp
*bgp
= NULL
;
10588 int exact_match
= 0;
10589 bool uj
= use_json(argc
, argv
);
10594 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10597 return CMD_WARNING
;
10599 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10600 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10603 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10604 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10605 return bgp_show(vty
, bgp
, afi
, safi
,
10606 bgp_show_type_dampend_paths
, NULL
, uj
);
10607 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10608 return bgp_show(vty
, bgp
, afi
, safi
,
10609 bgp_show_type_flap_statistics
, NULL
,
10613 if (argv_find(argv
, argc
, "community", &idx
)) {
10614 char *maybecomm
= NULL
;
10615 char *community
= NULL
;
10617 if (idx
+ 1 < argc
) {
10618 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10619 maybecomm
= argv
[idx
+ 1]->arg
;
10621 maybecomm
= argv
[idx
+ 1]->text
;
10624 if (maybecomm
&& !strmatch(maybecomm
, "json")
10625 && !strmatch(maybecomm
, "exact-match"))
10626 community
= maybecomm
;
10628 if (argv_find(argv
, argc
, "exact-match", &idx
))
10632 return bgp_show_community(vty
, bgp
, community
,
10633 exact_match
, afi
, safi
, uj
);
10635 return (bgp_show(vty
, bgp
, afi
, safi
,
10636 bgp_show_type_community_all
, NULL
,
10640 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10643 DEFUN (show_ip_bgp_route
,
10644 show_ip_bgp_route_cmd
,
10645 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10646 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10650 BGP_INSTANCE_HELP_STR
10652 BGP_SAFI_WITH_LABEL_HELP_STR
10653 "Network in the BGP routing table to display\n"
10655 "Network in the BGP routing table to display\n"
10657 "Display only the bestpath\n"
10658 "Display only multipaths\n"
10661 int prefix_check
= 0;
10663 afi_t afi
= AFI_IP6
;
10664 safi_t safi
= SAFI_UNICAST
;
10665 char *prefix
= NULL
;
10666 struct bgp
*bgp
= NULL
;
10667 enum bgp_path_type path_type
;
10668 bool uj
= use_json(argc
, argv
);
10672 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10675 return CMD_WARNING
;
10679 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10680 return CMD_WARNING
;
10683 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10684 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10685 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10687 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10688 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10691 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10692 && afi
!= AFI_IP6
) {
10694 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10695 return CMD_WARNING
;
10697 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10698 && afi
!= AFI_IP
) {
10700 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10701 return CMD_WARNING
;
10704 prefix
= argv
[idx
]->arg
;
10706 /* [<bestpath|multipath>] */
10707 if (argv_find(argv
, argc
, "bestpath", &idx
))
10708 path_type
= BGP_PATH_SHOW_BESTPATH
;
10709 else if (argv_find(argv
, argc
, "multipath", &idx
))
10710 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10712 path_type
= BGP_PATH_SHOW_ALL
;
10714 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10718 DEFUN (show_ip_bgp_regexp
,
10719 show_ip_bgp_regexp_cmd
,
10720 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10724 BGP_INSTANCE_HELP_STR
10726 BGP_SAFI_WITH_LABEL_HELP_STR
10727 "Display routes matching the AS path regular expression\n"
10728 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10731 afi_t afi
= AFI_IP6
;
10732 safi_t safi
= SAFI_UNICAST
;
10733 struct bgp
*bgp
= NULL
;
10734 bool uj
= use_json(argc
, argv
);
10735 char *regstr
= NULL
;
10738 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10741 return CMD_WARNING
;
10743 // get index of regex
10744 if (argv_find(argv
, argc
, "REGEX", &idx
))
10745 regstr
= argv
[idx
]->arg
;
10748 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10749 bgp_show_type_regexp
, uj
);
10752 DEFUN (show_ip_bgp_instance_all
,
10753 show_ip_bgp_instance_all_cmd
,
10754 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10758 BGP_INSTANCE_ALL_HELP_STR
10760 BGP_SAFI_WITH_LABEL_HELP_STR
10763 afi_t afi
= AFI_IP
;
10764 safi_t safi
= SAFI_UNICAST
;
10765 struct bgp
*bgp
= NULL
;
10767 bool uj
= use_json(argc
, argv
);
10772 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10775 return CMD_WARNING
;
10777 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10778 return CMD_SUCCESS
;
10781 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10782 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10788 if (!config_bgp_aspath_validate(regstr
)) {
10789 vty_out(vty
, "Invalid character in REGEX %s\n",
10791 return CMD_WARNING_CONFIG_FAILED
;
10794 regex
= bgp_regcomp(regstr
);
10796 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10797 return CMD_WARNING
;
10800 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
10801 bgp_regex_free(regex
);
10805 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10806 const char *prefix_list_str
, afi_t afi
,
10807 safi_t safi
, enum bgp_show_type type
)
10809 struct prefix_list
*plist
;
10811 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10812 if (plist
== NULL
) {
10813 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10815 return CMD_WARNING
;
10818 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10821 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10822 const char *filter
, afi_t afi
, safi_t safi
,
10823 enum bgp_show_type type
)
10825 struct as_list
*as_list
;
10827 as_list
= as_list_lookup(filter
);
10828 if (as_list
== NULL
) {
10829 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10831 return CMD_WARNING
;
10834 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10837 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10838 const char *rmap_str
, afi_t afi
, safi_t safi
,
10839 enum bgp_show_type type
)
10841 struct route_map
*rmap
;
10843 rmap
= route_map_lookup_by_name(rmap_str
);
10845 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10846 return CMD_WARNING
;
10849 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10852 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10853 const char *comstr
, int exact
, afi_t afi
,
10854 safi_t safi
, bool use_json
)
10856 struct community
*com
;
10859 com
= community_str2com(comstr
);
10861 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10862 return CMD_WARNING
;
10865 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10866 (exact
? bgp_show_type_community_exact
10867 : bgp_show_type_community
),
10869 community_free(&com
);
10874 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10875 const char *com
, int exact
, afi_t afi
,
10878 struct community_list
*list
;
10880 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10881 if (list
== NULL
) {
10882 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10883 return CMD_WARNING
;
10886 return bgp_show(vty
, bgp
, afi
, safi
,
10887 (exact
? bgp_show_type_community_list_exact
10888 : bgp_show_type_community_list
),
10892 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10893 const char *prefix
, afi_t afi
, safi_t safi
,
10894 enum bgp_show_type type
)
10901 ret
= str2prefix(prefix
, p
);
10903 vty_out(vty
, "%% Malformed Prefix\n");
10904 return CMD_WARNING
;
10907 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10913 BGP_STATS_MAXBITLEN
= 0,
10915 BGP_STATS_PREFIXES
,
10917 BGP_STATS_UNAGGREGATEABLE
,
10918 BGP_STATS_MAX_AGGREGATEABLE
,
10919 BGP_STATS_AGGREGATES
,
10921 BGP_STATS_ASPATH_COUNT
,
10922 BGP_STATS_ASPATH_MAXHOPS
,
10923 BGP_STATS_ASPATH_TOTHOPS
,
10924 BGP_STATS_ASPATH_MAXSIZE
,
10925 BGP_STATS_ASPATH_TOTSIZE
,
10926 BGP_STATS_ASN_HIGHEST
,
10930 static const char *const table_stats_strs
[] = {
10931 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10932 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10933 [BGP_STATS_RIB
] = "Total Advertisements",
10934 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10935 [BGP_STATS_MAX_AGGREGATEABLE
] =
10936 "Maximum aggregateable prefixes",
10937 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10938 [BGP_STATS_SPACE
] = "Address space advertised",
10939 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10940 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10941 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10942 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10943 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10944 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10945 [BGP_STATS_MAX
] = NULL
,
10948 struct bgp_table_stats
{
10949 struct bgp_table
*table
;
10950 unsigned long long counts
[BGP_STATS_MAX
];
10951 double total_space
;
10955 #define TALLY_SIGFIG 100000
10956 static unsigned long
10957 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10959 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10960 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10961 unsigned long ret
= newtot
/ count
;
10963 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10970 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10971 struct bgp_table_stats
*ts
, unsigned int space
)
10973 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10974 struct bgp_path_info
*pi
;
10979 if (!bgp_node_has_bgp_path_info_data(rn
))
10982 ts
->counts
[BGP_STATS_PREFIXES
]++;
10983 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10986 ts
->counts
[BGP_STATS_AVGPLEN
]
10987 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10988 ts
->counts
[BGP_STATS_AVGPLEN
],
10992 /* check if the prefix is included by any other announcements */
10993 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10994 prn
= bgp_node_parent_nolock(prn
);
10996 if (prn
== NULL
|| prn
== top
) {
10997 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10998 /* announced address space */
11000 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
11001 } else if (bgp_node_has_bgp_path_info_data(prn
))
11002 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11005 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11006 ts
->counts
[BGP_STATS_RIB
]++;
11008 if (CHECK_FLAG(pi
->attr
->flag
,
11009 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11010 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11012 /* as-path stats */
11013 if (pi
->attr
->aspath
) {
11014 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11015 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11016 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11018 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11020 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11021 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11023 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11024 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11026 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11027 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11029 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11030 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11031 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11033 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11034 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11035 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11038 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11039 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11044 static int bgp_table_stats_walker(struct thread
*t
)
11046 struct bgp_node
*rn
, *nrn
;
11047 struct bgp_node
*top
;
11048 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11049 unsigned int space
= 0;
11051 if (!(top
= bgp_table_top(ts
->table
)))
11054 switch (ts
->table
->afi
) {
11056 space
= IPV4_MAX_BITLEN
;
11059 space
= IPV6_MAX_BITLEN
;
11065 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11067 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
11068 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
11069 struct bgp_table
*table
;
11071 table
= bgp_node_get_bgp_table_info(rn
);
11075 top
= bgp_table_top(table
);
11076 for (nrn
= bgp_table_top(table
); nrn
;
11077 nrn
= bgp_route_next(nrn
))
11078 bgp_table_stats_rn(nrn
, top
, ts
, space
);
11080 bgp_table_stats_rn(rn
, top
, ts
, space
);
11087 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11090 struct bgp_table_stats ts
;
11093 if (!bgp
->rib
[afi
][safi
]) {
11094 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11096 return CMD_WARNING
;
11099 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
11101 /* labeled-unicast routes live in the unicast table */
11102 if (safi
== SAFI_LABELED_UNICAST
)
11103 safi
= SAFI_UNICAST
;
11105 memset(&ts
, 0, sizeof(ts
));
11106 ts
.table
= bgp
->rib
[afi
][safi
];
11107 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11109 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11110 if (!table_stats_strs
[i
])
11115 case BGP_STATS_ASPATH_AVGHOPS
:
11116 case BGP_STATS_ASPATH_AVGSIZE
:
11117 case BGP_STATS_AVGPLEN
:
11118 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11119 vty_out (vty
, "%12.2f",
11120 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11123 case BGP_STATS_ASPATH_TOTHOPS
:
11124 case BGP_STATS_ASPATH_TOTSIZE
:
11125 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11126 vty_out(vty
, "%12.2f",
11128 ? (float)ts
.counts
[i
]
11130 [BGP_STATS_ASPATH_COUNT
]
11133 case BGP_STATS_TOTPLEN
:
11134 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11135 vty_out(vty
, "%12.2f",
11137 ? (float)ts
.counts
[i
]
11139 [BGP_STATS_PREFIXES
]
11142 case BGP_STATS_SPACE
:
11143 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11144 vty_out(vty
, "%12g\n", ts
.total_space
);
11146 if (afi
== AFI_IP6
) {
11147 vty_out(vty
, "%30s: ", "/32 equivalent ");
11148 vty_out(vty
, "%12g\n",
11149 ts
.total_space
* pow(2.0, -128 + 32));
11150 vty_out(vty
, "%30s: ", "/48 equivalent ");
11151 vty_out(vty
, "%12g\n",
11152 ts
.total_space
* pow(2.0, -128 + 48));
11154 vty_out(vty
, "%30s: ", "% announced ");
11155 vty_out(vty
, "%12.2f\n",
11156 ts
.total_space
* 100. * pow(2.0, -32));
11157 vty_out(vty
, "%30s: ", "/8 equivalent ");
11158 vty_out(vty
, "%12.2f\n",
11159 ts
.total_space
* pow(2.0, -32 + 8));
11160 vty_out(vty
, "%30s: ", "/24 equivalent ");
11161 vty_out(vty
, "%12.2f\n",
11162 ts
.total_space
* pow(2.0, -32 + 24));
11166 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11167 vty_out(vty
, "%12llu", ts
.counts
[i
]);
11170 vty_out(vty
, "\n");
11172 return CMD_SUCCESS
;
11184 PCOUNT_PFCNT
, /* the figure we display to users */
11188 static const char *const pcount_strs
[] = {
11189 [PCOUNT_ADJ_IN
] = "Adj-in",
11190 [PCOUNT_DAMPED
] = "Damped",
11191 [PCOUNT_REMOVED
] = "Removed",
11192 [PCOUNT_HISTORY
] = "History",
11193 [PCOUNT_STALE
] = "Stale",
11194 [PCOUNT_VALID
] = "Valid",
11195 [PCOUNT_ALL
] = "All RIB",
11196 [PCOUNT_COUNTED
] = "PfxCt counted",
11197 [PCOUNT_PFCNT
] = "Useable",
11198 [PCOUNT_MAX
] = NULL
,
11201 struct peer_pcounts
{
11202 unsigned int count
[PCOUNT_MAX
];
11203 const struct peer
*peer
;
11204 const struct bgp_table
*table
;
11208 static void bgp_peer_count_proc(struct bgp_node
*rn
,
11209 struct peer_pcounts
*pc
)
11211 const struct bgp_adj_in
*ain
;
11212 const struct bgp_path_info
*pi
;
11213 const struct peer
*peer
= pc
->peer
;
11215 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11216 if (ain
->peer
== peer
)
11217 pc
->count
[PCOUNT_ADJ_IN
]++;
11219 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11221 if (pi
->peer
!= peer
)
11224 pc
->count
[PCOUNT_ALL
]++;
11226 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11227 pc
->count
[PCOUNT_DAMPED
]++;
11228 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11229 pc
->count
[PCOUNT_HISTORY
]++;
11230 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11231 pc
->count
[PCOUNT_REMOVED
]++;
11232 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11233 pc
->count
[PCOUNT_STALE
]++;
11234 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11235 pc
->count
[PCOUNT_VALID
]++;
11236 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11237 pc
->count
[PCOUNT_PFCNT
]++;
11239 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11240 pc
->count
[PCOUNT_COUNTED
]++;
11241 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11243 EC_LIB_DEVELOPMENT
,
11244 "Attempting to count but flags say it is unusable");
11246 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11248 EC_LIB_DEVELOPMENT
,
11249 "Not counted but flags say we should");
11254 static int bgp_peer_count_walker(struct thread
*t
)
11256 struct bgp_node
*rn
, *rm
;
11257 const struct bgp_table
*table
;
11258 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11260 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11261 || pc
->safi
== SAFI_EVPN
) {
11262 /* Special handling for 2-level routing tables. */
11263 for (rn
= bgp_table_top(pc
->table
); rn
;
11264 rn
= bgp_route_next(rn
)) {
11265 table
= bgp_node_get_bgp_table_info(rn
);
11267 for (rm
= bgp_table_top(table
); rm
;
11268 rm
= bgp_route_next(rm
))
11269 bgp_peer_count_proc(rm
, pc
);
11272 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11273 bgp_peer_count_proc(rn
, pc
);
11278 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11279 safi_t safi
, bool use_json
)
11281 struct peer_pcounts pcounts
= {.peer
= peer
};
11283 json_object
*json
= NULL
;
11284 json_object
*json_loop
= NULL
;
11287 json
= json_object_new_object();
11288 json_loop
= json_object_new_object();
11291 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11292 || !peer
->bgp
->rib
[afi
][safi
]) {
11294 json_object_string_add(
11296 "No such neighbor or address family");
11297 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11298 json_object_free(json
);
11300 vty_out(vty
, "%% No such neighbor or address family\n");
11302 return CMD_WARNING
;
11305 memset(&pcounts
, 0, sizeof(pcounts
));
11306 pcounts
.peer
= peer
;
11307 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11308 pcounts
.safi
= safi
;
11310 /* in-place call via thread subsystem so as to record execution time
11311 * stats for the thread-walk (i.e. ensure this can't be blamed on
11312 * on just vty_read()).
11314 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11317 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11318 json_object_string_add(json
, "multiProtocol",
11319 get_afi_safi_str(afi
, safi
, true));
11320 json_object_int_add(json
, "pfxCounter",
11321 peer
->pcount
[afi
][safi
]);
11323 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11324 json_object_int_add(json_loop
, pcount_strs
[i
],
11327 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11329 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11330 json_object_string_add(json
, "pfxctDriftFor",
11332 json_object_string_add(
11333 json
, "recommended",
11334 "Please report this bug, with the above command output");
11336 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11337 json
, JSON_C_TO_STRING_PRETTY
));
11338 json_object_free(json
);
11342 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11343 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11344 peer
->hostname
, peer
->host
,
11345 get_afi_safi_str(afi
, safi
, false));
11347 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11348 get_afi_safi_str(afi
, safi
, false));
11351 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11352 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11354 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11355 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11358 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11359 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11361 "Please report this bug, with the above command output\n");
11365 return CMD_SUCCESS
;
11368 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11369 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11370 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11371 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11375 BGP_INSTANCE_HELP_STR
11378 "Detailed information on TCP and BGP neighbor connections\n"
11379 "Neighbor to display information about\n"
11380 "Neighbor to display information about\n"
11381 "Neighbor on BGP configured interface\n"
11382 "Display detailed prefix count information\n"
11385 afi_t afi
= AFI_IP6
;
11386 safi_t safi
= SAFI_UNICAST
;
11389 struct bgp
*bgp
= NULL
;
11390 bool uj
= use_json(argc
, argv
);
11395 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11398 return CMD_WARNING
;
11400 argv_find(argv
, argc
, "neighbors", &idx
);
11401 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11403 return CMD_WARNING
;
11405 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11408 #ifdef KEEP_OLD_VPN_COMMANDS
11409 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11410 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11411 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11416 "Display information about all VPNv4 NLRIs\n"
11417 "Detailed information on TCP and BGP neighbor connections\n"
11418 "Neighbor to display information about\n"
11419 "Neighbor to display information about\n"
11420 "Neighbor on BGP configured interface\n"
11421 "Display detailed prefix count information\n"
11426 bool uj
= use_json(argc
, argv
);
11428 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11430 return CMD_WARNING
;
11432 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11435 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11436 show_ip_bgp_vpn_all_route_prefix_cmd
,
11437 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11442 "Display information about all VPNv4 NLRIs\n"
11443 "Network in the BGP routing table to display\n"
11444 "Network in the BGP routing table to display\n"
11448 char *network
= NULL
;
11449 struct bgp
*bgp
= bgp_get_default();
11451 vty_out(vty
, "Can't find default instance\n");
11452 return CMD_WARNING
;
11455 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11456 network
= argv
[idx
]->arg
;
11457 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11458 network
= argv
[idx
]->arg
;
11460 vty_out(vty
, "Unable to figure out Network\n");
11461 return CMD_WARNING
;
11464 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11465 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11467 #endif /* KEEP_OLD_VPN_COMMANDS */
11469 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11470 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11471 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11476 "Network in the BGP routing table to display\n"
11477 "Network in the BGP routing table to display\n"
11478 "Network in the BGP routing table to display\n"
11479 "Network in the BGP routing table to display\n"
11483 char *network
= NULL
;
11484 int prefix_check
= 0;
11486 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11487 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11488 network
= argv
[idx
]->arg
;
11489 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11490 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11491 network
= argv
[idx
]->arg
;
11494 vty_out(vty
, "Unable to figure out Network\n");
11495 return CMD_WARNING
;
11497 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11498 prefix_check
, BGP_PATH_SHOW_ALL
,
11499 use_json(argc
, argv
));
11502 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11503 safi_t safi
, enum bgp_show_adj_route_type type
,
11504 const char *rmap_name
, bool use_json
,
11507 struct bgp_table
*table
;
11508 struct bgp_adj_in
*ain
;
11509 struct bgp_adj_out
*adj
;
11510 unsigned long output_count
;
11511 unsigned long filtered_count
;
11512 struct bgp_node
*rn
;
11518 struct update_subgroup
*subgrp
;
11519 json_object
*json_scode
= NULL
;
11520 json_object
*json_ocode
= NULL
;
11521 json_object
*json_ar
= NULL
;
11522 struct peer_af
*paf
;
11523 bool route_filtered
;
11526 json_scode
= json_object_new_object();
11527 json_ocode
= json_object_new_object();
11528 json_ar
= json_object_new_object();
11530 json_object_string_add(json_scode
, "suppressed", "s");
11531 json_object_string_add(json_scode
, "damped", "d");
11532 json_object_string_add(json_scode
, "history", "h");
11533 json_object_string_add(json_scode
, "valid", "*");
11534 json_object_string_add(json_scode
, "best", ">");
11535 json_object_string_add(json_scode
, "multipath", "=");
11536 json_object_string_add(json_scode
, "internal", "i");
11537 json_object_string_add(json_scode
, "ribFailure", "r");
11538 json_object_string_add(json_scode
, "stale", "S");
11539 json_object_string_add(json_scode
, "removed", "R");
11541 json_object_string_add(json_ocode
, "igp", "i");
11542 json_object_string_add(json_ocode
, "egp", "e");
11543 json_object_string_add(json_ocode
, "incomplete", "?");
11550 json_object_string_add(json
, "alert", "no BGP");
11551 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11552 json_object_free(json
);
11554 vty_out(vty
, "%% No bgp\n");
11558 /* labeled-unicast routes live in the unicast table */
11559 if (safi
== SAFI_LABELED_UNICAST
)
11560 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11562 table
= bgp
->rib
[afi
][safi
];
11564 output_count
= filtered_count
= 0;
11565 subgrp
= peer_subgroup(peer
, afi
, safi
);
11567 if (type
== bgp_show_adj_route_advertised
&& subgrp
11568 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11570 json_object_int_add(json
, "bgpTableVersion",
11572 json_object_string_add(json
, "bgpLocalRouterId",
11573 inet_ntoa(bgp
->router_id
));
11574 json_object_int_add(json
, "defaultLocPrf",
11575 bgp
->default_local_pref
);
11576 json_object_int_add(json
, "localAS", bgp
->as
);
11577 json_object_object_add(json
, "bgpStatusCodes",
11579 json_object_object_add(json
, "bgpOriginCodes",
11581 json_object_string_add(
11582 json
, "bgpOriginatingDefaultNetwork",
11583 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11585 vty_out(vty
, "BGP table version is %" PRIu64
11586 ", local router ID is %s, vrf id ",
11587 table
->version
, inet_ntoa(bgp
->router_id
));
11588 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11589 vty_out(vty
, "%s", VRFID_NONE_STR
);
11591 vty_out(vty
, "%u", bgp
->vrf_id
);
11592 vty_out(vty
, "\n");
11593 vty_out(vty
, "Default local pref %u, ",
11594 bgp
->default_local_pref
);
11595 vty_out(vty
, "local AS %u\n", bgp
->as
);
11596 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11597 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11598 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11600 vty_out(vty
, "Originating default network %s\n\n",
11601 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11606 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11607 if (type
== bgp_show_adj_route_received
11608 || type
== bgp_show_adj_route_filtered
) {
11609 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11610 if (ain
->peer
!= peer
)
11615 json_object_int_add(
11616 json
, "bgpTableVersion",
11618 json_object_string_add(
11620 "bgpLocalRouterId",
11623 json_object_int_add(json
,
11625 bgp
->default_local_pref
);
11626 json_object_int_add(json
,
11627 "localAS", bgp
->as
);
11628 json_object_object_add(
11629 json
, "bgpStatusCodes",
11631 json_object_object_add(
11632 json
, "bgpOriginCodes",
11636 "BGP table version is 0, local router ID is %s, vrf id ",
11639 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11645 vty_out(vty
, "\n");
11647 "Default local pref %u, ",
11648 bgp
->default_local_pref
);
11649 vty_out(vty
, "local AS %u\n",
11652 BGP_SHOW_SCODE_HEADER
);
11654 BGP_SHOW_NCODE_HEADER
);
11656 BGP_SHOW_OCODE_HEADER
);
11662 vty_out(vty
, BGP_SHOW_HEADER
);
11667 route_filtered
= false;
11669 /* Filter prefix using distribute list,
11670 * filter list or prefix list
11672 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11673 safi
)) == FILTER_DENY
)
11674 route_filtered
= true;
11676 /* Filter prefix using route-map */
11677 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11678 afi
, safi
, rmap_name
, NULL
, 0,
11681 if (type
== bgp_show_adj_route_filtered
&&
11682 !route_filtered
&& ret
!= RMAP_DENY
) {
11683 bgp_attr_undup(&attr
, ain
->attr
);
11687 if (type
== bgp_show_adj_route_received
&&
11688 (route_filtered
|| ret
== RMAP_DENY
))
11691 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11692 use_json
, json_ar
);
11693 bgp_attr_undup(&attr
, ain
->attr
);
11696 } else if (type
== bgp_show_adj_route_advertised
) {
11697 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11698 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11699 if (paf
->peer
!= peer
|| !adj
->attr
)
11704 json_object_int_add(
11708 json_object_string_add(
11710 "bgpLocalRouterId",
11713 json_object_int_add(
11714 json
, "defaultLocPrf",
11715 bgp
->default_local_pref
11717 json_object_int_add(
11720 json_object_object_add(
11724 json_object_object_add(
11730 "BGP table version is %" PRIu64
11731 ", local router ID is %s, vrf id ",
11744 vty_out(vty
, "\n");
11746 "Default local pref %u, ",
11747 bgp
->default_local_pref
11753 BGP_SHOW_SCODE_HEADER
);
11755 BGP_SHOW_NCODE_HEADER
);
11757 BGP_SHOW_OCODE_HEADER
);
11769 ret
= bgp_output_modifier(
11770 peer
, &rn
->p
, &attr
, afi
, safi
,
11773 if (ret
!= RMAP_DENY
) {
11774 route_vty_out_tmp(vty
, &rn
->p
,
11783 bgp_attr_undup(&attr
, adj
->attr
);
11789 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11790 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11791 json_object_int_add(json
, "filteredPrefixCounter",
11794 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11795 json
, JSON_C_TO_STRING_PRETTY
));
11796 json_object_free(json
);
11797 } else if (output_count
> 0) {
11798 if (filtered_count
> 0)
11800 "\nTotal number of prefixes %ld (%ld filtered)\n",
11801 output_count
, filtered_count
);
11803 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11808 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11809 safi_t safi
, enum bgp_show_adj_route_type type
,
11810 const char *rmap_name
, bool use_json
)
11812 json_object
*json
= NULL
;
11815 json
= json_object_new_object();
11817 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11819 json_object_string_add(
11821 "No such neighbor or address family");
11822 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11823 json_object_free(json
);
11825 vty_out(vty
, "%% No such neighbor or address family\n");
11827 return CMD_WARNING
;
11830 if ((type
== bgp_show_adj_route_received
11831 || type
== bgp_show_adj_route_filtered
)
11832 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11833 PEER_FLAG_SOFT_RECONFIG
)) {
11835 json_object_string_add(
11837 "Inbound soft reconfiguration not enabled");
11838 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11839 json_object_free(json
);
11842 "%% Inbound soft reconfiguration not enabled\n");
11844 return CMD_WARNING
;
11847 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11849 return CMD_SUCCESS
;
11852 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11853 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11854 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11855 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11859 BGP_INSTANCE_HELP_STR
11861 BGP_SAFI_WITH_LABEL_HELP_STR
11862 "Detailed information on TCP and BGP neighbor connections\n"
11863 "Neighbor to display information about\n"
11864 "Neighbor to display information about\n"
11865 "Neighbor on BGP configured interface\n"
11866 "Display the routes advertised to a BGP neighbor\n"
11867 "Display the received routes from neighbor\n"
11868 "Display the filtered routes received from neighbor\n"
11869 "Route-map to modify the attributes\n"
11870 "Name of the route map\n"
11873 afi_t afi
= AFI_IP6
;
11874 safi_t safi
= SAFI_UNICAST
;
11875 char *rmap_name
= NULL
;
11876 char *peerstr
= NULL
;
11877 struct bgp
*bgp
= NULL
;
11879 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11881 bool uj
= use_json(argc
, argv
);
11886 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11889 return CMD_WARNING
;
11891 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11892 argv_find(argv
, argc
, "neighbors", &idx
);
11893 peerstr
= argv
[++idx
]->arg
;
11895 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11897 return CMD_WARNING
;
11899 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11900 type
= bgp_show_adj_route_advertised
;
11901 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11902 type
= bgp_show_adj_route_received
;
11903 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11904 type
= bgp_show_adj_route_filtered
;
11906 if (argv_find(argv
, argc
, "route-map", &idx
))
11907 rmap_name
= argv
[++idx
]->arg
;
11909 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11912 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11913 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11914 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11920 "Address Family modifier\n"
11921 "Detailed information on TCP and BGP neighbor connections\n"
11922 "Neighbor to display information about\n"
11923 "Neighbor to display information about\n"
11924 "Neighbor on BGP configured interface\n"
11925 "Display information received from a BGP neighbor\n"
11926 "Display the prefixlist filter\n"
11929 afi_t afi
= AFI_IP6
;
11930 safi_t safi
= SAFI_UNICAST
;
11931 char *peerstr
= NULL
;
11934 union sockunion su
;
11940 /* show [ip] bgp */
11941 if (argv_find(argv
, argc
, "ip", &idx
))
11943 /* [<ipv4|ipv6> [unicast]] */
11944 if (argv_find(argv
, argc
, "ipv4", &idx
))
11946 if (argv_find(argv
, argc
, "ipv6", &idx
))
11948 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11949 argv_find(argv
, argc
, "neighbors", &idx
);
11950 peerstr
= argv
[++idx
]->arg
;
11952 bool uj
= use_json(argc
, argv
);
11954 ret
= str2sockunion(peerstr
, &su
);
11956 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11959 vty_out(vty
, "{}\n");
11962 "%% Malformed address or name: %s\n",
11964 return CMD_WARNING
;
11967 peer
= peer_lookup(NULL
, &su
);
11970 vty_out(vty
, "{}\n");
11972 vty_out(vty
, "No peer\n");
11973 return CMD_WARNING
;
11977 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11978 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11981 vty_out(vty
, "Address Family: %s\n",
11982 get_afi_safi_str(afi
, safi
, false));
11983 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11986 vty_out(vty
, "{}\n");
11988 vty_out(vty
, "No functional output\n");
11991 return CMD_SUCCESS
;
11994 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11995 afi_t afi
, safi_t safi
,
11996 enum bgp_show_type type
, bool use_json
)
11998 /* labeled-unicast routes live in the unicast table */
11999 if (safi
== SAFI_LABELED_UNICAST
)
12000 safi
= SAFI_UNICAST
;
12002 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12004 json_object
*json_no
= NULL
;
12005 json_no
= json_object_new_object();
12006 json_object_string_add(
12007 json_no
, "warning",
12008 "No such neighbor or address family");
12009 vty_out(vty
, "%s\n",
12010 json_object_to_json_string(json_no
));
12011 json_object_free(json_no
);
12013 vty_out(vty
, "%% No such neighbor or address family\n");
12014 return CMD_WARNING
;
12017 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
12020 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12021 show_ip_bgp_flowspec_routes_detailed_cmd
,
12022 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12026 BGP_INSTANCE_HELP_STR
12029 "Detailed information on flowspec entries\n"
12032 afi_t afi
= AFI_IP
;
12033 safi_t safi
= SAFI_UNICAST
;
12034 struct bgp
*bgp
= NULL
;
12036 bool uj
= use_json(argc
, argv
);
12041 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12044 return CMD_WARNING
;
12046 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
12049 DEFUN (show_ip_bgp_neighbor_routes
,
12050 show_ip_bgp_neighbor_routes_cmd
,
12051 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12052 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
12056 BGP_INSTANCE_HELP_STR
12058 BGP_SAFI_WITH_LABEL_HELP_STR
12059 "Detailed information on TCP and BGP neighbor connections\n"
12060 "Neighbor to display information about\n"
12061 "Neighbor to display information about\n"
12062 "Neighbor on BGP configured interface\n"
12063 "Display flap statistics of the routes learned from neighbor\n"
12064 "Display the dampened routes received from neighbor\n"
12065 "Display routes learned from neighbor\n"
12068 char *peerstr
= NULL
;
12069 struct bgp
*bgp
= NULL
;
12070 afi_t afi
= AFI_IP6
;
12071 safi_t safi
= SAFI_UNICAST
;
12073 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12075 bool uj
= use_json(argc
, argv
);
12080 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12083 return CMD_WARNING
;
12085 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12086 argv_find(argv
, argc
, "neighbors", &idx
);
12087 peerstr
= argv
[++idx
]->arg
;
12089 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12091 return CMD_WARNING
;
12093 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12094 sh_type
= bgp_show_type_flap_neighbor
;
12095 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12096 sh_type
= bgp_show_type_damp_neighbor
;
12097 else if (argv_find(argv
, argc
, "routes", &idx
))
12098 sh_type
= bgp_show_type_neighbor
;
12100 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12103 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12105 struct bgp_distance
{
12106 /* Distance value for the IP source prefix. */
12109 /* Name of the access-list to be matched. */
12113 DEFUN (show_bgp_afi_vpn_rd_route
,
12114 show_bgp_afi_vpn_rd_route_cmd
,
12115 "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]",
12119 "Address Family modifier\n"
12120 "Display information for a route distinguisher\n"
12121 "Route Distinguisher\n"
12122 "Network in the BGP routing table to display\n"
12123 "Network in the BGP routing table to display\n"
12127 struct prefix_rd prd
;
12128 afi_t afi
= AFI_MAX
;
12131 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12132 vty_out(vty
, "%% Malformed Address Family\n");
12133 return CMD_WARNING
;
12136 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12138 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12139 return CMD_WARNING
;
12142 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12143 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12146 static struct bgp_distance
*bgp_distance_new(void)
12148 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12151 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12153 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12156 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12157 const char *ip_str
, const char *access_list_str
)
12164 struct bgp_node
*rn
;
12165 struct bgp_distance
*bdistance
;
12167 afi
= bgp_node_afi(vty
);
12168 safi
= bgp_node_safi(vty
);
12170 ret
= str2prefix(ip_str
, &p
);
12172 vty_out(vty
, "Malformed prefix\n");
12173 return CMD_WARNING_CONFIG_FAILED
;
12176 distance
= atoi(distance_str
);
12178 /* Get BGP distance node. */
12179 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
12180 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12182 bgp_unlock_node(rn
);
12184 bdistance
= bgp_distance_new();
12185 bgp_node_set_bgp_distance_info(rn
, bdistance
);
12188 /* Set distance value. */
12189 bdistance
->distance
= distance
;
12191 /* Reset access-list configuration. */
12192 if (bdistance
->access_list
) {
12193 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12194 bdistance
->access_list
= NULL
;
12196 if (access_list_str
)
12197 bdistance
->access_list
=
12198 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12200 return CMD_SUCCESS
;
12203 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12204 const char *ip_str
, const char *access_list_str
)
12211 struct bgp_node
*rn
;
12212 struct bgp_distance
*bdistance
;
12214 afi
= bgp_node_afi(vty
);
12215 safi
= bgp_node_safi(vty
);
12217 ret
= str2prefix(ip_str
, &p
);
12219 vty_out(vty
, "Malformed prefix\n");
12220 return CMD_WARNING_CONFIG_FAILED
;
12223 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
12224 (struct prefix
*)&p
);
12226 vty_out(vty
, "Can't find specified prefix\n");
12227 return CMD_WARNING_CONFIG_FAILED
;
12230 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12231 distance
= atoi(distance_str
);
12233 if (bdistance
->distance
!= distance
) {
12234 vty_out(vty
, "Distance does not match configured\n");
12235 return CMD_WARNING_CONFIG_FAILED
;
12238 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12239 bgp_distance_free(bdistance
);
12241 bgp_node_set_bgp_path_info(rn
, NULL
);
12242 bgp_unlock_node(rn
);
12243 bgp_unlock_node(rn
);
12245 return CMD_SUCCESS
;
12248 /* Apply BGP information to distance method. */
12249 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
12250 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12252 struct bgp_node
*rn
;
12255 struct bgp_distance
*bdistance
;
12256 struct access_list
*alist
;
12257 struct bgp_static
*bgp_static
;
12262 peer
= pinfo
->peer
;
12264 if (pinfo
->attr
->distance
)
12265 return pinfo
->attr
->distance
;
12267 /* Check source address. */
12268 sockunion2hostprefix(&peer
->su
, &q
);
12269 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12271 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12272 bgp_unlock_node(rn
);
12274 if (bdistance
->access_list
) {
12275 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12277 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12278 return bdistance
->distance
;
12280 return bdistance
->distance
;
12283 /* Backdoor check. */
12284 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12286 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12287 bgp_unlock_node(rn
);
12289 if (bgp_static
->backdoor
) {
12290 if (bgp
->distance_local
[afi
][safi
])
12291 return bgp
->distance_local
[afi
][safi
];
12293 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12297 if (peer
->sort
== BGP_PEER_EBGP
) {
12298 if (bgp
->distance_ebgp
[afi
][safi
])
12299 return bgp
->distance_ebgp
[afi
][safi
];
12300 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12302 if (bgp
->distance_ibgp
[afi
][safi
])
12303 return bgp
->distance_ibgp
[afi
][safi
];
12304 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12308 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12309 * we should tell ZEBRA update the routes for a specific
12310 * AFI/SAFI to reflect changes in RIB.
12312 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12314 safi_t update_safi
)
12319 FOREACH_AFI_SAFI (afi
, safi
) {
12320 if (!bgp_fibupd_safi(safi
))
12323 if (afi
!= update_afi
&& safi
!= update_safi
)
12326 if (BGP_DEBUG(zebra
, ZEBRA
))
12328 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12329 __func__
, afi
, safi
);
12330 bgp_zebra_announce_table(bgp
, afi
, safi
);
12334 DEFUN (bgp_distance
,
12336 "distance bgp (1-255) (1-255) (1-255)",
12337 "Define an administrative distance\n"
12339 "Distance for routes external to the AS\n"
12340 "Distance for routes internal to the AS\n"
12341 "Distance for local routes\n")
12343 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12344 int idx_number
= 2;
12345 int idx_number_2
= 3;
12346 int idx_number_3
= 4;
12347 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12348 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12349 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12353 afi
= bgp_node_afi(vty
);
12354 safi
= bgp_node_safi(vty
);
12356 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12357 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12358 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12359 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12360 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12361 bgp
->distance_local
[afi
][safi
] = distance_local
;
12362 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12364 return CMD_SUCCESS
;
12367 DEFUN (no_bgp_distance
,
12368 no_bgp_distance_cmd
,
12369 "no distance bgp [(1-255) (1-255) (1-255)]",
12371 "Define an administrative distance\n"
12373 "Distance for routes external to the AS\n"
12374 "Distance for routes internal to the AS\n"
12375 "Distance for local routes\n")
12377 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12381 afi
= bgp_node_afi(vty
);
12382 safi
= bgp_node_safi(vty
);
12384 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12385 || bgp
->distance_ibgp
[afi
][safi
] != 0
12386 || bgp
->distance_local
[afi
][safi
] != 0) {
12387 bgp
->distance_ebgp
[afi
][safi
] = 0;
12388 bgp
->distance_ibgp
[afi
][safi
] = 0;
12389 bgp
->distance_local
[afi
][safi
] = 0;
12390 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12392 return CMD_SUCCESS
;
12396 DEFUN (bgp_distance_source
,
12397 bgp_distance_source_cmd
,
12398 "distance (1-255) A.B.C.D/M",
12399 "Define an administrative distance\n"
12400 "Administrative distance\n"
12401 "IP source prefix\n")
12403 int idx_number
= 1;
12404 int idx_ipv4_prefixlen
= 2;
12405 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12406 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12407 return CMD_SUCCESS
;
12410 DEFUN (no_bgp_distance_source
,
12411 no_bgp_distance_source_cmd
,
12412 "no distance (1-255) A.B.C.D/M",
12414 "Define an administrative distance\n"
12415 "Administrative distance\n"
12416 "IP source prefix\n")
12418 int idx_number
= 2;
12419 int idx_ipv4_prefixlen
= 3;
12420 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12421 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12422 return CMD_SUCCESS
;
12425 DEFUN (bgp_distance_source_access_list
,
12426 bgp_distance_source_access_list_cmd
,
12427 "distance (1-255) A.B.C.D/M WORD",
12428 "Define an administrative distance\n"
12429 "Administrative distance\n"
12430 "IP source prefix\n"
12431 "Access list name\n")
12433 int idx_number
= 1;
12434 int idx_ipv4_prefixlen
= 2;
12436 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12437 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12438 return CMD_SUCCESS
;
12441 DEFUN (no_bgp_distance_source_access_list
,
12442 no_bgp_distance_source_access_list_cmd
,
12443 "no distance (1-255) A.B.C.D/M WORD",
12445 "Define an administrative distance\n"
12446 "Administrative distance\n"
12447 "IP source prefix\n"
12448 "Access list name\n")
12450 int idx_number
= 2;
12451 int idx_ipv4_prefixlen
= 3;
12453 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12454 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12455 return CMD_SUCCESS
;
12458 DEFUN (ipv6_bgp_distance_source
,
12459 ipv6_bgp_distance_source_cmd
,
12460 "distance (1-255) X:X::X:X/M",
12461 "Define an administrative distance\n"
12462 "Administrative distance\n"
12463 "IP source prefix\n")
12465 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12466 return CMD_SUCCESS
;
12469 DEFUN (no_ipv6_bgp_distance_source
,
12470 no_ipv6_bgp_distance_source_cmd
,
12471 "no distance (1-255) X:X::X:X/M",
12473 "Define an administrative distance\n"
12474 "Administrative distance\n"
12475 "IP source prefix\n")
12477 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12478 return CMD_SUCCESS
;
12481 DEFUN (ipv6_bgp_distance_source_access_list
,
12482 ipv6_bgp_distance_source_access_list_cmd
,
12483 "distance (1-255) X:X::X:X/M WORD",
12484 "Define an administrative distance\n"
12485 "Administrative distance\n"
12486 "IP source prefix\n"
12487 "Access list name\n")
12489 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12490 return CMD_SUCCESS
;
12493 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12494 no_ipv6_bgp_distance_source_access_list_cmd
,
12495 "no distance (1-255) X:X::X:X/M WORD",
12497 "Define an administrative distance\n"
12498 "Administrative distance\n"
12499 "IP source prefix\n"
12500 "Access list name\n")
12502 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12503 return CMD_SUCCESS
;
12506 DEFUN (bgp_damp_set
,
12508 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12509 "BGP Specific commands\n"
12510 "Enable route-flap dampening\n"
12511 "Half-life time for the penalty\n"
12512 "Value to start reusing a route\n"
12513 "Value to start suppressing a route\n"
12514 "Maximum duration to suppress a stable route\n")
12516 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12517 int idx_half_life
= 2;
12519 int idx_suppress
= 4;
12520 int idx_max_suppress
= 5;
12521 int half
= DEFAULT_HALF_LIFE
* 60;
12522 int reuse
= DEFAULT_REUSE
;
12523 int suppress
= DEFAULT_SUPPRESS
;
12524 int max
= 4 * half
;
12527 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12528 reuse
= atoi(argv
[idx_reuse
]->arg
);
12529 suppress
= atoi(argv
[idx_suppress
]->arg
);
12530 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12531 } else if (argc
== 3) {
12532 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12537 * These can't be 0 but our SA doesn't understand the
12538 * way our cli is constructed
12542 if (suppress
< reuse
) {
12544 "Suppress value cannot be less than reuse value \n");
12548 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12549 reuse
, suppress
, max
);
12552 DEFUN (bgp_damp_unset
,
12553 bgp_damp_unset_cmd
,
12554 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12556 "BGP Specific commands\n"
12557 "Enable route-flap dampening\n"
12558 "Half-life time for the penalty\n"
12559 "Value to start reusing a route\n"
12560 "Value to start suppressing a route\n"
12561 "Maximum duration to suppress a stable route\n")
12563 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12564 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12567 /* Display specified route of BGP table. */
12568 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12569 const char *ip_str
, afi_t afi
, safi_t safi
,
12570 struct prefix_rd
*prd
, int prefix_check
)
12573 struct prefix match
;
12574 struct bgp_node
*rn
;
12575 struct bgp_node
*rm
;
12576 struct bgp_path_info
*pi
;
12577 struct bgp_path_info
*pi_temp
;
12579 struct bgp_table
*table
;
12581 /* BGP structure lookup. */
12583 bgp
= bgp_lookup_by_name(view_name
);
12585 vty_out(vty
, "%% Can't find BGP instance %s\n",
12587 return CMD_WARNING
;
12590 bgp
= bgp_get_default();
12592 vty_out(vty
, "%% No BGP process is configured\n");
12593 return CMD_WARNING
;
12597 /* Check IP address argument. */
12598 ret
= str2prefix(ip_str
, &match
);
12600 vty_out(vty
, "%% address is malformed\n");
12601 return CMD_WARNING
;
12604 match
.family
= afi2family(afi
);
12606 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12607 || (safi
== SAFI_EVPN
)) {
12608 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12609 rn
= bgp_route_next(rn
)) {
12610 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12612 table
= bgp_node_get_bgp_table_info(rn
);
12615 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12619 || rm
->p
.prefixlen
== match
.prefixlen
) {
12620 pi
= bgp_node_get_bgp_path_info(rm
);
12622 if (pi
->extra
&& pi
->extra
->damp_info
) {
12623 pi_temp
= pi
->next
;
12624 bgp_damp_info_free(
12625 pi
->extra
->damp_info
,
12633 bgp_unlock_node(rm
);
12636 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12639 || rn
->p
.prefixlen
== match
.prefixlen
) {
12640 pi
= bgp_node_get_bgp_path_info(rn
);
12642 if (pi
->extra
&& pi
->extra
->damp_info
) {
12643 pi_temp
= pi
->next
;
12644 bgp_damp_info_free(
12645 pi
->extra
->damp_info
,
12653 bgp_unlock_node(rn
);
12657 return CMD_SUCCESS
;
12660 DEFUN (clear_ip_bgp_dampening
,
12661 clear_ip_bgp_dampening_cmd
,
12662 "clear ip bgp dampening",
12666 "Clear route flap dampening information\n")
12668 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12669 return CMD_SUCCESS
;
12672 DEFUN (clear_ip_bgp_dampening_prefix
,
12673 clear_ip_bgp_dampening_prefix_cmd
,
12674 "clear ip bgp dampening A.B.C.D/M",
12678 "Clear route flap dampening information\n"
12681 int idx_ipv4_prefixlen
= 4;
12682 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12683 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12686 DEFUN (clear_ip_bgp_dampening_address
,
12687 clear_ip_bgp_dampening_address_cmd
,
12688 "clear ip bgp dampening A.B.C.D",
12692 "Clear route flap dampening information\n"
12693 "Network to clear damping information\n")
12696 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12697 SAFI_UNICAST
, NULL
, 0);
12700 DEFUN (clear_ip_bgp_dampening_address_mask
,
12701 clear_ip_bgp_dampening_address_mask_cmd
,
12702 "clear ip bgp dampening A.B.C.D A.B.C.D",
12706 "Clear route flap dampening information\n"
12707 "Network to clear damping information\n"
12711 int idx_ipv4_2
= 5;
12713 char prefix_str
[BUFSIZ
];
12715 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12718 vty_out(vty
, "%% Inconsistent address and mask\n");
12719 return CMD_WARNING
;
12722 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12726 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12728 struct vty
*vty
= arg
;
12729 struct peer
*peer
= bucket
->data
;
12730 char buf
[SU_ADDRSTRLEN
];
12732 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12733 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12736 DEFUN (show_bgp_peerhash
,
12737 show_bgp_peerhash_cmd
,
12738 "show bgp peerhash",
12741 "Display information about the BGP peerhash\n")
12743 struct list
*instances
= bm
->bgp
;
12744 struct listnode
*node
;
12747 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12748 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12749 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12753 return CMD_SUCCESS
;
12756 /* also used for encap safi */
12757 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12758 afi_t afi
, safi_t safi
)
12760 struct bgp_node
*prn
;
12761 struct bgp_node
*rn
;
12762 struct bgp_table
*table
;
12764 struct prefix_rd
*prd
;
12765 struct bgp_static
*bgp_static
;
12766 mpls_label_t label
;
12767 char buf
[SU_ADDRSTRLEN
];
12768 char rdbuf
[RD_ADDRSTRLEN
];
12770 /* Network configuration. */
12771 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12772 prn
= bgp_route_next(prn
)) {
12773 table
= bgp_node_get_bgp_table_info(prn
);
12777 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12778 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12779 if (bgp_static
== NULL
)
12783 prd
= (struct prefix_rd
*)&prn
->p
;
12785 /* "network" configuration display. */
12786 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12787 label
= decode_label(&bgp_static
->label
);
12789 vty_out(vty
, " network %s/%d rd %s",
12790 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12792 p
->prefixlen
, rdbuf
);
12793 if (safi
== SAFI_MPLS_VPN
)
12794 vty_out(vty
, " label %u", label
);
12796 if (bgp_static
->rmap
.name
)
12797 vty_out(vty
, " route-map %s",
12798 bgp_static
->rmap
.name
);
12800 if (bgp_static
->backdoor
)
12801 vty_out(vty
, " backdoor");
12803 vty_out(vty
, "\n");
12808 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12809 afi_t afi
, safi_t safi
)
12811 struct bgp_node
*prn
;
12812 struct bgp_node
*rn
;
12813 struct bgp_table
*table
;
12815 struct prefix_rd
*prd
;
12816 struct bgp_static
*bgp_static
;
12817 char buf
[PREFIX_STRLEN
* 2];
12818 char buf2
[SU_ADDRSTRLEN
];
12819 char rdbuf
[RD_ADDRSTRLEN
];
12821 /* Network configuration. */
12822 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12823 prn
= bgp_route_next(prn
)) {
12824 table
= bgp_node_get_bgp_table_info(prn
);
12828 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12829 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12830 if (bgp_static
== NULL
)
12833 char *macrouter
= NULL
;
12836 if (bgp_static
->router_mac
)
12837 macrouter
= prefix_mac2str(
12838 bgp_static
->router_mac
, NULL
, 0);
12839 if (bgp_static
->eth_s_id
)
12840 esi
= esi2str(bgp_static
->eth_s_id
);
12842 prd
= (struct prefix_rd
*)&prn
->p
;
12844 /* "network" configuration display. */
12845 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12846 if (p
->u
.prefix_evpn
.route_type
== 5) {
12847 char local_buf
[PREFIX_STRLEN
];
12848 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12849 struct prefix_evpn
*)p
)
12853 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12854 local_buf
, PREFIX_STRLEN
);
12855 sprintf(buf
, "%s/%u", local_buf
,
12856 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12858 prefix2str(p
, buf
, sizeof(buf
));
12861 if (bgp_static
->gatewayIp
.family
== AF_INET
12862 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12863 inet_ntop(bgp_static
->gatewayIp
.family
,
12864 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12867 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12869 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12870 decode_label(&bgp_static
->label
), esi
, buf2
,
12873 XFREE(MTYPE_TMP
, macrouter
);
12874 XFREE(MTYPE_TMP
, esi
);
12879 /* Configuration of static route announcement and aggregate
12881 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12884 struct bgp_node
*rn
;
12886 struct bgp_static
*bgp_static
;
12887 struct bgp_aggregate
*bgp_aggregate
;
12888 char buf
[SU_ADDRSTRLEN
];
12890 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12891 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12895 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12896 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12900 /* Network configuration. */
12901 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12902 rn
= bgp_route_next(rn
)) {
12903 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12904 if (bgp_static
== NULL
)
12909 vty_out(vty
, " network %s/%d",
12910 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12913 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12914 vty_out(vty
, " label-index %u",
12915 bgp_static
->label_index
);
12917 if (bgp_static
->rmap
.name
)
12918 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12920 if (bgp_static
->backdoor
)
12921 vty_out(vty
, " backdoor");
12923 vty_out(vty
, "\n");
12926 /* Aggregate-address configuration. */
12927 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12928 rn
= bgp_route_next(rn
)) {
12929 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12930 if (bgp_aggregate
== NULL
)
12935 vty_out(vty
, " aggregate-address %s/%d",
12936 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12939 if (bgp_aggregate
->as_set
)
12940 vty_out(vty
, " as-set");
12942 if (bgp_aggregate
->summary_only
)
12943 vty_out(vty
, " summary-only");
12945 if (bgp_aggregate
->rmap
.name
)
12946 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12948 vty_out(vty
, "\n");
12952 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12955 struct bgp_node
*rn
;
12956 struct bgp_distance
*bdistance
;
12958 /* Distance configuration. */
12959 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12960 && bgp
->distance_local
[afi
][safi
]
12961 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12962 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12963 || bgp
->distance_local
[afi
][safi
]
12964 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12965 vty_out(vty
, " distance bgp %d %d %d\n",
12966 bgp
->distance_ebgp
[afi
][safi
],
12967 bgp
->distance_ibgp
[afi
][safi
],
12968 bgp
->distance_local
[afi
][safi
]);
12971 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12972 rn
= bgp_route_next(rn
)) {
12973 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12974 if (bdistance
!= NULL
) {
12975 char buf
[PREFIX_STRLEN
];
12977 vty_out(vty
, " distance %d %s %s\n",
12978 bdistance
->distance
,
12979 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12980 bdistance
->access_list
? bdistance
->access_list
12986 /* Allocate routing table structure and install commands. */
12987 void bgp_route_init(void)
12992 /* Init BGP distance table. */
12993 FOREACH_AFI_SAFI (afi
, safi
)
12994 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12996 /* IPv4 BGP commands. */
12997 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12998 install_element(BGP_NODE
, &bgp_network_cmd
);
12999 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
13001 install_element(BGP_NODE
, &aggregate_address_cmd
);
13002 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
13003 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
13004 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
13006 /* IPv4 unicast configuration. */
13007 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
13008 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
13009 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
13011 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
13012 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
13013 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
13014 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
13016 /* IPv4 multicast configuration. */
13017 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
13018 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
13019 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
13020 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
13021 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
13022 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
13023 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13025 /* IPv4 labeled-unicast configuration. */
13026 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13027 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13028 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13029 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13030 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13032 install_element(VIEW_NODE
,
13033 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13034 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13035 install_element(VIEW_NODE
,
13036 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13037 #ifdef KEEP_OLD_VPN_COMMANDS
13038 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13039 #endif /* KEEP_OLD_VPN_COMMANDS */
13040 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13041 install_element(VIEW_NODE
,
13042 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13044 /* BGP dampening clear commands */
13045 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13046 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13048 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13049 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13052 install_element(ENABLE_NODE
,
13053 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13054 #ifdef KEEP_OLD_VPN_COMMANDS
13055 install_element(ENABLE_NODE
,
13056 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13057 #endif /* KEEP_OLD_VPN_COMMANDS */
13059 /* New config IPv6 BGP commands. */
13060 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13061 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13062 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13064 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13065 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13067 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13069 install_element(BGP_NODE
, &bgp_distance_cmd
);
13070 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13071 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13072 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13073 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13074 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13075 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13076 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13077 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13078 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13079 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13080 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13081 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13082 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13083 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13084 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13085 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13086 install_element(BGP_IPV4M_NODE
,
13087 &no_bgp_distance_source_access_list_cmd
);
13088 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13089 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13090 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13091 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13092 install_element(BGP_IPV6_NODE
,
13093 &ipv6_bgp_distance_source_access_list_cmd
);
13094 install_element(BGP_IPV6_NODE
,
13095 &no_ipv6_bgp_distance_source_access_list_cmd
);
13096 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13097 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13098 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13099 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13100 install_element(BGP_IPV6M_NODE
,
13101 &ipv6_bgp_distance_source_access_list_cmd
);
13102 install_element(BGP_IPV6M_NODE
,
13103 &no_ipv6_bgp_distance_source_access_list_cmd
);
13105 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13106 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13107 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13108 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13110 /* IPv4 Multicast Mode */
13111 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13112 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13114 /* Large Communities */
13115 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13116 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13118 /* show bgp ipv4 flowspec detailed */
13119 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13121 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13124 void bgp_route_finish(void)
13129 FOREACH_AFI_SAFI (afi
, safi
) {
13130 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13131 bgp_distance_table
[afi
][safi
] = NULL
;