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
,
94 safi_t safi
, bool for_json
);
96 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
97 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
98 static const struct message bgp_pmsi_tnltype_str
[] = {
99 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
100 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
101 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
102 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
103 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
104 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
105 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
106 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
110 #define VRFID_NONE_STR "-"
112 DEFINE_HOOK(bgp_process
,
113 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
114 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
115 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
118 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
119 safi_t safi
, struct prefix
*p
,
120 struct prefix_rd
*prd
)
123 struct bgp_node
*prn
= NULL
;
129 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
130 || (safi
== SAFI_EVPN
)) {
131 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
133 if (!bgp_node_has_bgp_path_info_data(prn
))
134 bgp_node_set_bgp_table_info(
135 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
137 bgp_unlock_node(prn
);
138 table
= bgp_node_get_bgp_table_info(prn
);
141 rn
= bgp_node_get(table
, p
);
143 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
144 || (safi
== SAFI_EVPN
))
150 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
151 safi_t safi
, struct prefix
*p
,
152 struct prefix_rd
*prd
)
155 struct bgp_node
*prn
= NULL
;
160 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
161 || (safi
== SAFI_EVPN
)) {
162 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
166 if (!bgp_node_has_bgp_path_info_data(prn
)) {
167 bgp_unlock_node(prn
);
171 table
= bgp_node_get_bgp_table_info(prn
);
174 rn
= bgp_node_lookup(table
, p
);
179 /* Allocate bgp_path_info_extra */
180 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
182 struct bgp_path_info_extra
*new;
183 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
184 sizeof(struct bgp_path_info_extra
));
185 new->label
[0] = MPLS_INVALID_LABEL
;
187 new->bgp_fs_pbr
= NULL
;
188 new->bgp_fs_iprule
= NULL
;
192 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
194 struct bgp_path_info_extra
*e
;
196 if (!extra
|| !*extra
)
201 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
206 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
209 /* FIXME: since multiple e may have the same e->parent
210 * and e->parent->net is holding a refcount for each
211 * of them, we need to do some fudging here.
213 * WARNING: if bpi->net->lock drops to 0, bpi may be
214 * freed as well (because bpi->net was holding the
215 * last reference to bpi) => write after free!
219 bpi
= bgp_path_info_lock(bpi
);
220 refcount
= bpi
->net
->lock
- 1;
221 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
224 bgp_path_info_unlock(bpi
);
226 bgp_path_info_unlock(e
->parent
);
231 bgp_unlock(e
->bgp_orig
);
233 if ((*extra
)->bgp_fs_iprule
)
234 list_delete(&((*extra
)->bgp_fs_iprule
));
235 if ((*extra
)->bgp_fs_pbr
)
236 list_delete(&((*extra
)->bgp_fs_pbr
));
237 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
242 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
243 * allocated if required.
245 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
248 pi
->extra
= bgp_path_info_extra_new();
252 /* Free bgp route information. */
253 static void bgp_path_info_free(struct bgp_path_info
*path
)
255 bgp_attr_unintern(&path
->attr
);
257 bgp_unlink_nexthop(path
);
258 bgp_path_info_extra_free(&path
->extra
);
259 bgp_path_info_mpath_free(&path
->mpath
);
261 bgp_addpath_free_info_data(&path
->tx_addpath
,
262 &path
->net
->tx_addpath
);
264 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
266 XFREE(MTYPE_BGP_ROUTE
, path
);
269 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
275 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
277 assert(path
&& path
->lock
> 0);
280 if (path
->lock
== 0) {
282 zlog_debug ("%s: unlocked and freeing", __func__
);
283 zlog_backtrace (LOG_DEBUG
);
285 bgp_path_info_free(path
);
292 zlog_debug ("%s: unlocked to 1", __func__
);
293 zlog_backtrace (LOG_DEBUG
);
300 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
301 static int bgp_node_set_defer_flag(struct bgp_node
*rn
, bool delete)
304 struct bgp_path_info
*old_pi
, *nextpi
;
306 struct bgp
*bgp
= NULL
;
307 struct bgp_table
*table
= NULL
;
310 char buf
[PREFIX2STR_BUFFER
];
312 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
313 * then the route selection is deferred
315 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
318 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
319 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
320 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
321 zlog_debug("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
) &&
352 (old_pi
&& old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
360 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
363 if (set_flag
&& table
) {
364 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
365 SET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
366 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
367 if (rn
->rt_node
== NULL
)
368 rn
->rt_node
= listnode_add(
369 bgp
->gr_info
[afi
][safi
].route_list
, rn
);
370 if (BGP_DEBUG(update
, UPDATE_OUT
))
371 zlog_debug("DEFER route %s, rn %p, node %p",
372 buf
, rn
, rn
->rt_node
);
379 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
381 struct bgp_path_info
*top
;
383 top
= bgp_node_get_bgp_path_info(rn
);
389 bgp_node_set_bgp_path_info(rn
, pi
);
391 bgp_path_info_lock(pi
);
393 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
394 bgp_node_set_defer_flag(rn
, false);
397 /* Do the actual removal of info from RIB, for use by bgp_process
398 completion callback *only* */
399 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
402 pi
->next
->prev
= pi
->prev
;
404 pi
->prev
->next
= pi
->next
;
406 bgp_node_set_bgp_path_info(rn
, pi
->next
);
408 bgp_path_info_mpath_dequeue(pi
);
409 bgp_path_info_unlock(pi
);
413 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
415 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
416 /* set of previous already took care of pcount */
417 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
420 /* undo the effects of a previous call to bgp_path_info_delete; typically
421 called when a route is deleted and then quickly re-added before the
422 deletion has been processed */
423 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
425 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
426 /* unset of previous already took care of pcount */
427 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
430 /* Adjust pcount as required */
431 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
433 struct bgp_table
*table
;
435 assert(rn
&& bgp_node_table(rn
));
436 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
438 table
= bgp_node_table(rn
);
440 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
443 if (!BGP_PATH_COUNTABLE(pi
)
444 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
446 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
448 /* slight hack, but more robust against errors. */
449 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
450 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
452 flog_err(EC_LIB_DEVELOPMENT
,
453 "Asked to decrement 0 prefix count for peer");
454 } else if (BGP_PATH_COUNTABLE(pi
)
455 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
456 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
457 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
461 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
462 struct bgp_path_info
*pi2
)
464 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
467 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
468 * This is here primarily to keep prefix-count in check.
470 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
473 SET_FLAG(pi
->flags
, flag
);
475 /* early bath if we know it's not a flag that changes countability state
477 if (!CHECK_FLAG(flag
,
478 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
481 bgp_pcount_adjust(rn
, pi
);
484 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
487 UNSET_FLAG(pi
->flags
, flag
);
489 /* early bath if we know it's not a flag that changes countability state
491 if (!CHECK_FLAG(flag
,
492 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
495 bgp_pcount_adjust(rn
, pi
);
498 /* Get MED value. If MED value is missing and "bgp bestpath
499 missing-as-worst" is specified, treat it as the worst value. */
500 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
502 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
505 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
512 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
514 if (pi
->addpath_rx_id
)
515 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
518 sprintf(buf
, "path %s", pi
->peer
->host
);
521 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
523 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
524 struct bgp_path_info
*exist
, int *paths_eq
,
525 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
526 char *pfx_buf
, afi_t afi
, safi_t safi
,
527 enum bgp_path_selection_reason
*reason
)
529 struct attr
*newattr
, *existattr
;
530 bgp_peer_sort_t new_sort
;
531 bgp_peer_sort_t exist_sort
;
537 uint32_t exist_weight
;
538 uint32_t newm
, existm
;
539 struct in_addr new_id
;
540 struct in_addr exist_id
;
543 int internal_as_route
;
546 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
547 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
549 uint32_t exist_mm_seq
;
556 *reason
= bgp_path_selection_none
;
558 zlog_debug("%s: new is NULL", pfx_buf
);
563 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
566 *reason
= bgp_path_selection_first
;
568 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
574 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
575 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
576 pfx_buf
, new_buf
, new->flags
, exist_buf
,
581 existattr
= exist
->attr
;
583 /* For EVPN routes, we cannot just go by local vs remote, we have to
584 * look at the MAC mobility sequence number, if present.
586 if (safi
== SAFI_EVPN
) {
587 /* This is an error condition described in RFC 7432 Section
589 * states that in this scenario "the PE MUST alert the operator"
591 * does not state what other action to take. In order to provide
593 * consistency in this scenario we are going to prefer the path
597 if (newattr
->sticky
!= existattr
->sticky
) {
599 prefix2str(&new->net
->p
, pfx_buf
,
601 * PREFIX2STR_BUFFER
);
602 bgp_path_info_path_with_addpath_rx_str(new,
604 bgp_path_info_path_with_addpath_rx_str(
608 if (newattr
->sticky
&& !existattr
->sticky
) {
609 *reason
= bgp_path_selection_evpn_sticky_mac
;
612 "%s: %s wins over %s due to sticky MAC flag",
613 pfx_buf
, new_buf
, exist_buf
);
617 if (!newattr
->sticky
&& existattr
->sticky
) {
618 *reason
= bgp_path_selection_evpn_sticky_mac
;
621 "%s: %s loses to %s due to sticky MAC flag",
622 pfx_buf
, new_buf
, exist_buf
);
627 new_mm_seq
= mac_mobility_seqnum(newattr
);
628 exist_mm_seq
= mac_mobility_seqnum(existattr
);
630 if (new_mm_seq
> exist_mm_seq
) {
631 *reason
= bgp_path_selection_evpn_seq
;
634 "%s: %s wins over %s due to MM seq %u > %u",
635 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
640 if (new_mm_seq
< exist_mm_seq
) {
641 *reason
= bgp_path_selection_evpn_seq
;
644 "%s: %s loses to %s due to MM seq %u < %u",
645 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
651 * if sequence numbers are the same path with the lowest IP
654 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
656 *reason
= bgp_path_selection_evpn_lower_ip
;
659 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
660 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
661 inet_ntoa(new->attr
->nexthop
));
665 *reason
= bgp_path_selection_evpn_lower_ip
;
668 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
669 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
670 inet_ntoa(new->attr
->nexthop
));
675 /* 1. Weight check. */
676 new_weight
= newattr
->weight
;
677 exist_weight
= existattr
->weight
;
679 if (new_weight
> exist_weight
) {
680 *reason
= bgp_path_selection_weight
;
682 zlog_debug("%s: %s wins over %s due to weight %d > %d",
683 pfx_buf
, new_buf
, exist_buf
, new_weight
,
688 if (new_weight
< exist_weight
) {
689 *reason
= bgp_path_selection_weight
;
691 zlog_debug("%s: %s loses to %s due to weight %d < %d",
692 pfx_buf
, new_buf
, exist_buf
, new_weight
,
697 /* 2. Local preference check. */
698 new_pref
= exist_pref
= bgp
->default_local_pref
;
700 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
701 new_pref
= newattr
->local_pref
;
702 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
703 exist_pref
= existattr
->local_pref
;
705 if (new_pref
> exist_pref
) {
706 *reason
= bgp_path_selection_local_pref
;
709 "%s: %s wins over %s due to localpref %d > %d",
710 pfx_buf
, new_buf
, exist_buf
, new_pref
,
715 if (new_pref
< exist_pref
) {
716 *reason
= bgp_path_selection_local_pref
;
719 "%s: %s loses to %s due to localpref %d < %d",
720 pfx_buf
, new_buf
, exist_buf
, new_pref
,
725 /* 3. Local route check. We prefer:
727 * - BGP_ROUTE_AGGREGATE
728 * - BGP_ROUTE_REDISTRIBUTE
730 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
731 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
732 *reason
= bgp_path_selection_local_route
;
735 "%s: %s wins over %s due to preferred BGP_ROUTE type",
736 pfx_buf
, new_buf
, exist_buf
);
740 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
741 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
742 *reason
= bgp_path_selection_local_route
;
745 "%s: %s loses to %s due to preferred BGP_ROUTE type",
746 pfx_buf
, new_buf
, exist_buf
);
750 /* 4. AS path length check. */
751 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
752 int exist_hops
= aspath_count_hops(existattr
->aspath
);
753 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
755 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
758 aspath_hops
= aspath_count_hops(newattr
->aspath
);
759 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
761 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
762 *reason
= bgp_path_selection_confed_as_path
;
765 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
766 pfx_buf
, new_buf
, exist_buf
,
768 (exist_hops
+ exist_confeds
));
772 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
773 *reason
= bgp_path_selection_confed_as_path
;
776 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
777 pfx_buf
, new_buf
, exist_buf
,
779 (exist_hops
+ exist_confeds
));
783 int newhops
= aspath_count_hops(newattr
->aspath
);
785 if (newhops
< exist_hops
) {
786 *reason
= bgp_path_selection_as_path
;
789 "%s: %s wins over %s due to aspath hopcount %d < %d",
790 pfx_buf
, new_buf
, exist_buf
,
791 newhops
, exist_hops
);
795 if (newhops
> exist_hops
) {
796 *reason
= bgp_path_selection_as_path
;
799 "%s: %s loses to %s due to aspath hopcount %d > %d",
800 pfx_buf
, new_buf
, exist_buf
,
801 newhops
, exist_hops
);
807 /* 5. Origin check. */
808 if (newattr
->origin
< existattr
->origin
) {
809 *reason
= bgp_path_selection_origin
;
811 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
812 pfx_buf
, new_buf
, exist_buf
,
813 bgp_origin_long_str
[newattr
->origin
],
814 bgp_origin_long_str
[existattr
->origin
]);
818 if (newattr
->origin
> existattr
->origin
) {
819 *reason
= bgp_path_selection_origin
;
821 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
822 pfx_buf
, new_buf
, exist_buf
,
823 bgp_origin_long_str
[newattr
->origin
],
824 bgp_origin_long_str
[existattr
->origin
]);
829 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
830 && aspath_count_hops(existattr
->aspath
) == 0);
831 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
832 && aspath_count_confeds(existattr
->aspath
) > 0
833 && aspath_count_hops(newattr
->aspath
) == 0
834 && aspath_count_hops(existattr
->aspath
) == 0);
836 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
837 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
838 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
839 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
840 || internal_as_route
) {
841 new_med
= bgp_med_value(new->attr
, bgp
);
842 exist_med
= bgp_med_value(exist
->attr
, bgp
);
844 if (new_med
< exist_med
) {
845 *reason
= bgp_path_selection_med
;
848 "%s: %s wins over %s due to MED %d < %d",
849 pfx_buf
, new_buf
, exist_buf
, new_med
,
854 if (new_med
> exist_med
) {
855 *reason
= bgp_path_selection_med
;
858 "%s: %s loses to %s due to MED %d > %d",
859 pfx_buf
, new_buf
, exist_buf
, new_med
,
865 /* 7. Peer type check. */
866 new_sort
= new->peer
->sort
;
867 exist_sort
= exist
->peer
->sort
;
869 if (new_sort
== BGP_PEER_EBGP
870 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
871 *reason
= bgp_path_selection_peer
;
874 "%s: %s wins over %s due to eBGP peer > iBGP peer",
875 pfx_buf
, new_buf
, exist_buf
);
879 if (exist_sort
== BGP_PEER_EBGP
880 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
881 *reason
= bgp_path_selection_peer
;
884 "%s: %s loses to %s due to iBGP peer < eBGP peer",
885 pfx_buf
, new_buf
, exist_buf
);
889 /* 8. IGP metric check. */
893 newm
= new->extra
->igpmetric
;
895 existm
= exist
->extra
->igpmetric
;
900 "%s: %s wins over %s due to IGP metric %d < %d",
901 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
908 "%s: %s loses to %s due to IGP metric %d > %d",
909 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
913 /* 9. Same IGP metric. Compare the cluster list length as
914 representative of IGP hops metric. Rewrite the metric value
915 pair (newm, existm) with the cluster list length. Prefer the
916 path with smaller cluster list length. */
917 if (newm
== existm
) {
918 if (peer_sort(new->peer
) == BGP_PEER_IBGP
919 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
920 && (mpath_cfg
== NULL
922 mpath_cfg
->ibgp_flags
,
923 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
924 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
925 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
930 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
931 pfx_buf
, new_buf
, exist_buf
,
939 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
940 pfx_buf
, new_buf
, exist_buf
,
947 /* 10. confed-external vs. confed-internal */
948 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
949 if (new_sort
== BGP_PEER_CONFED
950 && exist_sort
== BGP_PEER_IBGP
) {
951 *reason
= bgp_path_selection_confed
;
954 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
955 pfx_buf
, new_buf
, exist_buf
);
959 if (exist_sort
== BGP_PEER_CONFED
960 && new_sort
== BGP_PEER_IBGP
) {
961 *reason
= bgp_path_selection_confed
;
964 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
965 pfx_buf
, new_buf
, exist_buf
);
970 /* 11. Maximum path check. */
971 if (newm
== existm
) {
972 /* If one path has a label but the other does not, do not treat
973 * them as equals for multipath
975 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
977 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
980 "%s: %s and %s cannot be multipath, one has a label while the other does not",
981 pfx_buf
, new_buf
, exist_buf
);
982 } else if (bgp_flag_check(bgp
,
983 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
986 * For the two paths, all comparison steps till IGP
988 * have succeeded - including AS_PATH hop count. Since
990 * bestpath as-path multipath-relax' knob is on, we
992 * an exact match of AS_PATH. Thus, mark the paths are
994 * That will trigger both these paths to get into the
1002 "%s: %s and %s are equal via multipath-relax",
1003 pfx_buf
, new_buf
, exist_buf
);
1004 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1005 if (aspath_cmp(new->attr
->aspath
,
1006 exist
->attr
->aspath
)) {
1011 "%s: %s and %s are equal via matching aspaths",
1012 pfx_buf
, new_buf
, exist_buf
);
1014 } else if (new->peer
->as
== exist
->peer
->as
) {
1019 "%s: %s and %s are equal via same remote-as",
1020 pfx_buf
, new_buf
, exist_buf
);
1024 * TODO: If unequal cost ibgp multipath is enabled we can
1025 * mark the paths as equal here instead of returning
1030 "%s: %s wins over %s after IGP metric comparison",
1031 pfx_buf
, new_buf
, exist_buf
);
1034 "%s: %s loses to %s after IGP metric comparison",
1035 pfx_buf
, new_buf
, exist_buf
);
1037 *reason
= bgp_path_selection_igp_metric
;
1041 /* 12. If both paths are external, prefer the path that was received
1042 first (the oldest one). This step minimizes route-flap, since a
1043 newer path won't displace an older one, even if it was the
1044 preferred route based on the additional decision criteria below. */
1045 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
1046 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1047 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1048 *reason
= bgp_path_selection_older
;
1051 "%s: %s wins over %s due to oldest external",
1052 pfx_buf
, new_buf
, exist_buf
);
1056 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1057 *reason
= bgp_path_selection_older
;
1060 "%s: %s loses to %s due to oldest external",
1061 pfx_buf
, new_buf
, exist_buf
);
1066 /* 13. Router-ID comparision. */
1067 /* If one of the paths is "stale", the corresponding peer router-id will
1068 * be 0 and would always win over the other path. If originator id is
1069 * used for the comparision, it will decide which path is better.
1071 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1072 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1074 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1075 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1076 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1078 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1080 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1081 *reason
= bgp_path_selection_router_id
;
1084 "%s: %s wins over %s due to Router-ID comparison",
1085 pfx_buf
, new_buf
, exist_buf
);
1089 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1090 *reason
= bgp_path_selection_router_id
;
1093 "%s: %s loses to %s due to Router-ID comparison",
1094 pfx_buf
, new_buf
, exist_buf
);
1098 /* 14. Cluster length comparision. */
1099 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1100 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1102 if (new_cluster
< exist_cluster
) {
1103 *reason
= bgp_path_selection_cluster_length
;
1106 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1107 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1112 if (new_cluster
> exist_cluster
) {
1113 *reason
= bgp_path_selection_cluster_length
;
1116 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1117 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1122 /* 15. Neighbor address comparision. */
1123 /* Do this only if neither path is "stale" as stale paths do not have
1124 * valid peer information (as the connection may or may not be up).
1126 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1127 *reason
= bgp_path_selection_stale
;
1130 "%s: %s wins over %s due to latter path being STALE",
1131 pfx_buf
, new_buf
, exist_buf
);
1135 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1136 *reason
= bgp_path_selection_stale
;
1139 "%s: %s loses to %s due to former path being STALE",
1140 pfx_buf
, new_buf
, exist_buf
);
1144 /* locally configured routes to advertise do not have su_remote */
1145 if (new->peer
->su_remote
== NULL
) {
1146 *reason
= bgp_path_selection_local_configured
;
1149 if (exist
->peer
->su_remote
== NULL
) {
1150 *reason
= bgp_path_selection_local_configured
;
1154 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1157 *reason
= bgp_path_selection_neighbor_ip
;
1160 "%s: %s loses to %s due to Neighor IP comparison",
1161 pfx_buf
, new_buf
, exist_buf
);
1166 *reason
= bgp_path_selection_neighbor_ip
;
1169 "%s: %s wins over %s due to Neighor IP comparison",
1170 pfx_buf
, new_buf
, exist_buf
);
1174 *reason
= bgp_path_selection_default
;
1176 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1177 pfx_buf
, new_buf
, exist_buf
);
1182 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1183 * is preferred, or 0 if they are the same (usually will only occur if
1184 * multipath is enabled
1185 * This version is compatible with */
1186 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1187 struct bgp_path_info
*exist
, char *pfx_buf
,
1188 afi_t afi
, safi_t safi
,
1189 enum bgp_path_selection_reason
*reason
)
1193 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1207 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1208 struct attr
*attr
, afi_t afi
,
1211 struct bgp_filter
*filter
;
1213 filter
= &peer
->filter
[afi
][safi
];
1215 #define FILTER_EXIST_WARN(F, f, filter) \
1216 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1217 zlog_debug("%s: Could not find configured input %s-list %s!", \
1218 peer->host, #f, F##_IN_NAME(filter));
1220 if (DISTRIBUTE_IN_NAME(filter
)) {
1221 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1223 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1227 if (PREFIX_LIST_IN_NAME(filter
)) {
1228 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1230 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1234 if (FILTER_LIST_IN_NAME(filter
)) {
1235 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1237 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1242 return FILTER_PERMIT
;
1243 #undef FILTER_EXIST_WARN
1246 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1247 struct attr
*attr
, afi_t afi
,
1250 struct bgp_filter
*filter
;
1252 filter
= &peer
->filter
[afi
][safi
];
1254 #define FILTER_EXIST_WARN(F, f, filter) \
1255 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1256 zlog_debug("%s: Could not find configured output %s-list %s!", \
1257 peer->host, #f, F##_OUT_NAME(filter));
1259 if (DISTRIBUTE_OUT_NAME(filter
)) {
1260 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1262 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1266 if (PREFIX_LIST_OUT_NAME(filter
)) {
1267 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1269 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1274 if (FILTER_LIST_OUT_NAME(filter
)) {
1275 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1277 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1282 return FILTER_PERMIT
;
1283 #undef FILTER_EXIST_WARN
1286 /* If community attribute includes no_export then return 1. */
1287 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1289 if (attr
->community
) {
1290 /* NO_ADVERTISE check. */
1291 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1294 /* NO_EXPORT check. */
1295 if (peer
->sort
== BGP_PEER_EBGP
1296 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1299 /* NO_EXPORT_SUBCONFED check. */
1300 if (peer
->sort
== BGP_PEER_EBGP
1301 || peer
->sort
== BGP_PEER_CONFED
)
1302 if (community_include(attr
->community
,
1303 COMMUNITY_NO_EXPORT_SUBCONFED
))
1309 /* Route reflection loop check. */
1310 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1312 struct in_addr cluster_id
;
1314 if (attr
->cluster
) {
1315 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1316 cluster_id
= peer
->bgp
->cluster_id
;
1318 cluster_id
= peer
->bgp
->router_id
;
1320 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1326 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1327 struct attr
*attr
, afi_t afi
, safi_t safi
,
1328 const char *rmap_name
, mpls_label_t
*label
,
1329 uint32_t num_labels
, struct bgp_node
*rn
)
1331 struct bgp_filter
*filter
;
1332 struct bgp_path_info rmap_path
= { 0 };
1333 struct bgp_path_info_extra extra
= { 0 };
1334 route_map_result_t ret
;
1335 struct route_map
*rmap
= NULL
;
1337 filter
= &peer
->filter
[afi
][safi
];
1339 /* Apply default weight value. */
1340 if (peer
->weight
[afi
][safi
])
1341 attr
->weight
= peer
->weight
[afi
][safi
];
1344 rmap
= route_map_lookup_by_name(rmap_name
);
1349 if (ROUTE_MAP_IN_NAME(filter
)) {
1350 rmap
= ROUTE_MAP_IN(filter
);
1357 /* Route map apply. */
1359 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1360 /* Duplicate current value to new strucutre for modification. */
1361 rmap_path
.peer
= peer
;
1362 rmap_path
.attr
= attr
;
1363 rmap_path
.extra
= &extra
;
1366 extra
.num_labels
= num_labels
;
1367 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1368 memcpy(extra
.label
, label
,
1369 num_labels
* sizeof(mpls_label_t
));
1371 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1373 /* Apply BGP route map to the attribute. */
1374 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1376 peer
->rmap_type
= 0;
1378 if (ret
== RMAP_DENYMATCH
)
1384 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1385 struct attr
*attr
, afi_t afi
, safi_t safi
,
1386 const char *rmap_name
)
1388 struct bgp_path_info rmap_path
;
1389 route_map_result_t ret
;
1390 struct route_map
*rmap
= NULL
;
1394 * So if we get to this point and have no rmap_name
1395 * we want to just show the output as it currently
1401 /* Apply default weight value. */
1402 if (peer
->weight
[afi
][safi
])
1403 attr
->weight
= peer
->weight
[afi
][safi
];
1405 rmap
= route_map_lookup_by_name(rmap_name
);
1408 * If we have a route map name and we do not find
1409 * the routemap that means we have an implicit
1415 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1416 /* Route map apply. */
1417 /* Duplicate current value to new strucutre for modification. */
1418 rmap_path
.peer
= peer
;
1419 rmap_path
.attr
= attr
;
1421 rmap_type
= peer
->rmap_type
;
1422 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1424 /* Apply BGP route map to the attribute. */
1425 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1427 peer
->rmap_type
= rmap_type
;
1429 if (ret
== RMAP_DENYMATCH
)
1431 * caller has multiple error paths with bgp_attr_flush()
1438 /* If this is an EBGP peer with remove-private-AS */
1439 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1440 struct peer
*peer
, struct attr
*attr
)
1442 if (peer
->sort
== BGP_PEER_EBGP
1443 && (peer_af_flag_check(peer
, afi
, safi
,
1444 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1445 || peer_af_flag_check(peer
, afi
, safi
,
1446 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1447 || peer_af_flag_check(peer
, afi
, safi
,
1448 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1449 || peer_af_flag_check(peer
, afi
, safi
,
1450 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1451 // Take action on the entire aspath
1452 if (peer_af_flag_check(peer
, afi
, safi
,
1453 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1454 || peer_af_flag_check(peer
, afi
, safi
,
1455 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1456 if (peer_af_flag_check(
1458 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1459 attr
->aspath
= aspath_replace_private_asns(
1460 attr
->aspath
, bgp
->as
, peer
->as
);
1462 // The entire aspath consists of private ASNs so create
1464 else if (aspath_private_as_check(attr
->aspath
))
1465 attr
->aspath
= aspath_empty_get();
1467 // There are some public and some private ASNs, remove
1470 attr
->aspath
= aspath_remove_private_asns(
1471 attr
->aspath
, peer
->as
);
1474 // 'all' was not specified so the entire aspath must be private
1476 // for us to do anything
1477 else if (aspath_private_as_check(attr
->aspath
)) {
1478 if (peer_af_flag_check(
1480 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1481 attr
->aspath
= aspath_replace_private_asns(
1482 attr
->aspath
, bgp
->as
, peer
->as
);
1484 attr
->aspath
= aspath_empty_get();
1489 /* If this is an EBGP peer with as-override */
1490 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1491 struct peer
*peer
, struct attr
*attr
)
1493 if (peer
->sort
== BGP_PEER_EBGP
1494 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1495 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1496 attr
->aspath
= aspath_replace_specific_asn(
1497 attr
->aspath
, peer
->as
, bgp
->as
);
1501 void bgp_attr_add_gshut_community(struct attr
*attr
)
1503 struct community
*old
;
1504 struct community
*new;
1505 struct community
*merge
;
1506 struct community
*gshut
;
1508 old
= attr
->community
;
1509 gshut
= community_str2com("graceful-shutdown");
1514 merge
= community_merge(community_dup(old
), gshut
);
1516 if (old
->refcnt
== 0)
1517 community_free(&old
);
1519 new = community_uniq_sort(merge
);
1520 community_free(&merge
);
1522 new = community_dup(gshut
);
1525 community_free(&gshut
);
1526 attr
->community
= new;
1527 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1529 /* When we add the graceful-shutdown community we must also
1530 * lower the local-preference */
1531 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1532 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1536 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1538 if (family
== AF_INET
) {
1539 attr
->nexthop
.s_addr
= 0;
1540 attr
->mp_nexthop_global_in
.s_addr
= 0;
1542 if (family
== AF_INET6
)
1543 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1544 if (family
== AF_EVPN
)
1545 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1548 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1549 struct update_subgroup
*subgrp
, struct prefix
*p
,
1552 struct bgp_filter
*filter
;
1555 struct peer
*onlypeer
;
1557 struct attr
*piattr
;
1558 char buf
[PREFIX_STRLEN
];
1559 route_map_result_t ret
;
1564 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1566 if (DISABLE_BGP_ANNOUNCE
)
1569 afi
= SUBGRP_AFI(subgrp
);
1570 safi
= SUBGRP_SAFI(subgrp
);
1571 peer
= SUBGRP_PEER(subgrp
);
1573 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1574 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1577 filter
= &peer
->filter
[afi
][safi
];
1578 bgp
= SUBGRP_INST(subgrp
);
1579 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1583 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1584 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1585 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1588 * direct and direct_ext type routes originate internally even
1589 * though they can have peer pointers that reference other
1592 prefix2str(p
, buf
, PREFIX_STRLEN
);
1593 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1599 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1600 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1601 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1602 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1604 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1609 /* With addpath we may be asked to TX all kinds of paths so make sure
1611 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1612 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1613 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1617 /* If this is not the bestpath then check to see if there is an enabled
1619 * feature that requires us to advertise it */
1620 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1621 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1626 /* Aggregate-address suppress check. */
1627 if (pi
->extra
&& pi
->extra
->suppress
)
1628 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1633 * If we are doing VRF 2 VRF leaking via the import
1634 * statement, we want to prevent the route going
1635 * off box as that the RT and RD created are localy
1636 * significant and globaly useless.
1638 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1639 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1642 /* If it's labeled safi, make sure the route has a valid label. */
1643 if (safi
== SAFI_LABELED_UNICAST
) {
1644 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1645 if (!bgp_is_valid_label(&label
)) {
1646 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1647 zlog_debug("u%" PRIu64
":s%" PRIu64
1648 " %s/%d is filtered - no label (%p)",
1649 subgrp
->update_group
->id
, subgrp
->id
,
1650 inet_ntop(p
->family
, &p
->u
.prefix
,
1651 buf
, SU_ADDRSTRLEN
),
1652 p
->prefixlen
, &label
);
1657 /* Do not send back route to sender. */
1658 if (onlypeer
&& from
== onlypeer
) {
1662 /* Do not send the default route in the BGP table if the neighbor is
1663 * configured for default-originate */
1664 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1665 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1666 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1668 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1672 /* Transparency check. */
1673 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1674 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1679 /* If community is not disabled check the no-export and local. */
1680 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1681 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1683 "subgrpannouncecheck: community filter check fail");
1687 /* If the attribute has originator-id and it is same as remote
1689 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1690 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1691 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1693 "%s [Update:SEND] %s originator-id is same as "
1696 prefix2str(p
, buf
, sizeof(buf
)));
1700 /* ORF prefix-list filter check */
1701 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1702 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1703 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1704 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1705 if (peer
->orf_plist
[afi
][safi
]) {
1706 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1708 if (bgp_debug_update(NULL
, p
,
1709 subgrp
->update_group
, 0))
1711 "%s [Update:SEND] %s is filtered via ORF",
1719 /* Output filter check. */
1720 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1721 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1722 zlog_debug("%s [Update:SEND] %s is filtered",
1723 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1727 /* AS path loop check. */
1728 if (onlypeer
&& onlypeer
->as_path_loop_detection
1729 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1730 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1732 "%s [Update:SEND] suppress announcement to peer AS %u "
1733 "that is part of AS path.",
1734 onlypeer
->host
, onlypeer
->as
);
1738 /* If we're a CONFED we need to loop check the CONFED ID too */
1739 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1740 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1741 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1743 "%s [Update:SEND] suppress announcement to peer AS %u"
1745 peer
->host
, bgp
->confed_id
);
1750 /* Route-Reflect check. */
1751 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1756 /* IBGP reflection check. */
1757 if (reflect
&& !samepeer_safe
) {
1758 /* A route from a Client peer. */
1759 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1760 PEER_FLAG_REFLECTOR_CLIENT
)) {
1761 /* Reflect to all the Non-Client peers and also to the
1762 Client peers other than the originator. Originator
1764 is already done. So there is noting to do. */
1765 /* no bgp client-to-client reflection check. */
1766 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1767 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1768 PEER_FLAG_REFLECTOR_CLIENT
))
1771 /* A route from a Non-client peer. Reflect to all other
1773 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1774 PEER_FLAG_REFLECTOR_CLIENT
))
1779 /* For modify attribute, copy it to temporary structure. */
1782 /* If local-preference is not set. */
1783 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1784 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1785 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1786 attr
->local_pref
= bgp
->default_local_pref
;
1789 /* If originator-id is not set and the route is to be reflected,
1790 set the originator id */
1792 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1793 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1794 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1797 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1799 if (peer
->sort
== BGP_PEER_EBGP
1800 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1801 if (from
!= bgp
->peer_self
&& !transparent
1802 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1803 PEER_FLAG_MED_UNCHANGED
))
1805 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1808 /* Since the nexthop attribute can vary per peer, it is not explicitly
1810 * in announce check, only certain flags and length (or number of
1812 * -- for IPv6/MP_REACH) are set here in order to guide the update
1814 * code in setting the nexthop(s) on a per peer basis in
1816 * Typically, the source nexthop in the attribute is preserved but in
1818 * scenarios where we know it will always be overwritten, we reset the
1819 * nexthop to "0" in an attempt to achieve better Update packing. An
1820 * example of this is when a prefix from each of 2 IBGP peers needs to
1822 * announced to an EBGP peer (and they have the same attributes barring
1826 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1828 #define NEXTHOP_IS_V6 \
1829 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1830 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1831 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1832 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1834 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1836 * the peer (group) is configured to receive link-local nexthop
1838 * and it is available in the prefix OR we're not reflecting the route,
1839 * link-local nexthop address is valid and
1840 * the peer (group) to whom we're going to announce is on a shared
1842 * and this is either a self-originated route or the peer is EBGP.
1843 * By checking if nexthop LL address is valid we are sure that
1844 * we do not announce LL address as `::`.
1846 if (NEXTHOP_IS_V6
) {
1847 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1848 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1849 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1850 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1852 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1853 && peer
->shared_network
1854 && (from
== bgp
->peer_self
1855 || peer
->sort
== BGP_PEER_EBGP
))) {
1856 attr
->mp_nexthop_len
=
1857 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1860 /* Clear off link-local nexthop in source, whenever it is not
1862 * ensure more prefixes share the same attribute for
1865 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1866 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1867 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1870 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1871 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1873 /* Route map & unsuppress-map apply. */
1874 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1875 struct bgp_path_info rmap_path
= {0};
1876 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1877 struct attr dummy_attr
= {0};
1879 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1880 rmap_path
.peer
= peer
;
1881 rmap_path
.attr
= attr
;
1885 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1886 sizeof(struct bgp_path_info_extra
));
1887 rmap_path
.extra
= &dummy_rmap_path_extra
;
1890 /* don't confuse inbound and outbound setting */
1891 RESET_FLAG(attr
->rmap_change_flags
);
1894 * The route reflector is not allowed to modify the attributes
1895 * of the reflected IBGP routes unless explicitly allowed.
1897 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1898 && !bgp_flag_check(bgp
,
1899 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1901 rmap_path
.attr
= &dummy_attr
;
1904 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1906 if (pi
->extra
&& pi
->extra
->suppress
)
1907 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1908 RMAP_BGP
, &rmap_path
);
1910 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1911 RMAP_BGP
, &rmap_path
);
1913 peer
->rmap_type
= 0;
1915 if (ret
== RMAP_DENYMATCH
) {
1916 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1917 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1918 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1920 bgp_attr_flush(attr
);
1925 /* RFC 8212 to prevent route leaks.
1926 * This specification intends to improve this situation by requiring the
1927 * explicit configuration of both BGP Import and Export Policies for any
1928 * External BGP (EBGP) session such as customers, peers, or
1929 * confederation boundaries for all enabled address families. Through
1930 * codification of the aforementioned requirement, operators will
1931 * benefit from consistent behavior across different BGP
1934 if (peer
->bgp
->ebgp_requires_policy
1935 == DEFAULT_EBGP_POLICY_ENABLED
)
1936 if (!bgp_outbound_policy_exists(peer
, filter
))
1939 /* draft-ietf-idr-deprecate-as-set-confed-set
1940 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1941 * Eventually, This document (if approved) updates RFC 4271
1942 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1943 * and obsoletes RFC 6472.
1945 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
1946 if (aspath_check_as_sets(attr
->aspath
))
1949 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1950 if (peer
->sort
== BGP_PEER_IBGP
1951 || peer
->sort
== BGP_PEER_CONFED
) {
1952 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1953 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1955 bgp_attr_add_gshut_community(attr
);
1959 /* After route-map has been applied, we check to see if the nexthop to
1960 * be carried in the attribute (that is used for the announcement) can
1961 * be cleared off or not. We do this in all cases where we would be
1962 * setting the nexthop to "ourselves". For IPv6, we only need to
1964 * the global nexthop here; the link-local nexthop would have been
1966 * already, and if not, it is required by the update formation code.
1967 * Also see earlier comments in this function.
1970 * If route-map has performed some operation on the nexthop or the peer
1971 * configuration says to pass it unchanged, we cannot reset the nexthop
1972 * here, so only attempt to do it if these aren't true. Note that the
1973 * route-map handler itself might have cleared the nexthop, if for
1975 * it is configured as 'peer-address'.
1977 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1978 piattr
->rmap_change_flags
)
1980 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1981 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1982 /* We can reset the nexthop, if setting (or forcing) it to
1984 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1985 PEER_FLAG_NEXTHOP_SELF
)
1986 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1987 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1989 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1990 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1991 subgroup_announce_reset_nhop(
1992 (peer_cap_enhe(peer
, afi
, safi
)
1996 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1997 /* Can also reset the nexthop if announcing to EBGP, but
1999 * no peer in the subgroup is on a shared subnet.
2000 * Note: 3rd party nexthop currently implemented for
2003 if ((p
->family
== AF_INET
) &&
2004 (!bgp_subgrp_multiaccess_check_v4(
2007 subgroup_announce_reset_nhop(
2008 (peer_cap_enhe(peer
, afi
, safi
)
2013 if ((p
->family
== AF_INET6
) &&
2014 (!bgp_subgrp_multiaccess_check_v6(
2015 piattr
->mp_nexthop_global
,
2017 subgroup_announce_reset_nhop(
2018 (peer_cap_enhe(peer
, afi
, safi
)
2025 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2027 * This flag is used for leaked vpn-vrf routes
2029 int family
= p
->family
;
2031 if (peer_cap_enhe(peer
, afi
, safi
))
2034 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2036 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2037 __func__
, family2str(family
));
2038 subgroup_announce_reset_nhop(family
, attr
);
2042 /* If IPv6/MP and nexthop does not have any override and happens
2044 * be a link-local address, reset it so that we don't pass along
2046 * source's link-local IPv6 address to recipients who may not be
2048 * the same interface.
2050 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2051 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
2052 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2058 static int bgp_route_select_timer_expire(struct thread
*thread
)
2060 struct afi_safi_info
*info
;
2065 info
= THREAD_ARG(thread
);
2070 if (BGP_DEBUG(update
, UPDATE_OUT
))
2071 zlog_debug("afi %d, safi %d : route select timer expired",
2074 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2076 XFREE(MTYPE_TMP
, info
);
2078 /* Best path selection */
2079 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2082 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
2083 struct bgp_maxpaths_cfg
*mpath_cfg
,
2084 struct bgp_path_info_pair
*result
, afi_t afi
,
2087 struct bgp_path_info
*new_select
;
2088 struct bgp_path_info
*old_select
;
2089 struct bgp_path_info
*pi
;
2090 struct bgp_path_info
*pi1
;
2091 struct bgp_path_info
*pi2
;
2092 struct bgp_path_info
*nextpi
= NULL
;
2093 int paths_eq
, do_mpath
, debug
;
2094 struct list mp_list
;
2095 char pfx_buf
[PREFIX2STR_BUFFER
];
2096 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2098 bgp_mp_list_init(&mp_list
);
2100 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2102 debug
= bgp_debug_bestpath(&rn
->p
);
2105 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2107 /* bgp deterministic-med */
2109 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
2111 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2112 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2114 bgp_path_info_unset_flag(rn
, pi1
,
2115 BGP_PATH_DMED_SELECTED
);
2117 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2119 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2121 if (BGP_PATH_HOLDDOWN(pi1
))
2123 if (pi1
->peer
!= bgp
->peer_self
)
2124 if (pi1
->peer
->status
!= Established
)
2129 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2130 if (CHECK_FLAG(pi2
->flags
,
2131 BGP_PATH_DMED_CHECK
))
2133 if (BGP_PATH_HOLDDOWN(pi2
))
2135 if (pi2
->peer
!= bgp
->peer_self
2138 PEER_STATUS_NSF_WAIT
))
2139 if (pi2
->peer
->status
2143 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2145 && !aspath_cmp_left_confed(
2150 if (bgp_path_info_cmp(
2151 bgp
, pi2
, new_select
,
2152 &paths_eq
, mpath_cfg
, debug
,
2155 bgp_path_info_unset_flag(
2157 BGP_PATH_DMED_SELECTED
);
2161 bgp_path_info_set_flag(
2162 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2165 bgp_path_info_set_flag(rn
, new_select
,
2166 BGP_PATH_DMED_CHECK
);
2167 bgp_path_info_set_flag(rn
, new_select
,
2168 BGP_PATH_DMED_SELECTED
);
2171 bgp_path_info_path_with_addpath_rx_str(
2172 new_select
, path_buf
);
2173 zlog_debug("%s: %s is the bestpath from AS %u",
2175 aspath_get_first_as(
2176 new_select
->attr
->aspath
));
2181 /* Check old selected route and new selected route. */
2184 for (pi
= bgp_node_get_bgp_path_info(rn
);
2185 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2186 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2189 if (BGP_PATH_HOLDDOWN(pi
)) {
2190 /* reap REMOVED routes, if needs be
2191 * selected route must stay for a while longer though
2193 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2194 && (pi
!= old_select
))
2195 bgp_path_info_reap(rn
, pi
);
2198 zlog_debug("%s: pi %p in holddown", __func__
,
2204 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2205 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2206 if (pi
->peer
->status
!= Established
) {
2210 "%s: pi %p non self peer %s not estab state",
2211 __func__
, pi
, pi
->peer
->host
);
2216 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2217 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2218 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2220 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2224 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2226 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2227 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2232 /* Now that we know which path is the bestpath see if any of the other
2234 * qualify as multipaths
2238 bgp_path_info_path_with_addpath_rx_str(new_select
,
2241 sprintf(path_buf
, "NONE");
2243 "%s: After path selection, newbest is %s oldbest was %s",
2245 old_select
? old_select
->peer
->host
: "NONE");
2248 if (do_mpath
&& new_select
) {
2249 for (pi
= bgp_node_get_bgp_path_info(rn
);
2250 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2253 bgp_path_info_path_with_addpath_rx_str(
2256 if (pi
== new_select
) {
2259 "%s: %s is the bestpath, add to the multipath list",
2261 bgp_mp_list_add(&mp_list
, pi
);
2265 if (BGP_PATH_HOLDDOWN(pi
))
2268 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2269 && !CHECK_FLAG(pi
->peer
->sflags
,
2270 PEER_STATUS_NSF_WAIT
))
2271 if (pi
->peer
->status
!= Established
)
2274 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2277 "%s: %s has the same nexthop as the bestpath, skip it",
2282 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2283 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2289 "%s: %s is equivalent to the bestpath, add to the multipath list",
2291 bgp_mp_list_add(&mp_list
, pi
);
2296 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2298 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2299 bgp_mp_list_clear(&mp_list
);
2301 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2303 result
->old
= old_select
;
2304 result
->new = new_select
;
2310 * A new route/change in bestpath of an existing route. Evaluate the path
2311 * for advertisement to the subgroup.
2313 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2314 struct bgp_path_info
*selected
,
2315 struct bgp_node
*rn
,
2316 uint32_t addpath_tx_id
)
2319 struct peer
*onlypeer
;
2325 afi
= SUBGRP_AFI(subgrp
);
2326 safi
= SUBGRP_SAFI(subgrp
);
2327 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2330 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2331 char buf_prefix
[PREFIX_STRLEN
];
2332 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2333 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2337 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2338 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2339 PEER_STATUS_ORF_WAIT_REFRESH
))
2342 memset(&attr
, 0, sizeof(struct attr
));
2343 /* It's initialized in bgp_announce_check() */
2345 /* Announcement to the subgroup. If the route is filtered withdraw it.
2348 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2349 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2351 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2355 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2357 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2364 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2365 * This is called at the end of route processing.
2367 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2369 struct bgp_path_info
*pi
;
2371 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2372 if (BGP_PATH_HOLDDOWN(pi
))
2374 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2375 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2380 * Has the route changed from the RIB's perspective? This is invoked only
2381 * if the route selection returns the same best route as earlier - to
2382 * determine if we need to update zebra or not.
2384 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2385 struct bgp_path_info
*selected
)
2387 struct bgp_path_info
*mpinfo
;
2389 /* If this is multipath, check all selected paths for any nexthop
2390 * change or attribute change. Some attribute changes (e.g., community)
2391 * aren't of relevance to the RIB, but we'll update zebra to ensure
2392 * we handle the case of BGP nexthop change. This is the behavior
2393 * when the best path has an attribute change anyway.
2395 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2396 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2400 * If this is multipath, check all selected paths for any nexthop change
2402 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2403 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2404 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2405 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2409 /* Nothing has changed from the RIB's perspective. */
2413 struct bgp_process_queue
{
2415 STAILQ_HEAD(, bgp_node
) pqueue
;
2416 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2418 unsigned int queued
;
2422 * old_select = The old best path
2423 * new_select = the new best path
2425 * if (!old_select && new_select)
2426 * We are sending new information on.
2428 * if (old_select && new_select) {
2429 * if (new_select != old_select)
2430 * We have a new best path send a change
2432 * We've received a update with new attributes that needs
2436 * if (old_select && !new_select)
2437 * We have no eligible route that we can announce or the rn
2440 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2441 afi_t afi
, safi_t safi
)
2443 struct bgp_path_info
*new_select
;
2444 struct bgp_path_info
*old_select
;
2445 struct bgp_path_info_pair old_and_new
;
2446 char pfx_buf
[PREFIX2STR_BUFFER
];
2449 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2451 debug
= bgp_debug_bestpath(&rn
->p
);
2453 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2455 "%s: bgp delete in progress, ignoring event, p=%s",
2460 /* Is it end of initial update? (after startup) */
2462 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2463 sizeof(bgp
->update_delay_zebra_resume_time
));
2465 bgp
->main_zebra_update_hold
= 0;
2466 FOREACH_AFI_SAFI (afi
, safi
) {
2467 if (bgp_fibupd_safi(safi
))
2468 bgp_zebra_announce_table(bgp
, afi
, safi
);
2470 bgp
->main_peers_update_hold
= 0;
2472 bgp_start_routeadv(bgp
);
2476 struct prefix
*p
= &rn
->p
;
2478 debug
= bgp_debug_bestpath(&rn
->p
);
2480 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2481 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2482 afi2str(afi
), safi2str(safi
));
2485 /* The best path calculation for the route is deferred if
2486 * BGP_NODE_SELECT_DEFER is set
2488 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2489 if (BGP_DEBUG(update
, UPDATE_OUT
))
2490 zlog_debug("SELECT_DEFER falg set for route %p", rn
);
2494 /* Best path selection. */
2495 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2497 old_select
= old_and_new
.old
;
2498 new_select
= old_and_new
.new;
2500 /* Do we need to allocate or free labels?
2501 * Right now, since we only deal with per-prefix labels, it is not
2502 * necessary to do this upon changes to best path. Exceptions:
2503 * - label index has changed -> recalculate resulting label
2504 * - path_info sub_type changed -> switch to/from implicit-null
2505 * - no valid label (due to removed static label binding) -> get new one
2507 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2510 || bgp_label_index_differs(new_select
, old_select
)
2511 || new_select
->sub_type
!= old_select
->sub_type
2512 || !bgp_is_valid_label(&rn
->local_label
)) {
2513 /* Enforced penultimate hop popping:
2514 * implicit-null for local routes, aggregate
2515 * and redistributed routes
2517 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2518 || new_select
->sub_type
2519 == BGP_ROUTE_AGGREGATE
2520 || new_select
->sub_type
2521 == BGP_ROUTE_REDISTRIBUTE
) {
2524 BGP_NODE_REGISTERED_FOR_LABEL
))
2525 bgp_unregister_for_label(rn
);
2526 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2528 bgp_set_valid_label(&rn
->local_label
);
2530 bgp_register_for_label(rn
, new_select
);
2532 } else if (CHECK_FLAG(rn
->flags
,
2533 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2534 bgp_unregister_for_label(rn
);
2536 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2537 bgp_unregister_for_label(rn
);
2541 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2543 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2544 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2545 old_select
, new_select
);
2548 /* If best route remains the same and this is not due to user-initiated
2549 * clear, see exactly what needs to be done.
2551 if (old_select
&& old_select
== new_select
2552 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2553 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2554 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2555 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2557 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2558 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2560 if (bgp_fibupd_safi(safi
)
2561 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2563 if (new_select
->type
== ZEBRA_ROUTE_BGP
2564 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2565 || new_select
->sub_type
2566 == BGP_ROUTE_IMPORTED
))
2568 bgp_zebra_announce(rn
, p
, old_select
,
2572 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2573 bgp_zebra_clear_route_change_flags(rn
);
2575 /* If there is a change of interest to peers, reannounce the
2577 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2578 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2579 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2581 /* unicast routes must also be annouced to
2582 * labeled-unicast update-groups */
2583 if (safi
== SAFI_UNICAST
)
2584 group_announce_route(bgp
, afi
,
2585 SAFI_LABELED_UNICAST
, rn
,
2588 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2589 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2592 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2596 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2598 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2600 /* bestpath has changed; bump version */
2601 if (old_select
|| new_select
) {
2602 bgp_bump_version(rn
);
2604 if (!bgp
->t_rmap_def_originate_eval
) {
2608 update_group_refresh_default_originate_route_map
,
2609 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2610 &bgp
->t_rmap_def_originate_eval
);
2615 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2618 zlog_debug("%s: setting SELECTED flag", __func__
);
2619 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2620 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2621 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2625 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2626 if (old_select
!= new_select
) {
2628 vnc_import_bgp_exterior_del_route(bgp
, p
,
2630 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2633 vnc_import_bgp_exterior_add_route(bgp
, p
,
2635 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2641 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2643 /* unicast routes must also be annouced to labeled-unicast update-groups
2645 if (safi
== SAFI_UNICAST
)
2646 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2650 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2651 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2652 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2653 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2654 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2655 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2657 /* if this is an evpn imported type-5 prefix,
2658 * we need to withdraw the route first to clear
2659 * the nh neigh and the RMAC entry.
2662 is_route_parent_evpn(old_select
))
2663 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2665 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2667 /* Withdraw the route from the kernel. */
2668 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2669 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2670 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2671 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2673 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2677 /* advertise/withdraw type-5 routes */
2678 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2679 if (advertise_type5_routes(bgp
, afi
) &&
2681 is_route_injectable_into_evpn(new_select
)) {
2683 /* apply the route-map */
2684 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2685 route_map_result_t ret
;
2687 ret
= route_map_apply(
2688 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2689 &rn
->p
, RMAP_BGP
, new_select
);
2690 if (ret
== RMAP_PERMITMATCH
)
2691 bgp_evpn_advertise_type5_route(
2692 bgp
, &rn
->p
, new_select
->attr
,
2695 bgp_evpn_withdraw_type5_route(
2696 bgp
, &rn
->p
, afi
, safi
);
2698 bgp_evpn_advertise_type5_route(bgp
,
2704 } else if (advertise_type5_routes(bgp
, afi
) &&
2706 is_route_injectable_into_evpn(old_select
))
2707 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2710 /* Clear any route change flags. */
2711 bgp_zebra_clear_route_change_flags(rn
);
2713 /* Reap old select bgp_path_info, if it has been removed */
2714 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2715 bgp_path_info_reap(rn
, old_select
);
2717 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2721 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2722 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2724 struct bgp_node
*rn
;
2726 struct afi_safi_info
*thread_info
;
2727 struct listnode
*node
= NULL
, *nnode
= NULL
;
2729 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2730 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2732 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2733 zlog_debug("%s: processing route for %s : cnt %d",
2734 __func__
, get_afi_safi_str(afi
, safi
, false),
2735 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2738 /* Process the route list */
2739 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2741 rn
= listgetdata(node
);
2743 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2746 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2747 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
2748 bgp_process_main_one(bgp
, rn
, afi
, safi
);
2750 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2756 /* Send EOR message when all routes are processed */
2757 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2758 bgp_send_delayed_eor(bgp
);
2759 /* Send route processing complete message to RIB */
2760 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2761 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2765 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2767 thread_info
->afi
= afi
;
2768 thread_info
->safi
= safi
;
2769 thread_info
->bgp
= bgp
;
2771 /* If there are more routes to be processed, start the
2774 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2775 BGP_ROUTE_SELECT_DELAY
,
2776 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2780 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2782 struct bgp_process_queue
*pqnode
= data
;
2783 struct bgp
*bgp
= pqnode
->bgp
;
2784 struct bgp_table
*table
;
2785 struct bgp_node
*rn
;
2788 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2789 bgp_process_main_one(bgp
, NULL
, 0, 0);
2790 /* should always have dedicated wq call */
2791 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2795 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2796 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2797 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2798 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2799 table
= bgp_node_table(rn
);
2800 /* note, new RNs may be added as part of processing */
2801 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2803 bgp_unlock_node(rn
);
2804 bgp_table_unlock(table
);
2810 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2812 struct bgp_process_queue
*pqnode
= data
;
2814 bgp_unlock(pqnode
->bgp
);
2816 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2819 void bgp_process_queue_init(void)
2821 if (!bm
->process_main_queue
)
2822 bm
->process_main_queue
=
2823 work_queue_new(bm
->master
, "process_main_queue");
2825 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2826 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2827 bm
->process_main_queue
->spec
.max_retries
= 0;
2828 bm
->process_main_queue
->spec
.hold
= 50;
2829 /* Use a higher yield value of 50ms for main queue processing */
2830 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2833 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2835 struct bgp_process_queue
*pqnode
;
2837 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2838 sizeof(struct bgp_process_queue
));
2840 /* unlocked in bgp_processq_del */
2841 pqnode
->bgp
= bgp_lock(bgp
);
2842 STAILQ_INIT(&pqnode
->pqueue
);
2847 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2849 #define ARBITRARY_PROCESS_QLEN 10000
2850 struct work_queue
*wq
= bm
->process_main_queue
;
2851 struct bgp_process_queue
*pqnode
;
2852 int pqnode_reuse
= 0;
2854 /* already scheduled for processing? */
2855 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2858 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2861 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2862 if (BGP_DEBUG(update
, UPDATE_OUT
))
2863 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2871 /* Add route nodes to an existing work queue item until reaching the
2872 limit only if is from the same BGP view and it's not an EOIU marker
2874 if (work_queue_item_count(wq
)) {
2875 struct work_queue_item
*item
= work_queue_last_item(wq
);
2876 pqnode
= item
->data
;
2878 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2879 || pqnode
->bgp
!= bgp
2880 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2881 pqnode
= bgp_processq_alloc(bgp
);
2885 pqnode
= bgp_processq_alloc(bgp
);
2886 /* all unlocked in bgp_process_wq */
2887 bgp_table_lock(bgp_node_table(rn
));
2889 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2892 /* can't be enqueued twice */
2893 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2894 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2898 work_queue_add(wq
, pqnode
);
2903 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2905 struct bgp_process_queue
*pqnode
;
2907 if (bm
->process_main_queue
== NULL
)
2910 pqnode
= bgp_processq_alloc(bgp
);
2912 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2913 work_queue_add(bm
->process_main_queue
, pqnode
);
2916 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2920 peer
= THREAD_ARG(thread
);
2921 peer
->t_pmax_restart
= NULL
;
2923 if (bgp_debug_neighbor_events(peer
))
2925 "%s Maximum-prefix restart timer expired, restore peering",
2928 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2929 zlog_debug("%s: %s peer_clear failed",
2930 __PRETTY_FUNCTION__
, peer
->host
);
2935 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2939 iana_safi_t pkt_safi
;
2941 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2944 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2945 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2946 PEER_STATUS_PREFIX_LIMIT
)
2951 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2952 " exceed, limit %" PRIu32
,
2953 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2954 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2955 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2957 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2958 PEER_FLAG_MAX_PREFIX_WARNING
))
2961 /* Convert AFI, SAFI to values for packet. */
2962 pkt_afi
= afi_int2iana(afi
);
2963 pkt_safi
= safi_int2iana(safi
);
2967 ndata
[0] = (pkt_afi
>> 8);
2969 ndata
[2] = pkt_safi
;
2970 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2971 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2972 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2973 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2975 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2976 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2977 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2981 /* Dynamic peers will just close their connection. */
2982 if (peer_dynamic_neighbor(peer
))
2985 /* restart timer start */
2986 if (peer
->pmax_restart
[afi
][safi
]) {
2987 peer
->v_pmax_restart
=
2988 peer
->pmax_restart
[afi
][safi
] * 60;
2990 if (bgp_debug_neighbor_events(peer
))
2992 "%s Maximum-prefix restart timer started for %d secs",
2993 peer
->host
, peer
->v_pmax_restart
);
2995 BGP_TIMER_ON(peer
->t_pmax_restart
,
2996 bgp_maximum_prefix_restart_timer
,
2997 peer
->v_pmax_restart
);
3002 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3003 PEER_STATUS_PREFIX_LIMIT
);
3005 if (peer
->pcount
[afi
][safi
]
3006 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3007 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3008 PEER_STATUS_PREFIX_THRESHOLD
)
3013 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3015 get_afi_safi_str(afi
, safi
, false), peer
->host
,
3016 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
3017 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3018 PEER_STATUS_PREFIX_THRESHOLD
);
3020 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3021 PEER_STATUS_PREFIX_THRESHOLD
);
3025 /* Unconditionally remove the route from the RIB, without taking
3026 * damping into consideration (eg, because the session went down)
3028 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3029 struct peer
*peer
, afi_t afi
, safi_t safi
)
3032 struct bgp
*bgp
= NULL
;
3033 bool delete_route
= false;
3035 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
3037 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3038 bgp_path_info_delete(rn
, pi
); /* keep historical info */
3040 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3043 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3044 delete_route
= true;
3046 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
;
3052 if ((rn
->rt_node
) &&
3053 (bgp
->gr_info
[afi
][safi
]
3056 bgp
->gr_info
[afi
][safi
]
3065 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
3066 bgp_process(peer
->bgp
, rn
, afi
, safi
);
3069 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3070 struct peer
*peer
, afi_t afi
, safi_t safi
,
3071 struct prefix_rd
*prd
)
3073 /* apply dampening, if result is suppressed, we'll be retaining
3074 * the bgp_path_info in the RIB for historical reference.
3076 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3077 && peer
->sort
== BGP_PEER_EBGP
)
3078 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
3079 == BGP_DAMP_SUPPRESSED
) {
3080 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
3086 if (safi
== SAFI_MPLS_VPN
) {
3087 struct bgp_node
*prn
= NULL
;
3088 struct bgp_table
*table
= NULL
;
3090 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3091 (struct prefix
*)prd
);
3092 if (bgp_node_has_bgp_path_info_data(prn
)) {
3093 table
= bgp_node_get_bgp_table_info(prn
);
3095 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3096 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
3098 bgp_unlock_node(prn
);
3100 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3101 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3103 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
3104 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
3110 /* If this is an EVPN route, process for un-import. */
3111 if (safi
== SAFI_EVPN
)
3112 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
3114 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3117 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3118 struct peer
*peer
, struct attr
*attr
,
3119 struct bgp_node
*rn
)
3121 struct bgp_path_info
*new;
3123 /* Make new BGP info. */
3124 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3126 new->instance
= instance
;
3127 new->sub_type
= sub_type
;
3130 new->uptime
= bgp_clock();
3135 static void overlay_index_update(struct attr
*attr
,
3136 struct eth_segment_id
*eth_s_id
,
3137 union gw_addr
*gw_ip
)
3142 if (eth_s_id
== NULL
) {
3143 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
3144 sizeof(struct eth_segment_id
));
3146 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
3147 sizeof(struct eth_segment_id
));
3149 if (gw_ip
== NULL
) {
3150 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3152 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3153 sizeof(union gw_addr
));
3157 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3158 struct eth_segment_id
*eth_s_id
,
3159 union gw_addr
*gw_ip
)
3161 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
3162 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3164 struct eth_segment_id esi
;
3168 if (afi
!= AFI_L2VPN
)
3171 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
3172 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3174 if (gw_ip
== NULL
) {
3175 memset(&temp
, 0, sizeof(temp
));
3176 path_gw_ip_remote
= &temp
.ip
;
3178 path_gw_ip_remote
= gw_ip
;
3180 if (eth_s_id
== NULL
) {
3181 memset(&temp
, 0, sizeof(temp
));
3182 path_eth_s_id_remote
= &temp
.esi
;
3184 path_eth_s_id_remote
= eth_s_id
;
3186 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
3189 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
3190 sizeof(struct eth_segment_id
));
3193 /* Check if received nexthop is valid or not. */
3194 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3195 uint8_t type
, uint8_t stype
,
3196 struct attr
*attr
, struct bgp_node
*rn
)
3200 /* Only validated for unicast and multicast currently. */
3201 /* Also valid for EVPN where the nexthop is an IP address. */
3202 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3205 /* If NEXT_HOP is present, validate it. */
3206 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3207 if (attr
->nexthop
.s_addr
== 0
3208 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3209 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3214 /* If MP_NEXTHOP is present, validate it. */
3215 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3216 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3217 * it is not an IPv6 link-local address.
3219 if (attr
->mp_nexthop_len
) {
3220 switch (attr
->mp_nexthop_len
) {
3221 case BGP_ATTR_NHLEN_IPV4
:
3222 case BGP_ATTR_NHLEN_VPNV4
:
3223 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3224 || IPV4_CLASS_DE(ntohl(
3225 attr
->mp_nexthop_global_in
.s_addr
))
3226 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3230 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3231 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3232 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3233 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3234 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3235 || IN6_IS_ADDR_MULTICAST(
3236 &attr
->mp_nexthop_global
)
3237 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3250 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3251 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3252 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3253 uint32_t num_labels
, int soft_reconfig
,
3254 struct bgp_route_evpn
*evpn
)
3257 int aspath_loop_count
= 0;
3258 struct bgp_node
*rn
;
3260 struct attr new_attr
;
3261 struct attr
*attr_new
;
3262 struct bgp_path_info
*pi
;
3263 struct bgp_path_info
*new;
3264 struct bgp_path_info_extra
*extra
;
3266 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3268 int do_loop_check
= 1;
3269 int has_valid_label
= 0;
3271 uint8_t pi_type
= 0;
3272 uint8_t pi_sub_type
= 0;
3275 int vnc_implicit_withdraw
= 0;
3279 memset(&new_attr
, 0, sizeof(struct attr
));
3280 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3281 new_attr
.label
= MPLS_INVALID_LABEL
;
3284 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3285 /* TODO: Check to see if we can get rid of "is_valid_label" */
3286 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3287 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3289 has_valid_label
= bgp_is_valid_label(label
);
3291 /* When peer's soft reconfiguration enabled. Record input packet in
3294 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3295 && peer
!= bgp
->peer_self
)
3296 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3298 /* Check previously received route. */
3299 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3300 if (pi
->peer
== peer
&& pi
->type
== type
3301 && pi
->sub_type
== sub_type
3302 && pi
->addpath_rx_id
== addpath_id
)
3305 /* AS path local-as loop check. */
3306 if (peer
->change_local_as
) {
3307 if (peer
->allowas_in
[afi
][safi
])
3308 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3309 else if (!CHECK_FLAG(peer
->flags
,
3310 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3311 aspath_loop_count
= 1;
3313 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3314 > aspath_loop_count
) {
3315 peer
->stat_pfx_aspath_loop
++;
3316 reason
= "as-path contains our own AS;";
3321 /* If the peer is configured for "allowas-in origin" and the last ASN in
3323 * as-path is our ASN then we do not need to call aspath_loop_check
3325 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3326 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3329 /* AS path loop check. */
3330 if (do_loop_check
) {
3331 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3332 > peer
->allowas_in
[afi
][safi
]
3333 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3334 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3335 > peer
->allowas_in
[afi
][safi
])) {
3336 peer
->stat_pfx_aspath_loop
++;
3337 reason
= "as-path contains our own AS;";
3342 /* Route reflector originator ID check. */
3343 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3344 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3345 peer
->stat_pfx_originator_loop
++;
3346 reason
= "originator is us;";
3350 /* Route reflector cluster ID check. */
3351 if (bgp_cluster_filter(peer
, attr
)) {
3352 peer
->stat_pfx_cluster_loop
++;
3353 reason
= "reflected from the same cluster;";
3357 /* Apply incoming filter. */
3358 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3359 peer
->stat_pfx_filter
++;
3364 /* RFC 8212 to prevent route leaks.
3365 * This specification intends to improve this situation by requiring the
3366 * explicit configuration of both BGP Import and Export Policies for any
3367 * External BGP (EBGP) session such as customers, peers, or
3368 * confederation boundaries for all enabled address families. Through
3369 * codification of the aforementioned requirement, operators will
3370 * benefit from consistent behavior across different BGP
3373 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3374 if (!bgp_inbound_policy_exists(peer
,
3375 &peer
->filter
[afi
][safi
])) {
3376 reason
= "inbound policy missing";
3380 /* draft-ietf-idr-deprecate-as-set-confed-set
3381 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3382 * Eventually, This document (if approved) updates RFC 4271
3383 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3384 * and obsoletes RFC 6472.
3386 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3387 if (aspath_check_as_sets(attr
->aspath
)) {
3389 "as-path contains AS_SET or AS_CONFED_SET type;";
3395 /* Apply incoming route-map.
3396 * NB: new_attr may now contain newly allocated values from route-map
3398 * commands, so we need bgp_attr_flush in the error paths, until we
3400 * the attr (which takes over the memory references) */
3401 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3402 label
, num_labels
, rn
) == RMAP_DENY
) {
3403 peer
->stat_pfx_filter
++;
3404 reason
= "route-map;";
3405 bgp_attr_flush(&new_attr
);
3409 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3410 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3411 /* remove from RIB previous entry */
3412 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3415 if (peer
->sort
== BGP_PEER_EBGP
) {
3417 /* If we receive the graceful-shutdown community from an eBGP
3418 * peer we must lower local-preference */
3419 if (new_attr
.community
3420 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3421 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3422 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3424 /* If graceful-shutdown is configured then add the GSHUT
3425 * community to all paths received from eBGP peers */
3426 } else if (bgp_flag_check(peer
->bgp
,
3427 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3428 bgp_attr_add_gshut_community(&new_attr
);
3434 pi_sub_type
= pi
->sub_type
;
3437 /* next hop check. */
3438 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3439 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3440 pi_sub_type
, &new_attr
, rn
)) {
3441 peer
->stat_pfx_nh_invalid
++;
3442 reason
= "martian or self next-hop;";
3443 bgp_attr_flush(&new_attr
);
3447 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3448 peer
->stat_pfx_nh_invalid
++;
3449 reason
= "self mac;";
3453 attr_new
= bgp_attr_intern(&new_attr
);
3455 /* If the update is implicit withdraw. */
3457 pi
->uptime
= bgp_clock();
3458 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3460 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3462 /* Same attribute comes in. */
3463 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3464 && attrhash_cmp(pi
->attr
, attr_new
)
3465 && (!has_valid_label
3466 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3467 num_labels
* sizeof(mpls_label_t
))
3469 && (overlay_index_equal(
3470 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3471 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3472 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3473 BGP_CONFIG_DAMPENING
)
3474 && peer
->sort
== BGP_PEER_EBGP
3475 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3476 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3477 bgp_debug_rdpfxpath2str(
3478 afi
, safi
, prd
, p
, label
,
3479 num_labels
, addpath_id
? 1 : 0,
3480 addpath_id
, pfx_buf
,
3482 zlog_debug("%s rcvd %s", peer
->host
,
3486 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3487 != BGP_DAMP_SUPPRESSED
) {
3488 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3490 bgp_process(bgp
, rn
, afi
, safi
);
3492 } else /* Duplicate - odd */
3494 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3495 if (!peer
->rcvd_attr_printed
) {
3497 "%s rcvd UPDATE w/ attr: %s",
3499 peer
->rcvd_attr_str
);
3500 peer
->rcvd_attr_printed
= 1;
3503 bgp_debug_rdpfxpath2str(
3504 afi
, safi
, prd
, p
, label
,
3505 num_labels
, addpath_id
? 1 : 0,
3506 addpath_id
, pfx_buf
,
3509 "%s rcvd %s...duplicate ignored",
3510 peer
->host
, pfx_buf
);
3513 /* graceful restart STALE flag unset. */
3514 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3515 bgp_path_info_unset_flag(
3516 rn
, pi
, BGP_PATH_STALE
);
3517 bgp_node_set_defer_flag(rn
, false);
3518 bgp_process(bgp
, rn
, afi
, safi
);
3522 bgp_unlock_node(rn
);
3523 bgp_attr_unintern(&attr_new
);
3528 /* Withdraw/Announce before we fully processed the withdraw */
3529 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3530 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3531 bgp_debug_rdpfxpath2str(
3532 afi
, safi
, prd
, p
, label
, num_labels
,
3533 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3536 "%s rcvd %s, flapped quicker than processing",
3537 peer
->host
, pfx_buf
);
3540 bgp_path_info_restore(rn
, pi
);
3543 /* Received Logging. */
3544 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3545 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3546 num_labels
, addpath_id
? 1 : 0,
3547 addpath_id
, pfx_buf
,
3549 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3552 /* graceful restart STALE flag unset. */
3553 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3554 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3555 bgp_node_set_defer_flag(rn
, false);
3558 /* The attribute is changed. */
3559 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3561 /* implicit withdraw, decrement aggregate and pcount here.
3562 * only if update is accepted, they'll increment below.
3564 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3566 /* Update bgp route dampening information. */
3567 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3568 && peer
->sort
== BGP_PEER_EBGP
) {
3569 /* This is implicit withdraw so we should update
3572 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3573 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3576 if (safi
== SAFI_MPLS_VPN
) {
3577 struct bgp_node
*prn
= NULL
;
3578 struct bgp_table
*table
= NULL
;
3580 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3581 (struct prefix
*)prd
);
3582 if (bgp_node_has_bgp_path_info_data(prn
)) {
3583 table
= bgp_node_get_bgp_table_info(prn
);
3585 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3586 bgp
, prd
, table
, p
, pi
);
3588 bgp_unlock_node(prn
);
3590 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3591 && (safi
== SAFI_UNICAST
)) {
3592 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3594 * Implicit withdraw case.
3596 ++vnc_implicit_withdraw
;
3597 vnc_import_bgp_del_route(bgp
, p
, pi
);
3598 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3603 /* Special handling for EVPN update of an existing route. If the
3604 * extended community attribute has changed, we need to
3606 * the route using its existing extended community. It will be
3607 * subsequently processed for import with the new extended
3610 if (safi
== SAFI_EVPN
&& !same_attr
) {
3612 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3614 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3617 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3618 attr_new
->ecommunity
);
3620 if (bgp_debug_update(peer
, p
, NULL
, 1))
3622 "Change in EXT-COMM, existing %s new %s",
3624 pi
->attr
->ecommunity
),
3626 attr_new
->ecommunity
));
3627 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3633 /* Update to new attribute. */
3634 bgp_attr_unintern(&pi
->attr
);
3635 pi
->attr
= attr_new
;
3637 /* Update MPLS label */
3638 if (has_valid_label
) {
3639 extra
= bgp_path_info_extra_get(pi
);
3640 if (extra
->label
!= label
) {
3641 memcpy(&extra
->label
, label
,
3642 num_labels
* sizeof(mpls_label_t
));
3643 extra
->num_labels
= num_labels
;
3645 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3646 bgp_set_valid_label(&extra
->label
[0]);
3649 /* Update SRv6 SID */
3650 if (attr
->srv6_l3vpn
) {
3651 extra
= bgp_path_info_extra_get(pi
);
3652 if (sid_diff(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
)) {
3653 sid_copy(&extra
->sid
[0],
3654 &attr
->srv6_l3vpn
->sid
);
3655 extra
->num_sids
= 1;
3657 } else if (attr
->srv6_vpn
) {
3658 extra
= bgp_path_info_extra_get(pi
);
3659 if (sid_diff(&extra
->sid
[0], &attr
->srv6_vpn
->sid
)) {
3660 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3661 extra
->num_sids
= 1;
3666 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3667 && (safi
== SAFI_UNICAST
)) {
3668 if (vnc_implicit_withdraw
) {
3670 * Add back the route with its new attributes
3672 * The route is still selected, until the route
3674 * queued by bgp_process actually runs. We have
3676 * update to the VNC side immediately to avoid
3678 * configuration changes (e.g., route-map
3680 * trigger re-importation of the entire RIB.
3682 vnc_import_bgp_add_route(bgp
, p
, pi
);
3683 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3687 /* Update Overlay Index */
3688 if (afi
== AFI_L2VPN
) {
3689 overlay_index_update(
3690 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3691 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3694 /* Update bgp route dampening information. */
3695 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3696 && peer
->sort
== BGP_PEER_EBGP
) {
3697 /* Now we do normal update dampening. */
3698 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3699 if (ret
== BGP_DAMP_SUPPRESSED
) {
3700 bgp_unlock_node(rn
);
3705 /* Nexthop reachability check - for unicast and
3706 * labeled-unicast.. */
3707 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3708 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3709 || (safi
== SAFI_EVPN
&&
3710 bgp_evpn_is_prefix_nht_supported(p
))) {
3711 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3712 && peer
->ttl
== BGP_DEFAULT_TTL
3713 && !CHECK_FLAG(peer
->flags
,
3714 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3716 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3721 struct bgp
*bgp_nexthop
= bgp
;
3723 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3724 bgp_nexthop
= pi
->extra
->bgp_orig
;
3726 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3728 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3729 pi
, NULL
, connected
)
3730 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3731 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3733 if (BGP_DEBUG(nht
, NHT
)) {
3734 char buf1
[INET6_ADDRSTRLEN
];
3736 (const void *)&attr_new
3738 buf1
, INET6_ADDRSTRLEN
);
3739 zlog_debug("%s(%s): NH unresolved",
3740 __FUNCTION__
, buf1
);
3742 bgp_path_info_unset_flag(rn
, pi
,
3746 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3749 if (safi
== SAFI_MPLS_VPN
) {
3750 struct bgp_node
*prn
= NULL
;
3751 struct bgp_table
*table
= NULL
;
3753 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3754 (struct prefix
*)prd
);
3755 if (bgp_node_has_bgp_path_info_data(prn
)) {
3756 table
= bgp_node_get_bgp_table_info(prn
);
3758 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3759 bgp
, prd
, table
, p
, pi
);
3761 bgp_unlock_node(prn
);
3765 /* If this is an EVPN route and some attribute has changed,
3767 * route for import. If the extended community has changed, we
3769 * have done the un-import earlier and the import would result
3771 * route getting injected into appropriate L2 VNIs. If it is
3773 * some other attribute change, the import will result in
3775 * the attributes for the route in the VNI(s).
3777 if (safi
== SAFI_EVPN
&& !same_attr
&&
3778 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3779 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3781 /* Process change. */
3782 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3784 bgp_process(bgp
, rn
, afi
, safi
);
3785 bgp_unlock_node(rn
);
3787 if (SAFI_UNICAST
== safi
3788 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3789 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3791 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3793 if ((SAFI_MPLS_VPN
== safi
)
3794 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3796 vpn_leak_to_vrf_update(bgp
, pi
);
3800 if (SAFI_MPLS_VPN
== safi
) {
3801 mpls_label_t label_decoded
= decode_label(label
);
3803 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3804 type
, sub_type
, &label_decoded
);
3806 if (SAFI_ENCAP
== safi
) {
3807 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3808 type
, sub_type
, NULL
);
3813 } // End of implicit withdraw
3815 /* Received Logging. */
3816 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3817 if (!peer
->rcvd_attr_printed
) {
3818 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3819 peer
->rcvd_attr_str
);
3820 peer
->rcvd_attr_printed
= 1;
3823 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3824 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3826 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3829 /* Make new BGP info. */
3830 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3832 /* Update MPLS label */
3833 if (has_valid_label
) {
3834 extra
= bgp_path_info_extra_get(new);
3835 if (extra
->label
!= label
) {
3836 memcpy(&extra
->label
, label
,
3837 num_labels
* sizeof(mpls_label_t
));
3838 extra
->num_labels
= num_labels
;
3840 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3841 bgp_set_valid_label(&extra
->label
[0]);
3844 /* Update SRv6 SID */
3845 if (safi
== SAFI_MPLS_VPN
) {
3846 extra
= bgp_path_info_extra_get(new);
3847 if (attr
->srv6_l3vpn
) {
3848 sid_copy(&extra
->sid
[0], &attr
->srv6_l3vpn
->sid
);
3849 extra
->num_sids
= 1;
3850 } else if (attr
->srv6_vpn
) {
3851 sid_copy(&extra
->sid
[0], &attr
->srv6_vpn
->sid
);
3852 extra
->num_sids
= 1;
3856 /* Update Overlay Index */
3857 if (afi
== AFI_L2VPN
) {
3858 overlay_index_update(new->attr
,
3859 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3860 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3862 /* Nexthop reachability check. */
3863 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3864 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3865 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3866 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3867 && peer
->ttl
== BGP_DEFAULT_TTL
3868 && !CHECK_FLAG(peer
->flags
,
3869 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3870 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3875 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3877 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3879 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3880 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3882 if (BGP_DEBUG(nht
, NHT
)) {
3883 char buf1
[INET6_ADDRSTRLEN
];
3885 (const void *)&attr_new
->nexthop
,
3886 buf1
, INET6_ADDRSTRLEN
);
3887 zlog_debug("%s(%s): NH unresolved",
3888 __FUNCTION__
, buf1
);
3890 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3893 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3896 new->addpath_rx_id
= addpath_id
;
3898 /* Increment prefix */
3899 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3901 /* Register new BGP information. */
3902 bgp_path_info_add(rn
, new);
3904 /* route_node_get lock */
3905 bgp_unlock_node(rn
);
3908 if (safi
== SAFI_MPLS_VPN
) {
3909 struct bgp_node
*prn
= NULL
;
3910 struct bgp_table
*table
= NULL
;
3912 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3913 if (bgp_node_has_bgp_path_info_data(prn
)) {
3914 table
= bgp_node_get_bgp_table_info(prn
);
3916 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3917 bgp
, prd
, table
, p
, new);
3919 bgp_unlock_node(prn
);
3923 /* If maximum prefix count is configured and current prefix
3925 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3928 /* If this is an EVPN route, process for import. */
3929 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3930 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3932 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3934 /* Process change. */
3935 bgp_process(bgp
, rn
, afi
, safi
);
3937 if (SAFI_UNICAST
== safi
3938 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3939 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3940 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3942 if ((SAFI_MPLS_VPN
== safi
)
3943 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3945 vpn_leak_to_vrf_update(bgp
, new);
3948 if (SAFI_MPLS_VPN
== safi
) {
3949 mpls_label_t label_decoded
= decode_label(label
);
3951 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3952 sub_type
, &label_decoded
);
3954 if (SAFI_ENCAP
== safi
) {
3955 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3962 /* This BGP update is filtered. Log the reason then update BGP
3965 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3967 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3968 if (!peer
->rcvd_attr_printed
) {
3969 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3970 peer
->rcvd_attr_str
);
3971 peer
->rcvd_attr_printed
= 1;
3974 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3975 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3977 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3978 peer
->host
, pfx_buf
, reason
);
3982 /* If this is an EVPN route, un-import it as it is now filtered.
3984 if (safi
== SAFI_EVPN
)
3985 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3987 if (SAFI_UNICAST
== safi
3988 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3989 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3991 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3993 if ((SAFI_MPLS_VPN
== safi
)
3994 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3996 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3999 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4002 bgp_unlock_node(rn
);
4006 * Filtered update is treated as an implicit withdrawal (see
4008 * a few lines above)
4010 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4011 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4019 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
4020 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4021 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4022 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4025 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4026 struct bgp_node
*rn
;
4027 struct bgp_path_info
*pi
;
4030 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4031 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4039 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4041 /* If peer is soft reconfiguration enabled. Record input packet for
4042 * further calculation.
4044 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4045 * routes that are filtered. This tanks out Quagga RS pretty badly due
4047 * the iteration over all RS clients.
4048 * Since we need to remove the entry from adj_in anyway, do that first
4050 * if there was no entry, we don't need to do anything more.
4052 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4053 && peer
!= bgp
->peer_self
)
4054 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
4055 peer
->stat_pfx_dup_withdraw
++;
4057 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4058 bgp_debug_rdpfxpath2str(
4059 afi
, safi
, prd
, p
, label
, num_labels
,
4060 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4063 "%s withdrawing route %s not in adj-in",
4064 peer
->host
, pfx_buf
);
4066 bgp_unlock_node(rn
);
4070 /* Lookup withdrawn route. */
4071 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4072 if (pi
->peer
== peer
&& pi
->type
== type
4073 && pi
->sub_type
== sub_type
4074 && pi
->addpath_rx_id
== addpath_id
)
4078 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4079 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4080 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4082 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4086 /* Withdraw specified route from routing table. */
4087 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4088 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
4089 if (SAFI_UNICAST
== safi
4090 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4091 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4092 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4094 if ((SAFI_MPLS_VPN
== safi
)
4095 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4097 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4099 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4100 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4101 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4103 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4106 /* Unlock bgp_node_get() lock. */
4107 bgp_unlock_node(rn
);
4112 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4115 struct update_subgroup
*subgrp
;
4116 subgrp
= peer_subgroup(peer
, afi
, safi
);
4117 subgroup_default_originate(subgrp
, withdraw
);
4122 * bgp_stop_announce_route_timer
4124 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4126 if (!paf
->t_announce_route
)
4129 THREAD_TIMER_OFF(paf
->t_announce_route
);
4133 * bgp_announce_route_timer_expired
4135 * Callback that is invoked when the route announcement timer for a
4138 static int bgp_announce_route_timer_expired(struct thread
*t
)
4140 struct peer_af
*paf
;
4143 paf
= THREAD_ARG(t
);
4146 if (peer
->status
!= Established
)
4149 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4152 peer_af_announce_route(paf
, 1);
4157 * bgp_announce_route
4159 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4161 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4163 struct peer_af
*paf
;
4164 struct update_subgroup
*subgrp
;
4166 paf
= peer_af_find(peer
, afi
, safi
);
4169 subgrp
= PAF_SUBGRP(paf
);
4172 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4173 * or a refresh has already been triggered.
4175 if (!subgrp
|| paf
->t_announce_route
)
4179 * Start a timer to stagger/delay the announce. This serves
4180 * two purposes - announcement can potentially be combined for
4181 * multiple peers and the announcement doesn't happen in the
4184 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4185 (subgrp
->peer_count
== 1)
4186 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4187 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4188 &paf
->t_announce_route
);
4192 * Announce routes from all AF tables to a peer.
4194 * This should ONLY be called when there is a need to refresh the
4195 * routes to the peer based on a policy change for this peer alone
4196 * or a route refresh request received from the peer.
4197 * The operation will result in splitting the peer from its existing
4198 * subgroups and putting it in new subgroups.
4200 void bgp_announce_route_all(struct peer
*peer
)
4205 FOREACH_AFI_SAFI (afi
, safi
)
4206 bgp_announce_route(peer
, afi
, safi
);
4209 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4210 struct bgp_table
*table
,
4211 struct prefix_rd
*prd
)
4214 struct bgp_node
*rn
;
4215 struct bgp_adj_in
*ain
;
4218 table
= peer
->bgp
->rib
[afi
][safi
];
4220 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4221 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
4222 if (ain
->peer
!= peer
)
4225 struct bgp_path_info
*pi
;
4226 uint32_t num_labels
= 0;
4227 mpls_label_t
*label_pnt
= NULL
;
4228 struct bgp_route_evpn evpn
;
4230 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4232 if (pi
->peer
== peer
)
4235 if (pi
&& pi
->extra
)
4236 num_labels
= pi
->extra
->num_labels
;
4238 label_pnt
= &pi
->extra
->label
[0];
4240 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4243 memset(&evpn
, 0, sizeof(evpn
));
4245 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
4246 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4247 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4248 num_labels
, 1, &evpn
);
4251 bgp_unlock_node(rn
);
4257 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4259 struct bgp_node
*rn
;
4260 struct bgp_table
*table
;
4262 if (peer
->status
!= Established
)
4265 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4266 && (safi
!= SAFI_EVPN
))
4267 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4269 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4270 rn
= bgp_route_next(rn
)) {
4271 table
= bgp_node_get_bgp_table_info(rn
);
4272 if (table
!= NULL
) {
4273 struct prefix_rd prd
;
4275 prd
.family
= AF_UNSPEC
;
4277 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4279 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4286 struct bgp_clear_node_queue
{
4287 struct bgp_node
*rn
;
4290 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4292 struct bgp_clear_node_queue
*cnq
= data
;
4293 struct bgp_node
*rn
= cnq
->rn
;
4294 struct peer
*peer
= wq
->spec
.data
;
4295 struct bgp_path_info
*pi
;
4297 afi_t afi
= bgp_node_table(rn
)->afi
;
4298 safi_t safi
= bgp_node_table(rn
)->safi
;
4303 /* It is possible that we have multiple paths for a prefix from a peer
4304 * if that peer is using AddPath.
4306 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4307 if (pi
->peer
!= peer
)
4310 /* graceful restart STALE flag set. */
4311 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4312 && peer
->nsf
[afi
][safi
]
4313 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4314 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4315 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4317 /* If this is an EVPN route, process for
4319 if (safi
== SAFI_EVPN
)
4320 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4322 /* Handle withdraw for VRF route-leaking and L3VPN */
4323 if (SAFI_UNICAST
== safi
4324 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4325 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4326 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4329 if (SAFI_MPLS_VPN
== safi
&&
4330 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4331 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4334 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4340 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4342 struct bgp_clear_node_queue
*cnq
= data
;
4343 struct bgp_node
*rn
= cnq
->rn
;
4344 struct bgp_table
*table
= bgp_node_table(rn
);
4346 bgp_unlock_node(rn
);
4347 bgp_table_unlock(table
);
4348 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4351 static void bgp_clear_node_complete(struct work_queue
*wq
)
4353 struct peer
*peer
= wq
->spec
.data
;
4355 /* Tickle FSM to start moving again */
4356 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4358 peer_unlock(peer
); /* bgp_clear_route */
4361 static void bgp_clear_node_queue_init(struct peer
*peer
)
4363 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4365 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4366 #undef CLEAR_QUEUE_NAME_LEN
4368 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4369 peer
->clear_node_queue
->spec
.hold
= 10;
4370 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4371 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4372 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4373 peer
->clear_node_queue
->spec
.max_retries
= 0;
4375 /* we only 'lock' this peer reference when the queue is actually active
4377 peer
->clear_node_queue
->spec
.data
= peer
;
4380 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4381 struct bgp_table
*table
)
4383 struct bgp_node
*rn
;
4384 int force
= bm
->process_main_queue
? 0 : 1;
4387 table
= peer
->bgp
->rib
[afi
][safi
];
4389 /* If still no table => afi/safi isn't configured at all or smth. */
4393 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4394 struct bgp_path_info
*pi
, *next
;
4395 struct bgp_adj_in
*ain
;
4396 struct bgp_adj_in
*ain_next
;
4398 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4399 * queued for every clearing peer, regardless of whether it is
4400 * relevant to the peer at hand.
4402 * Overview: There are 3 different indices which need to be
4403 * scrubbed, potentially, when a peer is removed:
4405 * 1 peer's routes visible via the RIB (ie accepted routes)
4406 * 2 peer's routes visible by the (optional) peer's adj-in index
4407 * 3 other routes visible by the peer's adj-out index
4409 * 3 there is no hurry in scrubbing, once the struct peer is
4410 * removed from bgp->peer, we could just GC such deleted peer's
4411 * adj-outs at our leisure.
4413 * 1 and 2 must be 'scrubbed' in some way, at least made
4414 * invisible via RIB index before peer session is allowed to be
4415 * brought back up. So one needs to know when such a 'search' is
4420 * - there'd be a single global queue or a single RIB walker
4421 * - rather than tracking which route_nodes still need to be
4422 * examined on a peer basis, we'd track which peers still
4425 * Given that our per-peer prefix-counts now should be reliable,
4426 * this may actually be achievable. It doesn't seem to be a huge
4427 * problem at this time,
4429 * It is possible that we have multiple paths for a prefix from
4431 * if that peer is using AddPath.
4435 ain_next
= ain
->next
;
4437 if (ain
->peer
== peer
) {
4438 bgp_adj_in_remove(rn
, ain
);
4439 bgp_unlock_node(rn
);
4445 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4447 if (pi
->peer
!= peer
)
4451 bgp_path_info_reap(rn
, pi
);
4453 struct bgp_clear_node_queue
*cnq
;
4455 /* both unlocked in bgp_clear_node_queue_del */
4456 bgp_table_lock(bgp_node_table(rn
));
4459 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4460 sizeof(struct bgp_clear_node_queue
));
4462 work_queue_add(peer
->clear_node_queue
, cnq
);
4470 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4472 struct bgp_node
*rn
;
4473 struct bgp_table
*table
;
4475 if (peer
->clear_node_queue
== NULL
)
4476 bgp_clear_node_queue_init(peer
);
4478 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4479 * Idle until it receives a Clearing_Completed event. This protects
4480 * against peers which flap faster than we can we clear, which could
4483 * a) race with routes from the new session being installed before
4484 * clear_route_node visits the node (to delete the route of that
4486 * b) resource exhaustion, clear_route_node likely leads to an entry
4487 * on the process_main queue. Fast-flapping could cause that queue
4491 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4492 * the unlock will happen upon work-queue completion; other wise, the
4493 * unlock happens at the end of this function.
4495 if (!peer
->clear_node_queue
->thread
)
4498 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4499 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4501 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4502 rn
= bgp_route_next(rn
)) {
4503 table
= bgp_node_get_bgp_table_info(rn
);
4507 bgp_clear_route_table(peer
, afi
, safi
, table
);
4510 /* unlock if no nodes got added to the clear-node-queue. */
4511 if (!peer
->clear_node_queue
->thread
)
4515 void bgp_clear_route_all(struct peer
*peer
)
4520 FOREACH_AFI_SAFI (afi
, safi
)
4521 bgp_clear_route(peer
, afi
, safi
);
4524 rfapiProcessPeerDown(peer
);
4528 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4530 struct bgp_table
*table
;
4531 struct bgp_node
*rn
;
4532 struct bgp_adj_in
*ain
;
4533 struct bgp_adj_in
*ain_next
;
4535 table
= peer
->bgp
->rib
[afi
][safi
];
4537 /* It is possible that we have multiple paths for a prefix from a peer
4538 * if that peer is using AddPath.
4540 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4544 ain_next
= ain
->next
;
4546 if (ain
->peer
== peer
) {
4547 bgp_adj_in_remove(rn
, ain
);
4548 bgp_unlock_node(rn
);
4556 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4558 struct bgp_node
*rn
;
4559 struct bgp_path_info
*pi
;
4560 struct bgp_table
*table
;
4562 if (safi
== SAFI_MPLS_VPN
) {
4563 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4564 rn
= bgp_route_next(rn
)) {
4565 struct bgp_node
*rm
;
4567 /* look for neighbor in tables */
4568 table
= bgp_node_get_bgp_table_info(rn
);
4572 for (rm
= bgp_table_top(table
); rm
;
4573 rm
= bgp_route_next(rm
))
4574 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4576 if (pi
->peer
!= peer
)
4578 if (!CHECK_FLAG(pi
->flags
,
4582 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4587 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4588 rn
= bgp_route_next(rn
))
4589 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4591 if (pi
->peer
!= peer
)
4593 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4595 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4601 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4603 if (peer
->sort
== BGP_PEER_IBGP
)
4606 if (peer
->sort
== BGP_PEER_EBGP
4607 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4608 || FILTER_LIST_OUT_NAME(filter
)
4609 || DISTRIBUTE_OUT_NAME(filter
)))
4614 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4616 if (peer
->sort
== BGP_PEER_IBGP
)
4619 if (peer
->sort
== BGP_PEER_EBGP
4620 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4621 || FILTER_LIST_IN_NAME(filter
)
4622 || DISTRIBUTE_IN_NAME(filter
)))
4627 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4630 struct bgp_node
*rn
;
4631 struct bgp_path_info
*pi
;
4632 struct bgp_path_info
*next
;
4634 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4635 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4638 /* Unimport EVPN routes from VRFs */
4639 if (safi
== SAFI_EVPN
)
4640 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4644 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4645 && pi
->type
== ZEBRA_ROUTE_BGP
4646 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4647 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4648 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4650 if (bgp_fibupd_safi(safi
))
4651 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4653 bgp_path_info_reap(rn
, pi
);
4658 /* Delete all kernel routes. */
4659 void bgp_cleanup_routes(struct bgp
*bgp
)
4662 struct bgp_node
*rn
;
4663 struct bgp_table
*table
;
4665 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4666 if (afi
== AFI_L2VPN
)
4668 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4671 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4673 if (afi
!= AFI_L2VPN
) {
4675 safi
= SAFI_MPLS_VPN
;
4676 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4677 rn
= bgp_route_next(rn
)) {
4678 table
= bgp_node_get_bgp_table_info(rn
);
4679 if (table
!= NULL
) {
4680 bgp_cleanup_table(bgp
, table
, safi
);
4681 bgp_table_finish(&table
);
4682 bgp_node_set_bgp_table_info(rn
, NULL
);
4683 bgp_unlock_node(rn
);
4687 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4688 rn
= bgp_route_next(rn
)) {
4689 table
= bgp_node_get_bgp_table_info(rn
);
4690 if (table
!= NULL
) {
4691 bgp_cleanup_table(bgp
, table
, safi
);
4692 bgp_table_finish(&table
);
4693 bgp_node_set_bgp_table_info(rn
, NULL
);
4694 bgp_unlock_node(rn
);
4699 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4700 rn
= bgp_route_next(rn
)) {
4701 table
= bgp_node_get_bgp_table_info(rn
);
4702 if (table
!= NULL
) {
4703 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4704 bgp_table_finish(&table
);
4705 bgp_node_set_bgp_table_info(rn
, NULL
);
4706 bgp_unlock_node(rn
);
4711 void bgp_reset(void)
4714 bgp_zclient_reset();
4715 access_list_reset();
4716 prefix_list_reset();
4719 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4721 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4722 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4723 PEER_CAP_ADDPATH_AF_TX_RCV
));
4726 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4728 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4729 struct bgp_nlri
*packet
)
4738 int addpath_encoded
;
4739 uint32_t addpath_id
;
4742 lim
= pnt
+ packet
->length
;
4744 safi
= packet
->safi
;
4746 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4748 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4749 syntactic validity. If the field is syntactically incorrect,
4750 then the Error Subcode is set to Invalid Network Field. */
4751 for (; pnt
< lim
; pnt
+= psize
) {
4752 /* Clear prefix structure. */
4753 memset(&p
, 0, sizeof(struct prefix
));
4755 if (addpath_encoded
) {
4757 /* When packet overflow occurs return immediately. */
4758 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4759 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4761 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4762 addpath_id
= ntohl(addpath_id
);
4763 pnt
+= BGP_ADDPATH_ID_LEN
;
4766 /* Fetch prefix length. */
4767 p
.prefixlen
= *pnt
++;
4768 /* afi/safi validity already verified by caller,
4769 * bgp_update_receive */
4770 p
.family
= afi2family(afi
);
4772 /* Prefix length check. */
4773 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4776 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4777 peer
->host
, p
.prefixlen
, packet
->afi
);
4778 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4781 /* Packet size overflow check. */
4782 psize
= PSIZE(p
.prefixlen
);
4784 /* When packet overflow occur return immediately. */
4785 if (pnt
+ psize
> lim
) {
4788 "%s [Error] Update packet error (prefix length %d overflows packet)",
4789 peer
->host
, p
.prefixlen
);
4790 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4793 /* Defensive coding, double-check the psize fits in a struct
4795 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4798 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4799 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4800 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4803 /* Fetch prefix from NLRI packet. */
4804 memcpy(p
.u
.val
, pnt
, psize
);
4806 /* Check address. */
4807 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4808 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4809 /* From RFC4271 Section 6.3:
4811 * If a prefix in the NLRI field is semantically
4813 * (e.g., an unexpected multicast IP address),
4815 * be logged locally, and the prefix SHOULD be
4820 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4821 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4826 /* Check address. */
4827 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4828 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4833 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4835 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4840 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4845 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4847 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4854 /* Normal process. */
4856 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4857 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4858 NULL
, NULL
, 0, 0, NULL
);
4860 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4861 safi
, ZEBRA_ROUTE_BGP
,
4862 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4865 /* Do not send BGP notification twice when maximum-prefix count
4867 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4868 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4870 /* Address family configuration mismatch. */
4872 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4875 /* Packet length consistency check. */
4879 "%s [Error] Update packet error (prefix length mismatch with total length)",
4881 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4884 return BGP_NLRI_PARSE_OK
;
4887 static struct bgp_static
*bgp_static_new(void)
4889 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4892 static void bgp_static_free(struct bgp_static
*bgp_static
)
4894 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4895 route_map_counter_decrement(bgp_static
->rmap
.map
);
4897 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4898 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4901 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4902 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4904 struct bgp_node
*rn
;
4905 struct bgp_path_info
*pi
;
4906 struct bgp_path_info
*new;
4907 struct bgp_path_info rmap_path
;
4909 struct attr
*attr_new
;
4910 route_map_result_t ret
;
4912 int vnc_implicit_withdraw
= 0;
4919 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4921 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4923 attr
.nexthop
= bgp_static
->igpnexthop
;
4924 attr
.med
= bgp_static
->igpmetric
;
4925 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4927 if (bgp_static
->atomic
)
4928 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4930 /* Store label index, if required. */
4931 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4932 attr
.label_index
= bgp_static
->label_index
;
4933 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4936 /* Apply route-map. */
4937 if (bgp_static
->rmap
.name
) {
4938 struct attr attr_tmp
= attr
;
4940 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4941 rmap_path
.peer
= bgp
->peer_self
;
4942 rmap_path
.attr
= &attr_tmp
;
4944 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4946 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4949 bgp
->peer_self
->rmap_type
= 0;
4951 if (ret
== RMAP_DENYMATCH
) {
4952 /* Free uninterned attribute. */
4953 bgp_attr_flush(&attr_tmp
);
4955 /* Unintern original. */
4956 aspath_unintern(&attr
.aspath
);
4957 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4961 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4962 bgp_attr_add_gshut_community(&attr_tmp
);
4964 attr_new
= bgp_attr_intern(&attr_tmp
);
4967 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4968 bgp_attr_add_gshut_community(&attr
);
4970 attr_new
= bgp_attr_intern(&attr
);
4973 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4974 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4975 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4979 if (attrhash_cmp(pi
->attr
, attr_new
)
4980 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4981 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4982 bgp_unlock_node(rn
);
4983 bgp_attr_unintern(&attr_new
);
4984 aspath_unintern(&attr
.aspath
);
4987 /* The attribute is changed. */
4988 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4990 /* Rewrite BGP route information. */
4991 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4992 bgp_path_info_restore(rn
, pi
);
4994 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4996 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4997 && (safi
== SAFI_UNICAST
)) {
4998 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
5000 * Implicit withdraw case.
5001 * We have to do this before pi is
5004 ++vnc_implicit_withdraw
;
5005 vnc_import_bgp_del_route(bgp
, p
, pi
);
5006 vnc_import_bgp_exterior_del_route(
5011 bgp_attr_unintern(&pi
->attr
);
5012 pi
->attr
= attr_new
;
5013 pi
->uptime
= bgp_clock();
5015 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5016 && (safi
== SAFI_UNICAST
)) {
5017 if (vnc_implicit_withdraw
) {
5018 vnc_import_bgp_add_route(bgp
, p
, pi
);
5019 vnc_import_bgp_exterior_add_route(
5025 /* Nexthop reachability check. */
5026 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5027 && (safi
== SAFI_UNICAST
5028 || safi
== SAFI_LABELED_UNICAST
)) {
5030 struct bgp
*bgp_nexthop
= bgp
;
5032 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5033 bgp_nexthop
= pi
->extra
->bgp_orig
;
5035 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5037 bgp_path_info_set_flag(rn
, pi
,
5040 if (BGP_DEBUG(nht
, NHT
)) {
5041 char buf1
[INET6_ADDRSTRLEN
];
5042 inet_ntop(p
->family
,
5046 "%s(%s): Route not in table, not advertising",
5047 __FUNCTION__
, buf1
);
5049 bgp_path_info_unset_flag(
5050 rn
, pi
, BGP_PATH_VALID
);
5053 /* Delete the NHT structure if any, if we're
5055 * enabling/disabling import check. We
5056 * deregister the route
5057 * from NHT to avoid overloading NHT and the
5058 * process interaction
5060 bgp_unlink_nexthop(pi
);
5061 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
5063 /* Process change. */
5064 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5065 bgp_process(bgp
, rn
, afi
, safi
);
5067 if (SAFI_UNICAST
== safi
5068 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5070 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5071 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5075 bgp_unlock_node(rn
);
5076 aspath_unintern(&attr
.aspath
);
5081 /* Make new BGP info. */
5082 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5084 /* Nexthop reachability check. */
5085 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5086 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5087 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5088 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5090 if (BGP_DEBUG(nht
, NHT
)) {
5091 char buf1
[INET6_ADDRSTRLEN
];
5092 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5095 "%s(%s): Route not in table, not advertising",
5096 __FUNCTION__
, buf1
);
5098 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
5101 /* Delete the NHT structure if any, if we're toggling between
5102 * enabling/disabling import check. We deregister the route
5103 * from NHT to avoid overloading NHT and the process interaction
5105 bgp_unlink_nexthop(new);
5107 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5110 /* Aggregate address increment. */
5111 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5113 /* Register new BGP information. */
5114 bgp_path_info_add(rn
, new);
5116 /* route_node_get lock */
5117 bgp_unlock_node(rn
);
5119 /* Process change. */
5120 bgp_process(bgp
, rn
, afi
, safi
);
5122 if (SAFI_UNICAST
== safi
5123 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5124 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5125 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5128 /* Unintern original. */
5129 aspath_unintern(&attr
.aspath
);
5132 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5135 struct bgp_node
*rn
;
5136 struct bgp_path_info
*pi
;
5138 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5140 /* Check selected route and self inserted route. */
5141 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5142 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5143 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5146 /* Withdraw static BGP route from routing table. */
5148 if (SAFI_UNICAST
== safi
5149 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5150 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5151 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5153 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5154 bgp_unlink_nexthop(pi
);
5155 bgp_path_info_delete(rn
, pi
);
5156 bgp_process(bgp
, rn
, afi
, safi
);
5159 /* Unlock bgp_node_lookup. */
5160 bgp_unlock_node(rn
);
5164 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5166 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
5167 afi_t afi
, safi_t safi
,
5168 struct prefix_rd
*prd
)
5170 struct bgp_node
*rn
;
5171 struct bgp_path_info
*pi
;
5173 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5175 /* Check selected route and self inserted route. */
5176 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5177 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5178 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5181 /* Withdraw static BGP route from routing table. */
5184 rfapiProcessWithdraw(
5185 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5186 1); /* Kill, since it is an administrative change */
5188 if (SAFI_MPLS_VPN
== safi
5189 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5190 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5192 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5193 bgp_path_info_delete(rn
, pi
);
5194 bgp_process(bgp
, rn
, afi
, safi
);
5197 /* Unlock bgp_node_lookup. */
5198 bgp_unlock_node(rn
);
5201 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
5202 struct bgp_static
*bgp_static
, afi_t afi
,
5205 struct bgp_node
*rn
;
5206 struct bgp_path_info
*new;
5207 struct attr
*attr_new
;
5208 struct attr attr
= {0};
5209 struct bgp_path_info
*pi
;
5211 mpls_label_t label
= 0;
5213 uint32_t num_labels
= 0;
5218 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5220 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5223 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5225 attr
.nexthop
= bgp_static
->igpnexthop
;
5226 attr
.med
= bgp_static
->igpmetric
;
5227 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5229 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5230 || (safi
== SAFI_ENCAP
)) {
5231 if (afi
== AFI_IP
) {
5232 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5233 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5236 if (afi
== AFI_L2VPN
) {
5237 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5239 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5240 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5241 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5242 sizeof(struct in6_addr
));
5243 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5244 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5245 struct bgp_encap_type_vxlan bet
;
5246 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5247 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5248 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5250 if (bgp_static
->router_mac
) {
5251 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5254 /* Apply route-map. */
5255 if (bgp_static
->rmap
.name
) {
5256 struct attr attr_tmp
= attr
;
5257 struct bgp_path_info rmap_path
;
5258 route_map_result_t ret
;
5260 rmap_path
.peer
= bgp
->peer_self
;
5261 rmap_path
.attr
= &attr_tmp
;
5263 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5265 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5268 bgp
->peer_self
->rmap_type
= 0;
5270 if (ret
== RMAP_DENYMATCH
) {
5271 /* Free uninterned attribute. */
5272 bgp_attr_flush(&attr_tmp
);
5274 /* Unintern original. */
5275 aspath_unintern(&attr
.aspath
);
5276 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5281 attr_new
= bgp_attr_intern(&attr_tmp
);
5283 attr_new
= bgp_attr_intern(&attr
);
5286 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5287 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5288 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5292 memset(&add
, 0, sizeof(union gw_addr
));
5293 if (attrhash_cmp(pi
->attr
, attr_new
)
5294 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5295 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5296 bgp_unlock_node(rn
);
5297 bgp_attr_unintern(&attr_new
);
5298 aspath_unintern(&attr
.aspath
);
5301 /* The attribute is changed. */
5302 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5304 /* Rewrite BGP route information. */
5305 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5306 bgp_path_info_restore(rn
, pi
);
5308 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5309 bgp_attr_unintern(&pi
->attr
);
5310 pi
->attr
= attr_new
;
5311 pi
->uptime
= bgp_clock();
5314 label
= decode_label(&pi
->extra
->label
[0]);
5317 /* Process change. */
5318 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5319 bgp_process(bgp
, rn
, afi
, safi
);
5321 if (SAFI_MPLS_VPN
== safi
5322 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5323 vpn_leak_to_vrf_update(bgp
, pi
);
5326 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5327 pi
->attr
, afi
, safi
, pi
->type
,
5328 pi
->sub_type
, &label
);
5330 bgp_unlock_node(rn
);
5331 aspath_unintern(&attr
.aspath
);
5337 /* Make new BGP info. */
5338 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5340 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5341 new->extra
= bgp_path_info_extra_new();
5343 new->extra
->label
[0] = bgp_static
->label
;
5344 new->extra
->num_labels
= num_labels
;
5347 label
= decode_label(&bgp_static
->label
);
5350 /* Aggregate address increment. */
5351 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5353 /* Register new BGP information. */
5354 bgp_path_info_add(rn
, new);
5355 /* route_node_get lock */
5356 bgp_unlock_node(rn
);
5358 /* Process change. */
5359 bgp_process(bgp
, rn
, afi
, safi
);
5361 if (SAFI_MPLS_VPN
== safi
5362 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5363 vpn_leak_to_vrf_update(bgp
, new);
5366 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5367 safi
, new->type
, new->sub_type
, &label
);
5370 /* Unintern original. */
5371 aspath_unintern(&attr
.aspath
);
5374 /* Configure static BGP network. When user don't run zebra, static
5375 route should be installed as valid. */
5376 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5377 const char *ip_str
, afi_t afi
, safi_t safi
,
5378 const char *rmap
, int backdoor
, uint32_t label_index
)
5380 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5383 struct bgp_static
*bgp_static
;
5384 struct bgp_node
*rn
;
5385 uint8_t need_update
= 0;
5387 /* Convert IP prefix string to struct prefix. */
5388 ret
= str2prefix(ip_str
, &p
);
5390 vty_out(vty
, "%% Malformed prefix\n");
5391 return CMD_WARNING_CONFIG_FAILED
;
5393 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5394 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5395 return CMD_WARNING_CONFIG_FAILED
;
5402 /* Set BGP static route configuration. */
5403 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5406 vty_out(vty
, "%% Can't find static route specified\n");
5407 return CMD_WARNING_CONFIG_FAILED
;
5410 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5412 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5413 && (label_index
!= bgp_static
->label_index
)) {
5415 "%% label-index doesn't match static route\n");
5416 return CMD_WARNING_CONFIG_FAILED
;
5419 if ((rmap
&& bgp_static
->rmap
.name
)
5420 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5422 "%% route-map name doesn't match static route\n");
5423 return CMD_WARNING_CONFIG_FAILED
;
5426 /* Update BGP RIB. */
5427 if (!bgp_static
->backdoor
)
5428 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5430 /* Clear configuration. */
5431 bgp_static_free(bgp_static
);
5432 bgp_node_set_bgp_static_info(rn
, NULL
);
5433 bgp_unlock_node(rn
);
5434 bgp_unlock_node(rn
);
5437 /* Set BGP static route configuration. */
5438 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5440 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5442 /* Configuration change. */
5443 /* Label index cannot be changed. */
5444 if (bgp_static
->label_index
!= label_index
) {
5445 vty_out(vty
, "%% cannot change label-index\n");
5446 return CMD_WARNING_CONFIG_FAILED
;
5449 /* Check previous routes are installed into BGP. */
5450 if (bgp_static
->valid
5451 && bgp_static
->backdoor
!= backdoor
)
5454 bgp_static
->backdoor
= backdoor
;
5457 XFREE(MTYPE_ROUTE_MAP_NAME
,
5458 bgp_static
->rmap
.name
);
5459 route_map_counter_decrement(
5460 bgp_static
->rmap
.map
);
5461 bgp_static
->rmap
.name
=
5462 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5463 bgp_static
->rmap
.map
=
5464 route_map_lookup_by_name(rmap
);
5465 route_map_counter_increment(
5466 bgp_static
->rmap
.map
);
5468 XFREE(MTYPE_ROUTE_MAP_NAME
,
5469 bgp_static
->rmap
.name
);
5470 route_map_counter_decrement(
5471 bgp_static
->rmap
.map
);
5472 bgp_static
->rmap
.name
= NULL
;
5473 bgp_static
->rmap
.map
= NULL
;
5474 bgp_static
->valid
= 0;
5476 bgp_unlock_node(rn
);
5478 /* New configuration. */
5479 bgp_static
= bgp_static_new();
5480 bgp_static
->backdoor
= backdoor
;
5481 bgp_static
->valid
= 0;
5482 bgp_static
->igpmetric
= 0;
5483 bgp_static
->igpnexthop
.s_addr
= 0;
5484 bgp_static
->label_index
= label_index
;
5487 XFREE(MTYPE_ROUTE_MAP_NAME
,
5488 bgp_static
->rmap
.name
);
5489 route_map_counter_decrement(
5490 bgp_static
->rmap
.map
);
5491 bgp_static
->rmap
.name
=
5492 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5493 bgp_static
->rmap
.map
=
5494 route_map_lookup_by_name(rmap
);
5495 route_map_counter_increment(
5496 bgp_static
->rmap
.map
);
5498 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5501 bgp_static
->valid
= 1;
5503 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5505 if (!bgp_static
->backdoor
)
5506 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5512 void bgp_static_add(struct bgp
*bgp
)
5516 struct bgp_node
*rn
;
5517 struct bgp_node
*rm
;
5518 struct bgp_table
*table
;
5519 struct bgp_static
*bgp_static
;
5521 FOREACH_AFI_SAFI (afi
, safi
)
5522 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5523 rn
= bgp_route_next(rn
)) {
5524 if (!bgp_node_has_bgp_path_info_data(rn
))
5527 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5528 || (safi
== SAFI_EVPN
)) {
5529 table
= bgp_node_get_bgp_table_info(rn
);
5531 for (rm
= bgp_table_top(table
); rm
;
5532 rm
= bgp_route_next(rm
)) {
5534 bgp_node_get_bgp_static_info(
5536 bgp_static_update_safi(bgp
, &rm
->p
,
5543 bgp_node_get_bgp_static_info(rn
), afi
,
5549 /* Called from bgp_delete(). Delete all static routes from the BGP
5551 void bgp_static_delete(struct bgp
*bgp
)
5555 struct bgp_node
*rn
;
5556 struct bgp_node
*rm
;
5557 struct bgp_table
*table
;
5558 struct bgp_static
*bgp_static
;
5560 FOREACH_AFI_SAFI (afi
, safi
)
5561 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5562 rn
= bgp_route_next(rn
)) {
5563 if (!bgp_node_has_bgp_path_info_data(rn
))
5566 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5567 || (safi
== SAFI_EVPN
)) {
5568 table
= bgp_node_get_bgp_table_info(rn
);
5570 for (rm
= bgp_table_top(table
); rm
;
5571 rm
= bgp_route_next(rm
)) {
5573 bgp_node_get_bgp_static_info(
5578 bgp_static_withdraw_safi(
5579 bgp
, &rm
->p
, AFI_IP
, safi
,
5580 (struct prefix_rd
*)&rn
->p
);
5581 bgp_static_free(bgp_static
);
5582 bgp_node_set_bgp_static_info(rn
, NULL
);
5583 bgp_unlock_node(rn
);
5586 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5587 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5588 bgp_static_free(bgp_static
);
5589 bgp_node_set_bgp_static_info(rn
, NULL
);
5590 bgp_unlock_node(rn
);
5595 void bgp_static_redo_import_check(struct bgp
*bgp
)
5599 struct bgp_node
*rn
;
5600 struct bgp_node
*rm
;
5601 struct bgp_table
*table
;
5602 struct bgp_static
*bgp_static
;
5604 /* Use this flag to force reprocessing of the route */
5605 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5606 FOREACH_AFI_SAFI (afi
, safi
) {
5607 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5608 rn
= bgp_route_next(rn
)) {
5609 if (!bgp_node_has_bgp_path_info_data(rn
))
5612 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5613 || (safi
== SAFI_EVPN
)) {
5614 table
= bgp_node_get_bgp_table_info(rn
);
5616 for (rm
= bgp_table_top(table
); rm
;
5617 rm
= bgp_route_next(rm
)) {
5619 bgp_node_get_bgp_static_info(
5621 bgp_static_update_safi(bgp
, &rm
->p
,
5626 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5627 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5632 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5635 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5638 struct bgp_table
*table
;
5639 struct bgp_node
*rn
;
5640 struct bgp_path_info
*pi
;
5642 /* Do not install the aggregate route if BGP is in the
5643 * process of termination.
5645 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5646 (bgp
->peer_self
== NULL
))
5649 table
= bgp
->rib
[afi
][safi
];
5650 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5651 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5652 if (pi
->peer
== bgp
->peer_self
5653 && ((pi
->type
== ZEBRA_ROUTE_BGP
5654 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5655 || (pi
->type
!= ZEBRA_ROUTE_BGP
5657 == BGP_ROUTE_REDISTRIBUTE
))) {
5658 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5660 bgp_unlink_nexthop(pi
);
5661 bgp_path_info_delete(rn
, pi
);
5662 bgp_process(bgp
, rn
, afi
, safi
);
5669 * Purge all networks and redistributed routes from routing table.
5670 * Invoked upon the instance going down.
5672 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5677 FOREACH_AFI_SAFI (afi
, safi
)
5678 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5683 * Currently this is used to set static routes for VPN and ENCAP.
5684 * I think it can probably be factored with bgp_static_set.
5686 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5687 const char *ip_str
, const char *rd_str
,
5688 const char *label_str
, const char *rmap_str
,
5689 int evpn_type
, const char *esi
, const char *gwip
,
5690 const char *ethtag
, const char *routermac
)
5692 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5695 struct prefix_rd prd
;
5696 struct bgp_node
*prn
;
5697 struct bgp_node
*rn
;
5698 struct bgp_table
*table
;
5699 struct bgp_static
*bgp_static
;
5700 mpls_label_t label
= MPLS_INVALID_LABEL
;
5701 struct prefix gw_ip
;
5703 /* validate ip prefix */
5704 ret
= str2prefix(ip_str
, &p
);
5706 vty_out(vty
, "%% Malformed prefix\n");
5707 return CMD_WARNING_CONFIG_FAILED
;
5710 if ((afi
== AFI_L2VPN
)
5711 && (bgp_build_evpn_prefix(evpn_type
,
5712 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5713 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5714 return CMD_WARNING_CONFIG_FAILED
;
5717 ret
= str2prefix_rd(rd_str
, &prd
);
5719 vty_out(vty
, "%% Malformed rd\n");
5720 return CMD_WARNING_CONFIG_FAILED
;
5724 unsigned long label_val
;
5725 label_val
= strtoul(label_str
, NULL
, 10);
5726 encode_label(label_val
, &label
);
5729 if (safi
== SAFI_EVPN
) {
5730 if (esi
&& str2esi(esi
, NULL
) == 0) {
5731 vty_out(vty
, "%% Malformed ESI\n");
5732 return CMD_WARNING_CONFIG_FAILED
;
5734 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5735 vty_out(vty
, "%% Malformed Router MAC\n");
5736 return CMD_WARNING_CONFIG_FAILED
;
5739 memset(&gw_ip
, 0, sizeof(struct prefix
));
5740 ret
= str2prefix(gwip
, &gw_ip
);
5742 vty_out(vty
, "%% Malformed GatewayIp\n");
5743 return CMD_WARNING_CONFIG_FAILED
;
5745 if ((gw_ip
.family
== AF_INET
5746 && is_evpn_prefix_ipaddr_v6(
5747 (struct prefix_evpn
*)&p
))
5748 || (gw_ip
.family
== AF_INET6
5749 && is_evpn_prefix_ipaddr_v4(
5750 (struct prefix_evpn
*)&p
))) {
5752 "%% GatewayIp family differs with IP prefix\n");
5753 return CMD_WARNING_CONFIG_FAILED
;
5757 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5758 if (!bgp_node_has_bgp_path_info_data(prn
))
5759 bgp_node_set_bgp_table_info(prn
,
5760 bgp_table_init(bgp
, afi
, safi
));
5761 table
= bgp_node_get_bgp_table_info(prn
);
5763 rn
= bgp_node_get(table
, &p
);
5765 if (bgp_node_has_bgp_path_info_data(rn
)) {
5766 vty_out(vty
, "%% Same network configuration exists\n");
5767 bgp_unlock_node(rn
);
5769 /* New configuration. */
5770 bgp_static
= bgp_static_new();
5771 bgp_static
->backdoor
= 0;
5772 bgp_static
->valid
= 0;
5773 bgp_static
->igpmetric
= 0;
5774 bgp_static
->igpnexthop
.s_addr
= 0;
5775 bgp_static
->label
= label
;
5776 bgp_static
->prd
= prd
;
5779 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5780 route_map_counter_decrement(bgp_static
->rmap
.map
);
5781 bgp_static
->rmap
.name
=
5782 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5783 bgp_static
->rmap
.map
=
5784 route_map_lookup_by_name(rmap_str
);
5785 route_map_counter_increment(bgp_static
->rmap
.map
);
5788 if (safi
== SAFI_EVPN
) {
5790 bgp_static
->eth_s_id
=
5792 sizeof(struct eth_segment_id
));
5793 str2esi(esi
, bgp_static
->eth_s_id
);
5796 bgp_static
->router_mac
=
5797 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5798 (void)prefix_str2mac(routermac
,
5799 bgp_static
->router_mac
);
5802 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5804 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5806 bgp_static
->valid
= 1;
5807 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5813 /* Configure static BGP network. */
5814 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5815 const char *ip_str
, const char *rd_str
,
5816 const char *label_str
, int evpn_type
, const char *esi
,
5817 const char *gwip
, const char *ethtag
)
5819 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5822 struct prefix_rd prd
;
5823 struct bgp_node
*prn
;
5824 struct bgp_node
*rn
;
5825 struct bgp_table
*table
;
5826 struct bgp_static
*bgp_static
;
5827 mpls_label_t label
= MPLS_INVALID_LABEL
;
5829 /* Convert IP prefix string to struct prefix. */
5830 ret
= str2prefix(ip_str
, &p
);
5832 vty_out(vty
, "%% Malformed prefix\n");
5833 return CMD_WARNING_CONFIG_FAILED
;
5836 if ((afi
== AFI_L2VPN
)
5837 && (bgp_build_evpn_prefix(evpn_type
,
5838 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5839 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5840 return CMD_WARNING_CONFIG_FAILED
;
5842 ret
= str2prefix_rd(rd_str
, &prd
);
5844 vty_out(vty
, "%% Malformed rd\n");
5845 return CMD_WARNING_CONFIG_FAILED
;
5849 unsigned long label_val
;
5850 label_val
= strtoul(label_str
, NULL
, 10);
5851 encode_label(label_val
, &label
);
5854 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5855 if (!bgp_node_has_bgp_path_info_data(prn
))
5856 bgp_node_set_bgp_table_info(prn
,
5857 bgp_table_init(bgp
, afi
, safi
));
5859 bgp_unlock_node(prn
);
5860 table
= bgp_node_get_bgp_table_info(prn
);
5862 rn
= bgp_node_lookup(table
, &p
);
5865 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5867 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5868 bgp_static_free(bgp_static
);
5869 bgp_node_set_bgp_static_info(rn
, NULL
);
5870 bgp_unlock_node(rn
);
5871 bgp_unlock_node(rn
);
5873 vty_out(vty
, "%% Can't find the route\n");
5878 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5879 const char *rmap_name
)
5881 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5882 struct bgp_rmap
*rmap
;
5884 rmap
= &bgp
->table_map
[afi
][safi
];
5886 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5887 route_map_counter_decrement(rmap
->map
);
5888 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5889 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5890 route_map_counter_increment(rmap
->map
);
5892 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5893 route_map_counter_decrement(rmap
->map
);
5898 if (bgp_fibupd_safi(safi
))
5899 bgp_zebra_announce_table(bgp
, afi
, safi
);
5904 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5905 const char *rmap_name
)
5907 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5908 struct bgp_rmap
*rmap
;
5910 rmap
= &bgp
->table_map
[afi
][safi
];
5911 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5912 route_map_counter_decrement(rmap
->map
);
5916 if (bgp_fibupd_safi(safi
))
5917 bgp_zebra_announce_table(bgp
, afi
, safi
);
5922 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5925 if (bgp
->table_map
[afi
][safi
].name
) {
5926 vty_out(vty
, " table-map %s\n",
5927 bgp
->table_map
[afi
][safi
].name
);
5931 DEFUN (bgp_table_map
,
5934 "BGP table to RIB route download filter\n"
5935 "Name of the route map\n")
5938 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5939 argv
[idx_word
]->arg
);
5941 DEFUN (no_bgp_table_map
,
5942 no_bgp_table_map_cmd
,
5943 "no table-map WORD",
5945 "BGP table to RIB route download filter\n"
5946 "Name of the route map\n")
5949 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5950 argv
[idx_word
]->arg
);
5956 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5957 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5958 backdoor$backdoor}]",
5960 "Specify a network to announce via BGP\n"
5965 "Route-map to modify the attributes\n"
5966 "Name of the route map\n"
5967 "Label index to associate with the prefix\n"
5968 "Label index value\n"
5969 "Specify a BGP backdoor route\n")
5971 char addr_prefix_str
[BUFSIZ
];
5976 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5979 vty_out(vty
, "%% Inconsistent address and mask\n");
5980 return CMD_WARNING_CONFIG_FAILED
;
5984 return bgp_static_set(
5985 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5986 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5987 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5990 DEFPY(ipv6_bgp_network
,
5991 ipv6_bgp_network_cmd
,
5992 "[no] network X:X::X:X/M$prefix \
5993 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5995 "Specify a network to announce via BGP\n"
5997 "Route-map to modify the attributes\n"
5998 "Name of the route map\n"
5999 "Label index to associate with the prefix\n"
6000 "Label index value\n")
6002 return bgp_static_set(
6003 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
6004 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
6007 static struct bgp_aggregate
*bgp_aggregate_new(void)
6009 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
6012 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
6014 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6015 route_map_counter_decrement(aggregate
->rmap
.map
);
6016 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6019 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6020 struct aspath
*aspath
,
6021 struct community
*comm
,
6022 struct ecommunity
*ecomm
,
6023 struct lcommunity
*lcomm
)
6025 static struct aspath
*ae
= NULL
;
6028 ae
= aspath_empty();
6033 if (origin
!= pi
->attr
->origin
)
6036 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6039 if (!community_cmp(pi
->attr
->community
, comm
))
6042 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6045 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6048 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6054 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
6055 struct prefix
*p
, uint8_t origin
,
6056 struct aspath
*aspath
,
6057 struct community
*community
,
6058 struct ecommunity
*ecommunity
,
6059 struct lcommunity
*lcommunity
,
6060 uint8_t atomic_aggregate
,
6061 struct bgp_aggregate
*aggregate
)
6063 struct bgp_node
*rn
;
6064 struct bgp_table
*table
;
6065 struct bgp_path_info
*pi
, *orig
, *new;
6068 table
= bgp
->rib
[afi
][safi
];
6070 rn
= bgp_node_get(table
, p
);
6072 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6073 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6074 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6077 if (aggregate
->count
> 0) {
6079 * If the aggregate information has not changed
6080 * no need to re-install it again.
6082 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6083 ecommunity
, lcommunity
)) {
6084 bgp_unlock_node(rn
);
6087 aspath_free(aspath
);
6089 community_free(&community
);
6091 ecommunity_free(&ecommunity
);
6093 lcommunity_free(&lcommunity
);
6099 * Mark the old as unusable
6102 bgp_path_info_delete(rn
, pi
);
6104 attr
= bgp_attr_aggregate_intern(
6105 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6106 aggregate
, atomic_aggregate
, p
);
6109 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6113 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6114 bgp
->peer_self
, attr
, rn
);
6116 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6118 bgp_path_info_add(rn
, new);
6119 bgp_process(bgp
, rn
, afi
, safi
);
6121 for (pi
= orig
; pi
; pi
= pi
->next
)
6122 if (pi
->peer
== bgp
->peer_self
6123 && pi
->type
== ZEBRA_ROUTE_BGP
6124 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6127 /* Withdraw static BGP route from routing table. */
6129 bgp_path_info_delete(rn
, pi
);
6130 bgp_process(bgp
, rn
, afi
, safi
);
6134 bgp_unlock_node(rn
);
6137 /* Update an aggregate as routes are added/removed from the BGP table */
6138 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
6139 afi_t afi
, safi_t safi
,
6140 struct bgp_aggregate
*aggregate
)
6142 struct bgp_table
*table
;
6143 struct bgp_node
*top
;
6144 struct bgp_node
*rn
;
6146 struct aspath
*aspath
= NULL
;
6147 struct community
*community
= NULL
;
6148 struct ecommunity
*ecommunity
= NULL
;
6149 struct lcommunity
*lcommunity
= NULL
;
6150 struct bgp_path_info
*pi
;
6151 unsigned long match
= 0;
6152 uint8_t atomic_aggregate
= 0;
6154 /* If the bgp instance is being deleted or self peer is deleted
6155 * then do not create aggregate route
6157 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
6158 (bgp
->peer_self
== NULL
))
6161 /* ORIGIN attribute: If at least one route among routes that are
6162 aggregated has ORIGIN with the value INCOMPLETE, then the
6163 aggregated route must have the ORIGIN attribute with the value
6164 INCOMPLETE. Otherwise, if at least one route among routes that
6165 are aggregated has ORIGIN with the value EGP, then the aggregated
6166 route must have the origin attribute with the value EGP. In all
6167 other case the value of the ORIGIN attribute of the aggregated
6168 route is INTERNAL. */
6169 origin
= BGP_ORIGIN_IGP
;
6171 table
= bgp
->rib
[afi
][safi
];
6173 top
= bgp_node_get(table
, p
);
6174 for (rn
= bgp_node_get(table
, p
); rn
;
6175 rn
= bgp_route_next_until(rn
, top
)) {
6176 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6181 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6182 if (BGP_PATH_HOLDDOWN(pi
))
6186 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6187 atomic_aggregate
= 1;
6189 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6193 * summary-only aggregate route suppress
6194 * aggregated route announcements.
6196 if (aggregate
->summary_only
) {
6197 (bgp_path_info_extra_get(pi
))->suppress
++;
6198 bgp_path_info_set_flag(rn
, pi
,
6199 BGP_PATH_ATTR_CHANGED
);
6206 * If at least one route among routes that are
6207 * aggregated has ORIGIN with the value INCOMPLETE,
6208 * then the aggregated route MUST have the ORIGIN
6209 * attribute with the value INCOMPLETE. Otherwise, if
6210 * at least one route among routes that are aggregated
6211 * has ORIGIN with the value EGP, then the aggregated
6212 * route MUST have the ORIGIN attribute with the value
6215 switch (pi
->attr
->origin
) {
6216 case BGP_ORIGIN_INCOMPLETE
:
6217 aggregate
->incomplete_origin_count
++;
6219 case BGP_ORIGIN_EGP
:
6220 aggregate
->egp_origin_count
++;
6228 if (!aggregate
->as_set
)
6232 * as-set aggregate route generate origin, as path,
6233 * and community aggregation.
6235 /* Compute aggregate route's as-path.
6237 bgp_compute_aggregate_aspath_hash(aggregate
,
6240 /* Compute aggregate route's community.
6242 if (pi
->attr
->community
)
6243 bgp_compute_aggregate_community_hash(
6245 pi
->attr
->community
);
6247 /* Compute aggregate route's extended community.
6249 if (pi
->attr
->ecommunity
)
6250 bgp_compute_aggregate_ecommunity_hash(
6252 pi
->attr
->ecommunity
);
6254 /* Compute aggregate route's large community.
6256 if (pi
->attr
->lcommunity
)
6257 bgp_compute_aggregate_lcommunity_hash(
6259 pi
->attr
->lcommunity
);
6262 bgp_process(bgp
, rn
, afi
, safi
);
6264 if (aggregate
->as_set
) {
6265 bgp_compute_aggregate_aspath_val(aggregate
);
6266 bgp_compute_aggregate_community_val(aggregate
);
6267 bgp_compute_aggregate_ecommunity_val(aggregate
);
6268 bgp_compute_aggregate_lcommunity_val(aggregate
);
6272 bgp_unlock_node(top
);
6275 if (aggregate
->incomplete_origin_count
> 0)
6276 origin
= BGP_ORIGIN_INCOMPLETE
;
6277 else if (aggregate
->egp_origin_count
> 0)
6278 origin
= BGP_ORIGIN_EGP
;
6280 if (aggregate
->as_set
) {
6281 if (aggregate
->aspath
)
6282 /* Retrieve aggregate route's as-path.
6284 aspath
= aspath_dup(aggregate
->aspath
);
6286 if (aggregate
->community
)
6287 /* Retrieve aggregate route's community.
6289 community
= community_dup(aggregate
->community
);
6291 if (aggregate
->ecommunity
)
6292 /* Retrieve aggregate route's ecommunity.
6294 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6296 if (aggregate
->lcommunity
)
6297 /* Retrieve aggregate route's lcommunity.
6299 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6302 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6303 ecommunity
, lcommunity
, atomic_aggregate
,
6307 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6308 safi_t safi
, struct bgp_aggregate
*aggregate
)
6310 struct bgp_table
*table
;
6311 struct bgp_node
*top
;
6312 struct bgp_node
*rn
;
6313 struct bgp_path_info
*pi
;
6314 unsigned long match
;
6316 table
= bgp
->rib
[afi
][safi
];
6318 /* If routes exists below this node, generate aggregate routes. */
6319 top
= bgp_node_get(table
, p
);
6320 for (rn
= bgp_node_get(table
, p
); rn
;
6321 rn
= bgp_route_next_until(rn
, top
)) {
6322 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6326 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6327 if (BGP_PATH_HOLDDOWN(pi
))
6330 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6333 if (aggregate
->summary_only
&& pi
->extra
) {
6334 pi
->extra
->suppress
--;
6336 if (pi
->extra
->suppress
== 0) {
6337 bgp_path_info_set_flag(
6338 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6344 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6345 aggregate
->incomplete_origin_count
--;
6346 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6347 aggregate
->egp_origin_count
--;
6349 if (aggregate
->as_set
) {
6350 /* Remove as-path from aggregate.
6352 bgp_remove_aspath_from_aggregate_hash(
6356 if (pi
->attr
->community
)
6357 /* Remove community from aggregate.
6359 bgp_remove_comm_from_aggregate_hash(
6361 pi
->attr
->community
);
6363 if (pi
->attr
->ecommunity
)
6364 /* Remove ecommunity from aggregate.
6366 bgp_remove_ecomm_from_aggregate_hash(
6368 pi
->attr
->ecommunity
);
6370 if (pi
->attr
->lcommunity
)
6371 /* Remove lcommunity from aggregate.
6373 bgp_remove_lcomm_from_aggregate_hash(
6375 pi
->attr
->lcommunity
);
6380 /* If this node was suppressed, process the change. */
6382 bgp_process(bgp
, rn
, afi
, safi
);
6384 if (aggregate
->as_set
) {
6385 aspath_free(aggregate
->aspath
);
6386 aggregate
->aspath
= NULL
;
6387 if (aggregate
->community
)
6388 community_free(&aggregate
->community
);
6389 if (aggregate
->ecommunity
)
6390 ecommunity_free(&aggregate
->ecommunity
);
6391 if (aggregate
->lcommunity
)
6392 lcommunity_free(&aggregate
->lcommunity
);
6395 bgp_unlock_node(top
);
6398 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6399 struct bgp_path_info
*pinew
, afi_t afi
,
6401 struct bgp_aggregate
*aggregate
)
6404 struct aspath
*aspath
= NULL
;
6405 uint8_t atomic_aggregate
= 0;
6406 struct community
*community
= NULL
;
6407 struct ecommunity
*ecommunity
= NULL
;
6408 struct lcommunity
*lcommunity
= NULL
;
6410 /* ORIGIN attribute: If at least one route among routes that are
6411 * aggregated has ORIGIN with the value INCOMPLETE, then the
6412 * aggregated route must have the ORIGIN attribute with the value
6413 * INCOMPLETE. Otherwise, if at least one route among routes that
6414 * are aggregated has ORIGIN with the value EGP, then the aggregated
6415 * route must have the origin attribute with the value EGP. In all
6416 * other case the value of the ORIGIN attribute of the aggregated
6417 * route is INTERNAL.
6419 origin
= BGP_ORIGIN_IGP
;
6423 if (aggregate
->summary_only
)
6424 (bgp_path_info_extra_get(pinew
))->suppress
++;
6426 switch (pinew
->attr
->origin
) {
6427 case BGP_ORIGIN_INCOMPLETE
:
6428 aggregate
->incomplete_origin_count
++;
6430 case BGP_ORIGIN_EGP
:
6431 aggregate
->egp_origin_count
++;
6439 if (aggregate
->incomplete_origin_count
> 0)
6440 origin
= BGP_ORIGIN_INCOMPLETE
;
6441 else if (aggregate
->egp_origin_count
> 0)
6442 origin
= BGP_ORIGIN_EGP
;
6444 if (aggregate
->as_set
) {
6445 /* Compute aggregate route's as-path.
6447 bgp_compute_aggregate_aspath(aggregate
,
6448 pinew
->attr
->aspath
);
6450 /* Compute aggregate route's community.
6452 if (pinew
->attr
->community
)
6453 bgp_compute_aggregate_community(
6455 pinew
->attr
->community
);
6457 /* Compute aggregate route's extended community.
6459 if (pinew
->attr
->ecommunity
)
6460 bgp_compute_aggregate_ecommunity(
6462 pinew
->attr
->ecommunity
);
6464 /* Compute aggregate route's large community.
6466 if (pinew
->attr
->lcommunity
)
6467 bgp_compute_aggregate_lcommunity(
6469 pinew
->attr
->lcommunity
);
6471 /* Retrieve aggregate route's as-path.
6473 if (aggregate
->aspath
)
6474 aspath
= aspath_dup(aggregate
->aspath
);
6476 /* Retrieve aggregate route's community.
6478 if (aggregate
->community
)
6479 community
= community_dup(aggregate
->community
);
6481 /* Retrieve aggregate route's ecommunity.
6483 if (aggregate
->ecommunity
)
6484 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6486 /* Retrieve aggregate route's lcommunity.
6488 if (aggregate
->lcommunity
)
6489 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6492 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6493 aspath
, community
, ecommunity
,
6494 lcommunity
, atomic_aggregate
, aggregate
);
6497 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6499 struct bgp_path_info
*pi
,
6500 struct bgp_aggregate
*aggregate
,
6501 struct prefix
*aggr_p
)
6504 struct aspath
*aspath
= NULL
;
6505 uint8_t atomic_aggregate
= 0;
6506 struct community
*community
= NULL
;
6507 struct ecommunity
*ecommunity
= NULL
;
6508 struct lcommunity
*lcommunity
= NULL
;
6509 unsigned long match
= 0;
6511 if (BGP_PATH_HOLDDOWN(pi
))
6514 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6517 if (aggregate
->summary_only
6519 && pi
->extra
->suppress
> 0) {
6520 pi
->extra
->suppress
--;
6522 if (pi
->extra
->suppress
== 0) {
6523 bgp_path_info_set_flag(pi
->net
, pi
,
6524 BGP_PATH_ATTR_CHANGED
);
6529 if (aggregate
->count
> 0)
6532 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6533 aggregate
->incomplete_origin_count
--;
6534 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6535 aggregate
->egp_origin_count
--;
6537 if (aggregate
->as_set
) {
6538 /* Remove as-path from aggregate.
6540 bgp_remove_aspath_from_aggregate(aggregate
,
6543 if (pi
->attr
->community
)
6544 /* Remove community from aggregate.
6546 bgp_remove_community_from_aggregate(
6548 pi
->attr
->community
);
6550 if (pi
->attr
->ecommunity
)
6551 /* Remove ecommunity from aggregate.
6553 bgp_remove_ecommunity_from_aggregate(
6555 pi
->attr
->ecommunity
);
6557 if (pi
->attr
->lcommunity
)
6558 /* Remove lcommunity from aggregate.
6560 bgp_remove_lcommunity_from_aggregate(
6562 pi
->attr
->lcommunity
);
6565 /* If this node was suppressed, process the change. */
6567 bgp_process(bgp
, pi
->net
, afi
, safi
);
6569 origin
= BGP_ORIGIN_IGP
;
6570 if (aggregate
->incomplete_origin_count
> 0)
6571 origin
= BGP_ORIGIN_INCOMPLETE
;
6572 else if (aggregate
->egp_origin_count
> 0)
6573 origin
= BGP_ORIGIN_EGP
;
6575 if (aggregate
->as_set
) {
6576 /* Retrieve aggregate route's as-path.
6578 if (aggregate
->aspath
)
6579 aspath
= aspath_dup(aggregate
->aspath
);
6581 /* Retrieve aggregate route's community.
6583 if (aggregate
->community
)
6584 community
= community_dup(aggregate
->community
);
6586 /* Retrieve aggregate route's ecommunity.
6588 if (aggregate
->ecommunity
)
6589 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6591 /* Retrieve aggregate route's lcommunity.
6593 if (aggregate
->lcommunity
)
6594 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6597 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6598 aspath
, community
, ecommunity
,
6599 lcommunity
, atomic_aggregate
, aggregate
);
6602 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6603 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6605 struct bgp_node
*child
;
6606 struct bgp_node
*rn
;
6607 struct bgp_aggregate
*aggregate
;
6608 struct bgp_table
*table
;
6610 table
= bgp
->aggregate
[afi
][safi
];
6612 /* No aggregates configured. */
6613 if (bgp_table_top_nolock(table
) == NULL
)
6616 if (p
->prefixlen
== 0)
6619 if (BGP_PATH_HOLDDOWN(pi
))
6622 child
= bgp_node_get(table
, p
);
6624 /* Aggregate address configuration check. */
6625 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6626 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6627 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6628 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6632 bgp_unlock_node(child
);
6635 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6636 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6638 struct bgp_node
*child
;
6639 struct bgp_node
*rn
;
6640 struct bgp_aggregate
*aggregate
;
6641 struct bgp_table
*table
;
6643 table
= bgp
->aggregate
[afi
][safi
];
6645 /* No aggregates configured. */
6646 if (bgp_table_top_nolock(table
) == NULL
)
6649 if (p
->prefixlen
== 0)
6652 child
= bgp_node_get(table
, p
);
6654 /* Aggregate address configuration check. */
6655 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6656 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6657 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6658 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6659 del
, aggregate
, &rn
->p
);
6662 bgp_unlock_node(child
);
6665 /* Aggregate route attribute. */
6666 #define AGGREGATE_SUMMARY_ONLY 1
6667 #define AGGREGATE_AS_SET 1
6668 #define AGGREGATE_AS_UNSET 0
6670 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6671 afi_t afi
, safi_t safi
)
6673 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6676 struct bgp_node
*rn
;
6677 struct bgp_aggregate
*aggregate
;
6679 /* Convert string to prefix structure. */
6680 ret
= str2prefix(prefix_str
, &p
);
6682 vty_out(vty
, "Malformed prefix\n");
6683 return CMD_WARNING_CONFIG_FAILED
;
6687 /* Old configuration check. */
6688 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6691 "%% There is no aggregate-address configuration.\n");
6692 return CMD_WARNING_CONFIG_FAILED
;
6695 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6696 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6697 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6698 NULL
, NULL
, 0, aggregate
);
6700 /* Unlock aggregate address configuration. */
6701 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6703 if (aggregate
->community
)
6704 community_free(&aggregate
->community
);
6706 if (aggregate
->community_hash
) {
6707 /* Delete all communities in the hash.
6709 hash_clean(aggregate
->community_hash
,
6710 bgp_aggr_community_remove
);
6711 /* Free up the community_hash.
6713 hash_free(aggregate
->community_hash
);
6716 if (aggregate
->ecommunity
)
6717 ecommunity_free(&aggregate
->ecommunity
);
6719 if (aggregate
->ecommunity_hash
) {
6720 /* Delete all ecommunities in the hash.
6722 hash_clean(aggregate
->ecommunity_hash
,
6723 bgp_aggr_ecommunity_remove
);
6724 /* Free up the ecommunity_hash.
6726 hash_free(aggregate
->ecommunity_hash
);
6729 if (aggregate
->lcommunity
)
6730 lcommunity_free(&aggregate
->lcommunity
);
6732 if (aggregate
->lcommunity_hash
) {
6733 /* Delete all lcommunities in the hash.
6735 hash_clean(aggregate
->lcommunity_hash
,
6736 bgp_aggr_lcommunity_remove
);
6737 /* Free up the lcommunity_hash.
6739 hash_free(aggregate
->lcommunity_hash
);
6742 if (aggregate
->aspath
)
6743 aspath_free(aggregate
->aspath
);
6745 if (aggregate
->aspath_hash
) {
6746 /* Delete all as-paths in the hash.
6748 hash_clean(aggregate
->aspath_hash
,
6749 bgp_aggr_aspath_remove
);
6750 /* Free up the aspath_hash.
6752 hash_free(aggregate
->aspath_hash
);
6755 bgp_aggregate_free(aggregate
);
6756 bgp_unlock_node(rn
);
6757 bgp_unlock_node(rn
);
6762 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6763 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6766 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6769 struct bgp_node
*rn
;
6770 struct bgp_aggregate
*aggregate
;
6771 uint8_t as_set_new
= as_set
;
6773 /* Convert string to prefix structure. */
6774 ret
= str2prefix(prefix_str
, &p
);
6776 vty_out(vty
, "Malformed prefix\n");
6777 return CMD_WARNING_CONFIG_FAILED
;
6781 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6782 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6783 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6785 return CMD_WARNING_CONFIG_FAILED
;
6788 /* Old configuration check. */
6789 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6790 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6793 vty_out(vty
, "There is already same aggregate network.\n");
6794 /* try to remove the old entry */
6795 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6797 vty_out(vty
, "Error deleting aggregate.\n");
6798 bgp_unlock_node(rn
);
6799 return CMD_WARNING_CONFIG_FAILED
;
6803 /* Make aggregate address structure. */
6804 aggregate
= bgp_aggregate_new();
6805 aggregate
->summary_only
= summary_only
;
6807 /* Network operators MUST NOT locally generate any new
6808 * announcements containing AS_SET or AS_CONFED_SET. If they have
6809 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6810 * SHOULD withdraw those routes and re-announce routes for the
6811 * aggregate or component prefixes (i.e., the more-specific routes
6812 * subsumed by the previously aggregated route) without AS_SET
6813 * or AS_CONFED_SET in the updates.
6815 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6816 if (as_set
== AGGREGATE_AS_SET
) {
6817 as_set_new
= AGGREGATE_AS_UNSET
;
6819 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6822 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6826 aggregate
->as_set
= as_set_new
;
6827 aggregate
->safi
= safi
;
6830 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6831 route_map_counter_decrement(aggregate
->rmap
.map
);
6832 aggregate
->rmap
.name
=
6833 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6834 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6835 route_map_counter_increment(aggregate
->rmap
.map
);
6837 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6839 /* Aggregate address insert into BGP routing table. */
6840 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6845 DEFUN (aggregate_address
,
6846 aggregate_address_cmd
,
6847 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6848 "Configure BGP aggregate entries\n"
6849 "Aggregate prefix\n"
6850 "Generate AS set path information\n"
6851 "Filter more specific routes from updates\n"
6852 "Filter more specific routes from updates\n"
6853 "Generate AS set path information\n"
6854 "Apply route map to aggregate network\n"
6855 "Name of route map\n")
6858 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6859 char *prefix
= argv
[idx
]->arg
;
6861 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6862 : AGGREGATE_AS_UNSET
;
6864 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6865 ? AGGREGATE_SUMMARY_ONLY
6869 argv_find(argv
, argc
, "WORD", &idx
);
6871 rmap
= argv
[idx
]->arg
;
6873 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6874 rmap
, summary_only
, as_set
);
6877 DEFUN (aggregate_address_mask
,
6878 aggregate_address_mask_cmd
,
6879 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6880 "Configure BGP aggregate entries\n"
6881 "Aggregate address\n"
6883 "Generate AS set path information\n"
6884 "Filter more specific routes from updates\n"
6885 "Filter more specific routes from updates\n"
6886 "Generate AS set path information\n"
6887 "Apply route map to aggregate network\n"
6888 "Name of route map\n")
6891 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6892 char *prefix
= argv
[idx
]->arg
;
6893 char *mask
= argv
[idx
+ 1]->arg
;
6896 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6897 : AGGREGATE_AS_UNSET
;
6899 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6900 ? AGGREGATE_SUMMARY_ONLY
6903 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6905 rmap
= argv
[idx
]->arg
;
6907 char prefix_str
[BUFSIZ
];
6908 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6911 vty_out(vty
, "%% Inconsistent address and mask\n");
6912 return CMD_WARNING_CONFIG_FAILED
;
6915 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6916 rmap
, summary_only
, as_set
);
6919 DEFUN (no_aggregate_address
,
6920 no_aggregate_address_cmd
,
6921 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6923 "Configure BGP aggregate entries\n"
6924 "Aggregate prefix\n"
6925 "Generate AS set path information\n"
6926 "Filter more specific routes from updates\n"
6927 "Filter more specific routes from updates\n"
6928 "Generate AS set path information\n"
6929 "Apply route map to aggregate network\n"
6930 "Name of route map\n")
6933 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6934 char *prefix
= argv
[idx
]->arg
;
6935 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6938 DEFUN (no_aggregate_address_mask
,
6939 no_aggregate_address_mask_cmd
,
6940 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6942 "Configure BGP aggregate entries\n"
6943 "Aggregate address\n"
6945 "Generate AS set path information\n"
6946 "Filter more specific routes from updates\n"
6947 "Filter more specific routes from updates\n"
6948 "Generate AS set path information\n"
6949 "Apply route map to aggregate network\n"
6950 "Name of route map\n")
6953 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6954 char *prefix
= argv
[idx
]->arg
;
6955 char *mask
= argv
[idx
+ 1]->arg
;
6957 char prefix_str
[BUFSIZ
];
6958 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6961 vty_out(vty
, "%% Inconsistent address and mask\n");
6962 return CMD_WARNING_CONFIG_FAILED
;
6965 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6968 DEFUN (ipv6_aggregate_address
,
6969 ipv6_aggregate_address_cmd
,
6970 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6971 "Configure BGP aggregate entries\n"
6972 "Aggregate prefix\n"
6973 "Generate AS set path information\n"
6974 "Filter more specific routes from updates\n"
6975 "Filter more specific routes from updates\n"
6976 "Generate AS set path information\n"
6977 "Apply route map to aggregate network\n"
6978 "Name of route map\n")
6981 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6982 char *prefix
= argv
[idx
]->arg
;
6985 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6986 : AGGREGATE_AS_UNSET
;
6989 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6990 ? AGGREGATE_SUMMARY_ONLY
6993 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6995 rmap
= argv
[idx
]->arg
;
6997 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
7001 DEFUN (no_ipv6_aggregate_address
,
7002 no_ipv6_aggregate_address_cmd
,
7003 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
7005 "Configure BGP aggregate entries\n"
7006 "Aggregate prefix\n"
7007 "Generate AS set path information\n"
7008 "Filter more specific routes from updates\n"
7009 "Filter more specific routes from updates\n"
7010 "Generate AS set path information\n"
7011 "Apply route map to aggregate network\n"
7012 "Name of route map\n")
7015 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7016 char *prefix
= argv
[idx
]->arg
;
7017 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7020 /* Redistribute route treatment. */
7021 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7022 const union g_addr
*nexthop
, ifindex_t ifindex
,
7023 enum nexthop_types_t nhtype
, uint32_t metric
,
7024 uint8_t type
, unsigned short instance
,
7027 struct bgp_path_info
*new;
7028 struct bgp_path_info
*bpi
;
7029 struct bgp_path_info rmap_path
;
7030 struct bgp_node
*bn
;
7032 struct attr
*new_attr
;
7034 route_map_result_t ret
;
7035 struct bgp_redist
*red
;
7037 /* Make default attribute. */
7038 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7040 * This must not be NULL to satisfy Coverity SA
7042 assert(attr
.aspath
);
7045 case NEXTHOP_TYPE_IFINDEX
:
7047 case NEXTHOP_TYPE_IPV4
:
7048 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7049 attr
.nexthop
= nexthop
->ipv4
;
7051 case NEXTHOP_TYPE_IPV6
:
7052 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7053 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7054 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7056 case NEXTHOP_TYPE_BLACKHOLE
:
7057 switch (p
->family
) {
7059 attr
.nexthop
.s_addr
= INADDR_ANY
;
7062 memset(&attr
.mp_nexthop_global
, 0,
7063 sizeof(attr
.mp_nexthop_global
));
7064 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7069 attr
.nh_ifindex
= ifindex
;
7072 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7075 afi
= family2afi(p
->family
);
7077 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7079 struct attr attr_new
;
7081 /* Copy attribute for modification. */
7084 if (red
->redist_metric_flag
)
7085 attr_new
.med
= red
->redist_metric
;
7087 /* Apply route-map. */
7088 if (red
->rmap
.name
) {
7089 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7090 rmap_path
.peer
= bgp
->peer_self
;
7091 rmap_path
.attr
= &attr_new
;
7093 SET_FLAG(bgp
->peer_self
->rmap_type
,
7094 PEER_RMAP_TYPE_REDISTRIBUTE
);
7096 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7099 bgp
->peer_self
->rmap_type
= 0;
7101 if (ret
== RMAP_DENYMATCH
) {
7102 /* Free uninterned attribute. */
7103 bgp_attr_flush(&attr_new
);
7105 /* Unintern original. */
7106 aspath_unintern(&attr
.aspath
);
7107 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7112 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7113 bgp_attr_add_gshut_community(&attr_new
);
7115 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7116 SAFI_UNICAST
, p
, NULL
);
7118 new_attr
= bgp_attr_intern(&attr_new
);
7120 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
7122 if (bpi
->peer
== bgp
->peer_self
7123 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7127 /* Ensure the (source route) type is updated. */
7129 if (attrhash_cmp(bpi
->attr
, new_attr
)
7130 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7131 bgp_attr_unintern(&new_attr
);
7132 aspath_unintern(&attr
.aspath
);
7133 bgp_unlock_node(bn
);
7136 /* The attribute is changed. */
7137 bgp_path_info_set_flag(bn
, bpi
,
7138 BGP_PATH_ATTR_CHANGED
);
7140 /* Rewrite BGP route information. */
7141 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7142 bgp_path_info_restore(bn
, bpi
);
7144 bgp_aggregate_decrement(
7145 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7146 bgp_attr_unintern(&bpi
->attr
);
7147 bpi
->attr
= new_attr
;
7148 bpi
->uptime
= bgp_clock();
7150 /* Process change. */
7151 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7153 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7154 bgp_unlock_node(bn
);
7155 aspath_unintern(&attr
.aspath
);
7157 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7159 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7161 vpn_leak_from_vrf_update(
7162 bgp_get_default(), bgp
, bpi
);
7168 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7169 bgp
->peer_self
, new_attr
, bn
);
7170 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7172 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7173 bgp_path_info_add(bn
, new);
7174 bgp_unlock_node(bn
);
7175 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7177 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7178 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7180 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7184 /* Unintern original. */
7185 aspath_unintern(&attr
.aspath
);
7188 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7189 unsigned short instance
)
7192 struct bgp_node
*rn
;
7193 struct bgp_path_info
*pi
;
7194 struct bgp_redist
*red
;
7196 afi
= family2afi(p
->family
);
7198 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7200 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7201 SAFI_UNICAST
, p
, NULL
);
7203 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7204 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7208 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7209 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7211 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7214 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7215 bgp_path_info_delete(rn
, pi
);
7216 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7218 bgp_unlock_node(rn
);
7222 /* Withdraw specified route type's route. */
7223 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7224 unsigned short instance
)
7226 struct bgp_node
*rn
;
7227 struct bgp_path_info
*pi
;
7228 struct bgp_table
*table
;
7230 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7232 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7233 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7234 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7235 && pi
->instance
== instance
)
7239 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7240 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7242 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7245 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7247 bgp_path_info_delete(rn
, pi
);
7248 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7253 /* Static function to display route. */
7254 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7261 if (p
->family
== AF_INET
) {
7265 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7268 json_object_string_add(json
, "prefix",
7269 inet_ntop(p
->family
,
7272 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7273 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7274 json_object_string_add(json
, "network", buf2
);
7276 } else if (p
->family
== AF_ETHERNET
) {
7277 prefix2str(p
, buf
, PREFIX_STRLEN
);
7278 len
= vty_out(vty
, "%s", buf
);
7279 } else if (p
->family
== AF_EVPN
) {
7283 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7286 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7287 } else if (p
->family
== AF_FLOWSPEC
) {
7288 route_vty_out_flowspec(vty
, p
, NULL
,
7290 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7291 NLRI_STRING_FORMAT_MIN
, json
);
7296 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7299 json_object_string_add(json
, "prefix",
7300 inet_ntop(p
->family
,
7303 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7304 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7305 json_object_string_add(json
, "network", buf2
);
7312 vty_out(vty
, "\n%*s", 20, " ");
7314 vty_out(vty
, "%*s", len
, " ");
7318 enum bgp_display_type
{
7322 /* Print the short form route status for a bgp_path_info */
7323 static void route_vty_short_status_out(struct vty
*vty
,
7324 struct bgp_path_info
*path
,
7325 json_object
*json_path
)
7329 /* Route status display. */
7330 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7331 json_object_boolean_true_add(json_path
, "removed");
7333 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7334 json_object_boolean_true_add(json_path
, "stale");
7336 if (path
->extra
&& path
->extra
->suppress
)
7337 json_object_boolean_true_add(json_path
, "suppressed");
7339 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7340 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7341 json_object_boolean_true_add(json_path
, "valid");
7344 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7345 json_object_boolean_true_add(json_path
, "history");
7347 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7348 json_object_boolean_true_add(json_path
, "damped");
7350 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7351 json_object_boolean_true_add(json_path
, "bestpath");
7353 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7354 json_object_boolean_true_add(json_path
, "multipath");
7356 /* Internal route. */
7357 if ((path
->peer
->as
)
7358 && (path
->peer
->as
== path
->peer
->local_as
))
7359 json_object_string_add(json_path
, "pathFrom",
7362 json_object_string_add(json_path
, "pathFrom",
7368 /* Route status display. */
7369 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7371 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7373 else if (path
->extra
&& path
->extra
->suppress
)
7375 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7376 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7382 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7384 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7386 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7388 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7393 /* Internal route. */
7394 if (path
->peer
&& (path
->peer
->as
)
7395 && (path
->peer
->as
== path
->peer
->local_as
))
7401 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7403 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7404 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7405 return peer
->hostname
;
7409 /* called from terminal list command */
7410 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7411 struct bgp_path_info
*path
, int display
, safi_t safi
,
7412 json_object
*json_paths
)
7414 struct attr
*attr
= path
->attr
;
7415 json_object
*json_path
= NULL
;
7416 json_object
*json_nexthops
= NULL
;
7417 json_object
*json_nexthop_global
= NULL
;
7418 json_object
*json_nexthop_ll
= NULL
;
7419 json_object
*json_ext_community
= NULL
;
7420 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7422 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7423 bool nexthop_othervrf
= false;
7424 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7425 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7426 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7429 json_path
= json_object_new_object();
7431 /* short status lead text */
7432 route_vty_short_status_out(vty
, path
, json_path
);
7435 /* print prefix and mask */
7437 route_vty_out_route(p
, vty
, json_path
);
7439 vty_out(vty
, "%*s", 17, " ");
7441 route_vty_out_route(p
, vty
, json_path
);
7445 * If vrf id of nexthop is different from that of prefix,
7446 * set up printable string to append
7448 if (path
->extra
&& path
->extra
->bgp_orig
) {
7449 const char *self
= "";
7454 nexthop_othervrf
= true;
7455 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7457 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7458 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7459 "@%s%s", VRFID_NONE_STR
, self
);
7461 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7462 path
->extra
->bgp_orig
->vrf_id
, self
);
7464 if (path
->extra
->bgp_orig
->inst_type
7465 != BGP_INSTANCE_TYPE_DEFAULT
)
7467 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7469 const char *self
= "";
7474 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7478 * For ENCAP and EVPN routes, nexthop address family is not
7479 * neccessarily the same as the prefix address family.
7480 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7481 * EVPN routes are also exchanged with a MP nexthop. Currently,
7483 * is only IPv4, the value will be present in either
7485 * attr->mp_nexthop_global_in
7487 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7490 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7494 sprintf(nexthop
, "%s",
7495 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7499 sprintf(nexthop
, "%s",
7500 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7504 sprintf(nexthop
, "?");
7509 json_nexthop_global
= json_object_new_object();
7511 json_object_string_add(json_nexthop_global
, "ip",
7514 if (nexthop_hostname
)
7515 json_object_string_add(json_nexthop_global
,
7519 json_object_string_add(json_nexthop_global
, "afi",
7520 (af
== AF_INET
) ? "ipv4"
7522 json_object_boolean_true_add(json_nexthop_global
,
7525 vty_out(vty
, "%s%s",
7526 nexthop_hostname
? nexthop_hostname
: nexthop
,
7528 } else if (safi
== SAFI_EVPN
) {
7530 json_nexthop_global
= json_object_new_object();
7532 json_object_string_add(json_nexthop_global
, "ip",
7533 inet_ntoa(attr
->nexthop
));
7535 if (nexthop_hostname
)
7536 json_object_string_add(json_nexthop_global
,
7540 json_object_string_add(json_nexthop_global
, "afi",
7542 json_object_boolean_true_add(json_nexthop_global
,
7545 vty_out(vty
, "%-16s%s",
7546 nexthop_hostname
? nexthop_hostname
7547 : inet_ntoa(attr
->nexthop
),
7549 } else if (safi
== SAFI_FLOWSPEC
) {
7550 if (attr
->nexthop
.s_addr
!= 0) {
7552 json_nexthop_global
= json_object_new_object();
7554 json_object_string_add(json_nexthop_global
,
7556 json_object_string_add(
7557 json_nexthop_global
, "ip",
7558 inet_ntoa(attr
->nexthop
));
7560 if (nexthop_hostname
)
7561 json_object_string_add(
7562 json_nexthop_global
, "hostname",
7565 json_object_boolean_true_add(
7566 json_nexthop_global
,
7569 vty_out(vty
, "%-16s",
7572 : inet_ntoa(attr
->nexthop
));
7575 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7577 json_nexthop_global
= json_object_new_object();
7579 json_object_string_add(json_nexthop_global
, "ip",
7580 inet_ntoa(attr
->nexthop
));
7582 if (nexthop_hostname
)
7583 json_object_string_add(json_nexthop_global
,
7587 json_object_string_add(json_nexthop_global
, "afi",
7589 json_object_boolean_true_add(json_nexthop_global
,
7594 snprintf(buf
, sizeof(buf
), "%s%s",
7595 nexthop_hostname
? nexthop_hostname
7596 : inet_ntoa(attr
->nexthop
),
7598 vty_out(vty
, "%-16s", buf
);
7603 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7608 json_nexthop_global
= json_object_new_object();
7609 json_object_string_add(
7610 json_nexthop_global
, "ip",
7611 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7614 if (nexthop_hostname
)
7615 json_object_string_add(json_nexthop_global
,
7619 json_object_string_add(json_nexthop_global
, "afi",
7621 json_object_string_add(json_nexthop_global
, "scope",
7624 /* We display both LL & GL if both have been
7626 if ((attr
->mp_nexthop_len
7627 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7628 || (path
->peer
->conf_if
)) {
7629 json_nexthop_ll
= json_object_new_object();
7630 json_object_string_add(
7631 json_nexthop_ll
, "ip",
7633 &attr
->mp_nexthop_local
, buf
,
7636 if (nexthop_hostname
)
7637 json_object_string_add(
7638 json_nexthop_ll
, "hostname",
7641 json_object_string_add(json_nexthop_ll
, "afi",
7643 json_object_string_add(json_nexthop_ll
, "scope",
7646 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7647 &attr
->mp_nexthop_local
)
7649 && !attr
->mp_nexthop_prefer_global
)
7650 json_object_boolean_true_add(
7651 json_nexthop_ll
, "used");
7653 json_object_boolean_true_add(
7654 json_nexthop_global
, "used");
7656 json_object_boolean_true_add(
7657 json_nexthop_global
, "used");
7659 /* Display LL if LL/Global both in table unless
7660 * prefer-global is set */
7661 if (((attr
->mp_nexthop_len
7662 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7663 && !attr
->mp_nexthop_prefer_global
)
7664 || (path
->peer
->conf_if
)) {
7665 if (path
->peer
->conf_if
) {
7666 len
= vty_out(vty
, "%s",
7667 path
->peer
->conf_if
);
7668 len
= 16 - len
; /* len of IPv6
7674 vty_out(vty
, "\n%*s", 36, " ");
7676 vty_out(vty
, "%*s", len
, " ");
7684 &attr
->mp_nexthop_local
,
7690 vty_out(vty
, "\n%*s", 36, " ");
7692 vty_out(vty
, "%*s", len
, " ");
7701 &attr
->mp_nexthop_global
,
7707 vty_out(vty
, "\n%*s", 36, " ");
7709 vty_out(vty
, "%*s", len
, " ");
7715 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7719 * Adding "metric" field to match with corresponding
7720 * CLI. "med" will be deprecated in future.
7722 json_object_int_add(json_path
, "med", attr
->med
);
7723 json_object_int_add(json_path
, "metric", attr
->med
);
7725 vty_out(vty
, "%10u", attr
->med
);
7726 else if (!json_paths
)
7730 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7734 * Adding "locPrf" field to match with corresponding
7735 * CLI. "localPref" will be deprecated in future.
7737 json_object_int_add(json_path
, "localpref",
7739 json_object_int_add(json_path
, "locPrf",
7742 vty_out(vty
, "%7u", attr
->local_pref
);
7743 else if (!json_paths
)
7747 json_object_int_add(json_path
, "weight", attr
->weight
);
7749 vty_out(vty
, "%7u ", attr
->weight
);
7753 json_object_string_add(
7754 json_path
, "peerId",
7755 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7763 * Adding "path" field to match with corresponding
7764 * CLI. "aspath" will be deprecated in future.
7766 json_object_string_add(json_path
, "aspath",
7768 json_object_string_add(json_path
, "path",
7771 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7776 json_object_string_add(json_path
, "origin",
7777 bgp_origin_long_str
[attr
->origin
]);
7779 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7782 if (safi
== SAFI_EVPN
&&
7783 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7784 json_ext_community
= json_object_new_object();
7785 json_object_string_add(json_ext_community
,
7787 attr
->ecommunity
->str
);
7788 json_object_object_add(json_path
,
7789 "extendedCommunity",
7790 json_ext_community
);
7794 json_object_boolean_true_add(json_path
,
7795 "announceNexthopSelf");
7796 if (nexthop_othervrf
) {
7797 json_object_string_add(json_path
, "nhVrfName",
7800 json_object_int_add(json_path
, "nhVrfId",
7801 ((nexthop_vrfid
== VRF_UNKNOWN
)
7803 : (int)nexthop_vrfid
));
7808 if (json_nexthop_global
|| json_nexthop_ll
) {
7809 json_nexthops
= json_object_new_array();
7811 if (json_nexthop_global
)
7812 json_object_array_add(json_nexthops
,
7813 json_nexthop_global
);
7815 if (json_nexthop_ll
)
7816 json_object_array_add(json_nexthops
,
7819 json_object_object_add(json_path
, "nexthops",
7823 json_object_array_add(json_paths
, json_path
);
7827 if (safi
== SAFI_EVPN
&&
7828 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7829 vty_out(vty
, "%*s", 20, " ");
7830 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7834 /* prints an additional line, indented, with VNC info, if
7836 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7837 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7842 /* called from terminal list command */
7843 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7844 safi_t safi
, bool use_json
, json_object
*json_ar
)
7846 json_object
*json_status
= NULL
;
7847 json_object
*json_net
= NULL
;
7850 /* Route status display. */
7852 json_status
= json_object_new_object();
7853 json_net
= json_object_new_object();
7860 /* print prefix and mask */
7862 if (safi
== SAFI_EVPN
)
7863 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7864 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7865 json_object_string_add(
7866 json_net
, "addrPrefix",
7867 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7869 json_object_int_add(json_net
, "prefixLen",
7871 prefix2str(p
, buff
, PREFIX_STRLEN
);
7872 json_object_string_add(json_net
, "network", buff
);
7875 route_vty_out_route(p
, vty
, NULL
);
7877 /* Print attribute */
7880 if (p
->family
== AF_INET
7881 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7882 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7883 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7884 json_object_string_add(
7885 json_net
, "nextHop",
7887 attr
->mp_nexthop_global_in
));
7889 json_object_string_add(
7890 json_net
, "nextHop",
7891 inet_ntoa(attr
->nexthop
));
7892 } else if (p
->family
== AF_INET6
7893 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7896 json_object_string_add(
7897 json_net
, "nextHopGlobal",
7899 &attr
->mp_nexthop_global
, buf
,
7901 } else if (p
->family
== AF_EVPN
&&
7902 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7903 json_object_string_add(json_net
,
7904 "nextHop", inet_ntoa(
7905 attr
->mp_nexthop_global_in
));
7908 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7909 json_object_int_add(json_net
, "metric",
7912 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7915 * Adding "locPrf" field to match with
7916 * corresponding CLI. "localPref" will be
7917 * deprecated in future.
7919 json_object_int_add(json_net
, "localPref",
7921 json_object_int_add(json_net
, "locPrf",
7925 json_object_int_add(json_net
, "weight", attr
->weight
);
7931 * Adding "path" field to match with
7932 * corresponding CLI. "localPref" will be
7933 * deprecated in future.
7935 json_object_string_add(json_net
, "asPath",
7937 json_object_string_add(json_net
, "path",
7942 json_object_string_add(json_net
, "bgpOriginCode",
7943 bgp_origin_str
[attr
->origin
]);
7945 if (p
->family
== AF_INET
7946 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7947 || safi
== SAFI_EVPN
7948 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7949 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7950 || safi
== SAFI_EVPN
)
7951 vty_out(vty
, "%-16s",
7953 attr
->mp_nexthop_global_in
));
7955 vty_out(vty
, "%-16s",
7956 inet_ntoa(attr
->nexthop
));
7957 } else if (p
->family
== AF_INET6
7958 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7965 &attr
->mp_nexthop_global
, buf
,
7969 vty_out(vty
, "\n%*s", 36, " ");
7971 vty_out(vty
, "%*s", len
, " ");
7974 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7975 vty_out(vty
, "%10u", attr
->med
);
7979 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7980 vty_out(vty
, "%7u", attr
->local_pref
);
7984 vty_out(vty
, "%7u ", attr
->weight
);
7988 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7991 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7995 json_object_boolean_true_add(json_status
, "*");
7996 json_object_boolean_true_add(json_status
, ">");
7997 json_object_object_add(json_net
, "appliedStatusSymbols",
8000 prefix2str(p
, buff
, PREFIX_STRLEN
);
8001 json_object_object_add(json_ar
, buff
, json_net
);
8006 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
8007 struct bgp_path_info
*path
, int display
, safi_t safi
,
8010 json_object
*json_out
= NULL
;
8012 mpls_label_t label
= MPLS_INVALID_LABEL
;
8018 json_out
= json_object_new_object();
8020 /* short status lead text */
8021 route_vty_short_status_out(vty
, path
, json_out
);
8023 /* print prefix and mask */
8026 route_vty_out_route(p
, vty
, NULL
);
8028 vty_out(vty
, "%*s", 17, " ");
8031 /* Print attribute */
8033 if (((p
->family
== AF_INET
)
8034 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8035 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8036 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8037 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8038 || safi
== SAFI_EVPN
) {
8040 json_object_string_add(
8041 json_out
, "mpNexthopGlobalIn",
8042 inet_ntoa(attr
->mp_nexthop_global_in
));
8044 vty_out(vty
, "%-16s",
8045 inet_ntoa(attr
->mp_nexthop_global_in
));
8048 json_object_string_add(
8049 json_out
, "nexthop",
8050 inet_ntoa(attr
->nexthop
));
8052 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8054 } else if (((p
->family
== AF_INET6
)
8055 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8056 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8057 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8060 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8062 json_object_string_add(
8063 json_out
, "mpNexthopGlobalIn",
8065 &attr
->mp_nexthop_global
,
8066 buf_a
, sizeof(buf_a
)));
8070 &attr
->mp_nexthop_global
,
8071 buf_a
, sizeof(buf_a
)));
8072 } else if (attr
->mp_nexthop_len
8073 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8074 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8075 &attr
->mp_nexthop_global
,
8076 &attr
->mp_nexthop_local
);
8078 json_object_string_add(json_out
,
8079 "mpNexthopGlobalLocal",
8082 vty_out(vty
, "%s", buf_a
);
8086 label
= decode_label(&path
->extra
->label
[0]);
8088 if (bgp_is_valid_label(&label
)) {
8090 json_object_int_add(json_out
, "notag", label
);
8091 json_object_array_add(json
, json_out
);
8093 vty_out(vty
, "notag/%d", label
);
8099 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
8100 struct bgp_path_info
*path
, int display
,
8101 json_object
*json_paths
)
8104 char buf
[BUFSIZ
] = {0};
8105 json_object
*json_path
= NULL
;
8106 json_object
*json_nexthop
= NULL
;
8107 json_object
*json_overlay
= NULL
;
8113 json_path
= json_object_new_object();
8114 json_overlay
= json_object_new_object();
8115 json_nexthop
= json_object_new_object();
8118 /* short status lead text */
8119 route_vty_short_status_out(vty
, path
, json_path
);
8121 /* print prefix and mask */
8123 route_vty_out_route(p
, vty
, json_path
);
8125 vty_out(vty
, "%*s", 17, " ");
8127 /* Print attribute */
8130 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8134 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8136 vty_out(vty
, "%-16s", buf
);
8138 json_object_string_add(json_nexthop
, "ip", buf
);
8140 json_object_string_add(json_nexthop
, "afi", "ipv4");
8142 json_object_object_add(json_path
, "nexthop",
8147 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8148 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8150 vty_out(vty
, "%s(%s)", buf
, buf1
);
8152 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8154 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8157 json_object_string_add(json_nexthop
, "afi", "ipv6");
8159 json_object_object_add(json_path
, "nexthop",
8167 json_object_string_add(json_nexthop
, "Error",
8168 "Unsupported address-family");
8172 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
8175 vty_out(vty
, "%s", str
);
8177 json_object_string_add(json_overlay
, "esi", str
);
8179 XFREE(MTYPE_TMP
, str
);
8181 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8182 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8184 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8185 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8190 vty_out(vty
, "/%s", buf
);
8192 json_object_string_add(json_overlay
, "gw", buf
);
8194 if (attr
->ecommunity
) {
8196 struct ecommunity_val
*routermac
= ecommunity_lookup(
8197 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8198 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8201 mac
= ecom_mac2str((char *)routermac
->val
);
8204 vty_out(vty
, "/%s", (char *)mac
);
8206 json_object_string_add(json_overlay
, "rmac",
8209 XFREE(MTYPE_TMP
, mac
);
8216 json_object_object_add(json_path
, "overlay", json_overlay
);
8218 json_object_array_add(json_paths
, json_path
);
8222 /* dampening route */
8223 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8224 struct bgp_path_info
*path
, int display
, afi_t afi
,
8225 safi_t safi
, bool use_json
, json_object
*json
)
8229 char timebuf
[BGP_UPTIME_LEN
];
8231 /* short status lead text */
8232 route_vty_short_status_out(vty
, path
, json
);
8234 /* print prefix and mask */
8237 route_vty_out_route(p
, vty
, NULL
);
8239 vty_out(vty
, "%*s", 17, " ");
8242 len
= vty_out(vty
, "%s", path
->peer
->host
);
8246 vty_out(vty
, "\n%*s", 34, " ");
8249 json_object_int_add(json
, "peerHost", len
);
8251 vty_out(vty
, "%*s", len
, " ");
8255 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8256 safi
, use_json
, json
);
8259 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8260 BGP_UPTIME_LEN
, afi
, safi
,
8263 /* Print attribute */
8269 json_object_string_add(json
, "asPath",
8272 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8277 json_object_string_add(json
, "origin",
8278 bgp_origin_str
[attr
->origin
]);
8280 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8287 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8288 struct bgp_path_info
*path
, int display
, afi_t afi
,
8289 safi_t safi
, bool use_json
, json_object
*json
)
8292 struct bgp_damp_info
*bdi
;
8293 char timebuf
[BGP_UPTIME_LEN
];
8299 bdi
= path
->extra
->damp_info
;
8301 /* short status lead text */
8302 route_vty_short_status_out(vty
, path
, json
);
8304 /* print prefix and mask */
8307 route_vty_out_route(p
, vty
, NULL
);
8309 vty_out(vty
, "%*s", 17, " ");
8312 len
= vty_out(vty
, "%s", path
->peer
->host
);
8316 vty_out(vty
, "\n%*s", 33, " ");
8319 json_object_int_add(json
, "peerHost", len
);
8321 vty_out(vty
, "%*s", len
, " ");
8324 len
= vty_out(vty
, "%d", bdi
->flap
);
8331 json_object_int_add(json
, "bdiFlap", len
);
8333 vty_out(vty
, "%*s", len
, " ");
8337 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8340 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8341 BGP_UPTIME_LEN
, 0, NULL
));
8343 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8344 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8346 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8347 BGP_UPTIME_LEN
, afi
, safi
,
8351 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8352 BGP_UPTIME_LEN
, afi
,
8353 safi
, use_json
, json
));
8356 vty_out(vty
, "%*s ", 8, " ");
8359 /* Print attribute */
8365 json_object_string_add(json
, "asPath",
8368 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8373 json_object_string_add(json
, "origin",
8374 bgp_origin_str
[attr
->origin
]);
8376 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8382 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8383 int *first
, const char *header
,
8384 json_object
*json_adv_to
)
8386 char buf1
[INET6_ADDRSTRLEN
];
8387 json_object
*json_peer
= NULL
;
8390 /* 'advertised-to' is a dictionary of peers we have advertised
8392 * prefix too. The key is the peer's IP or swpX, the value is
8394 * hostname if we know it and "" if not.
8396 json_peer
= json_object_new_object();
8399 json_object_string_add(json_peer
, "hostname",
8403 json_object_object_add(json_adv_to
, peer
->conf_if
,
8406 json_object_object_add(
8408 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8412 vty_out(vty
, "%s", header
);
8417 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8419 vty_out(vty
, " %s(%s)", peer
->hostname
,
8422 vty_out(vty
, " %s(%s)", peer
->hostname
,
8423 sockunion2str(&peer
->su
, buf1
,
8427 vty_out(vty
, " %s", peer
->conf_if
);
8430 sockunion2str(&peer
->su
, buf1
,
8436 static void route_vty_out_tx_ids(struct vty
*vty
,
8437 struct bgp_addpath_info_data
*d
)
8441 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8442 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8443 d
->addpath_tx_id
[i
],
8444 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8448 static const char *bgp_path_selection_reason2str(
8449 enum bgp_path_selection_reason reason
)
8452 case bgp_path_selection_none
:
8453 return "Nothing to Select";
8455 case bgp_path_selection_first
:
8456 return "First path received";
8458 case bgp_path_selection_evpn_sticky_mac
:
8459 return "EVPN Sticky Mac";
8461 case bgp_path_selection_evpn_seq
:
8462 return "EVPN sequence number";
8464 case bgp_path_selection_evpn_lower_ip
:
8465 return "EVPN lower IP";
8467 case bgp_path_selection_weight
:
8470 case bgp_path_selection_local_pref
:
8471 return "Local Pref";
8473 case bgp_path_selection_local_route
:
8474 return "Local Route";
8476 case bgp_path_selection_confed_as_path
:
8477 return "Confederation based AS Path";
8479 case bgp_path_selection_as_path
:
8482 case bgp_path_selection_origin
:
8485 case bgp_path_selection_med
:
8488 case bgp_path_selection_peer
:
8491 case bgp_path_selection_confed
:
8492 return "Confed Peer Type";
8494 case bgp_path_selection_igp_metric
:
8495 return "IGP Metric";
8497 case bgp_path_selection_older
:
8498 return "Older Path";
8500 case bgp_path_selection_router_id
:
8503 case bgp_path_selection_cluster_length
:
8504 return "Cluser length";
8506 case bgp_path_selection_stale
:
8507 return "Path Staleness";
8509 case bgp_path_selection_local_configured
:
8510 return "Locally configured route";
8512 case bgp_path_selection_neighbor_ip
:
8513 return "Neighbor IP";
8515 case bgp_path_selection_default
:
8516 return "Nothing left to compare";
8519 return "Invalid (internal error)";
8522 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8523 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8524 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8526 char buf
[INET6_ADDRSTRLEN
];
8528 char buf2
[EVPN_ROUTE_STRLEN
];
8529 struct attr
*attr
= path
->attr
;
8530 int sockunion_vty_out(struct vty
*, union sockunion
*);
8532 json_object
*json_bestpath
= NULL
;
8533 json_object
*json_cluster_list
= NULL
;
8534 json_object
*json_cluster_list_list
= NULL
;
8535 json_object
*json_ext_community
= NULL
;
8536 json_object
*json_last_update
= NULL
;
8537 json_object
*json_pmsi
= NULL
;
8538 json_object
*json_nexthop_global
= NULL
;
8539 json_object
*json_nexthop_ll
= NULL
;
8540 json_object
*json_nexthops
= NULL
;
8541 json_object
*json_path
= NULL
;
8542 json_object
*json_peer
= NULL
;
8543 json_object
*json_string
= NULL
;
8544 json_object
*json_adv_to
= NULL
;
8546 struct listnode
*node
, *nnode
;
8548 int addpath_capable
;
8550 unsigned int first_as
;
8552 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8554 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8557 json_path
= json_object_new_object();
8558 json_peer
= json_object_new_object();
8559 json_nexthop_global
= json_object_new_object();
8567 if (path
->extra
&& path
->extra
->num_labels
) {
8568 bgp_evpn_label2str(path
->extra
->label
,
8569 path
->extra
->num_labels
, tag_buf
,
8572 if (safi
== SAFI_EVPN
) {
8574 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8575 buf2
, sizeof(buf2
));
8576 vty_out(vty
, " Route %s", buf2
);
8577 if (tag_buf
[0] != '\0')
8578 vty_out(vty
, " VNI %s", tag_buf
);
8582 json_object_string_add(json_path
, "VNI",
8587 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8588 struct bgp_path_info
*parent_ri
;
8589 struct bgp_node
*rn
, *prn
;
8591 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8592 rn
= parent_ri
->net
;
8593 if (rn
&& rn
->prn
) {
8595 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8596 buf1
, sizeof(buf1
));
8597 if (is_pi_family_evpn(parent_ri
)) {
8598 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8599 buf2
, sizeof(buf2
));
8600 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8602 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8607 /* Line1 display AS-path, Aggregator */
8610 if (!attr
->aspath
->json
)
8611 aspath_str_update(attr
->aspath
, true);
8612 json_object_lock(attr
->aspath
->json
);
8613 json_object_object_add(json_path
, "aspath",
8614 attr
->aspath
->json
);
8616 if (attr
->aspath
->segments
)
8617 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8619 vty_out(vty
, " Local");
8623 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8625 json_object_boolean_true_add(json_path
, "removed");
8627 vty_out(vty
, ", (removed)");
8630 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8632 json_object_boolean_true_add(json_path
, "stale");
8634 vty_out(vty
, ", (stale)");
8637 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8639 json_object_int_add(json_path
, "aggregatorAs",
8640 attr
->aggregator_as
);
8641 json_object_string_add(
8642 json_path
, "aggregatorId",
8643 inet_ntoa(attr
->aggregator_addr
));
8645 vty_out(vty
, ", (aggregated by %u %s)",
8646 attr
->aggregator_as
,
8647 inet_ntoa(attr
->aggregator_addr
));
8651 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8652 PEER_FLAG_REFLECTOR_CLIENT
)) {
8654 json_object_boolean_true_add(json_path
,
8655 "rxedFromRrClient");
8657 vty_out(vty
, ", (Received from a RR-client)");
8660 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8661 PEER_FLAG_RSERVER_CLIENT
)) {
8663 json_object_boolean_true_add(json_path
,
8664 "rxedFromRsClient");
8666 vty_out(vty
, ", (Received from a RS-client)");
8669 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8671 json_object_boolean_true_add(json_path
,
8672 "dampeningHistoryEntry");
8674 vty_out(vty
, ", (history entry)");
8675 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8677 json_object_boolean_true_add(json_path
,
8678 "dampeningSuppressed");
8680 vty_out(vty
, ", (suppressed due to dampening)");
8686 /* Line2 display Next-hop, Neighbor, Router-id */
8687 /* Display the nexthop */
8688 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8689 || bn
->p
.family
== AF_EVPN
)
8690 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8691 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8692 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8693 || safi
== SAFI_EVPN
) {
8695 json_object_string_add(
8696 json_nexthop_global
, "ip",
8697 inet_ntoa(attr
->mp_nexthop_global_in
));
8699 if (nexthop_hostname
)
8700 json_object_string_add(
8701 json_nexthop_global
, "hostname",
8708 attr
->mp_nexthop_global_in
));
8711 json_object_string_add(
8712 json_nexthop_global
, "ip",
8713 inet_ntoa(attr
->nexthop
));
8715 if (nexthop_hostname
)
8716 json_object_string_add(
8717 json_nexthop_global
, "hostname",
8723 : inet_ntoa(attr
->nexthop
));
8727 json_object_string_add(json_nexthop_global
, "afi",
8731 json_object_string_add(
8732 json_nexthop_global
, "ip",
8733 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8734 buf
, INET6_ADDRSTRLEN
));
8736 if (nexthop_hostname
)
8737 json_object_string_add(json_nexthop_global
,
8741 json_object_string_add(json_nexthop_global
, "afi",
8743 json_object_string_add(json_nexthop_global
, "scope",
8749 : inet_ntop(AF_INET6
,
8750 &attr
->mp_nexthop_global
,
8751 buf
, INET6_ADDRSTRLEN
));
8755 /* Display the IGP cost or 'inaccessible' */
8756 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8758 json_object_boolean_false_add(json_nexthop_global
,
8761 vty_out(vty
, " (inaccessible)");
8763 if (path
->extra
&& path
->extra
->igpmetric
) {
8765 json_object_int_add(json_nexthop_global
,
8767 path
->extra
->igpmetric
);
8769 vty_out(vty
, " (metric %u)",
8770 path
->extra
->igpmetric
);
8773 /* IGP cost is 0, display this only for json */
8776 json_object_int_add(json_nexthop_global
,
8781 json_object_boolean_true_add(json_nexthop_global
,
8785 /* Display peer "from" output */
8786 /* This path was originated locally */
8787 if (path
->peer
== bgp
->peer_self
) {
8789 if (safi
== SAFI_EVPN
8790 || (bn
->p
.family
== AF_INET
8791 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8793 json_object_string_add(json_peer
, "peerId",
8796 vty_out(vty
, " from 0.0.0.0 ");
8799 json_object_string_add(json_peer
, "peerId",
8802 vty_out(vty
, " from :: ");
8806 json_object_string_add(json_peer
, "routerId",
8807 inet_ntoa(bgp
->router_id
));
8809 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8812 /* We RXed this path from one of our peers */
8816 json_object_string_add(json_peer
, "peerId",
8817 sockunion2str(&path
->peer
->su
,
8820 json_object_string_add(json_peer
, "routerId",
8822 &path
->peer
->remote_id
,
8823 buf1
, sizeof(buf1
)));
8825 if (path
->peer
->hostname
)
8826 json_object_string_add(json_peer
, "hostname",
8827 path
->peer
->hostname
);
8829 if (path
->peer
->domainname
)
8830 json_object_string_add(json_peer
, "domainname",
8831 path
->peer
->domainname
);
8833 if (path
->peer
->conf_if
)
8834 json_object_string_add(json_peer
, "interface",
8835 path
->peer
->conf_if
);
8837 if (path
->peer
->conf_if
) {
8838 if (path
->peer
->hostname
8839 && bgp_flag_check(path
->peer
->bgp
,
8840 BGP_FLAG_SHOW_HOSTNAME
))
8841 vty_out(vty
, " from %s(%s)",
8842 path
->peer
->hostname
,
8843 path
->peer
->conf_if
);
8845 vty_out(vty
, " from %s",
8846 path
->peer
->conf_if
);
8848 if (path
->peer
->hostname
8849 && bgp_flag_check(path
->peer
->bgp
,
8850 BGP_FLAG_SHOW_HOSTNAME
))
8851 vty_out(vty
, " from %s(%s)",
8852 path
->peer
->hostname
,
8855 vty_out(vty
, " from %s",
8856 sockunion2str(&path
->peer
->su
,
8861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8862 vty_out(vty
, " (%s)",
8863 inet_ntoa(attr
->originator_id
));
8865 vty_out(vty
, " (%s)",
8867 &path
->peer
->remote_id
, buf1
,
8873 * Note when vrfid of nexthop is different from that of prefix
8875 if (path
->extra
&& path
->extra
->bgp_orig
) {
8876 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8881 if (path
->extra
->bgp_orig
->inst_type
8882 == BGP_INSTANCE_TYPE_DEFAULT
)
8883 vn
= VRF_DEFAULT_NAME
;
8885 vn
= path
->extra
->bgp_orig
->name
;
8887 json_object_string_add(json_path
, "nhVrfName", vn
);
8889 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8890 json_object_int_add(json_path
, "nhVrfId", -1);
8892 json_object_int_add(json_path
, "nhVrfId",
8893 (int)nexthop_vrfid
);
8896 if (nexthop_vrfid
== VRF_UNKNOWN
)
8897 vty_out(vty
, " vrf ?");
8899 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8905 json_object_boolean_true_add(json_path
,
8906 "announceNexthopSelf");
8908 vty_out(vty
, " announce-nh-self");
8915 /* display the link-local nexthop */
8916 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8918 json_nexthop_ll
= json_object_new_object();
8919 json_object_string_add(
8920 json_nexthop_ll
, "ip",
8921 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8922 buf
, INET6_ADDRSTRLEN
));
8924 if (nexthop_hostname
)
8925 json_object_string_add(json_nexthop_ll
,
8929 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8930 json_object_string_add(json_nexthop_ll
, "scope",
8933 json_object_boolean_true_add(json_nexthop_ll
,
8936 if (!attr
->mp_nexthop_prefer_global
)
8937 json_object_boolean_true_add(json_nexthop_ll
,
8940 json_object_boolean_true_add(
8941 json_nexthop_global
, "used");
8943 vty_out(vty
, " (%s) %s\n",
8944 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8945 buf
, INET6_ADDRSTRLEN
),
8946 attr
->mp_nexthop_prefer_global
8951 /* If we do not have a link-local nexthop then we must flag the
8955 json_object_boolean_true_add(json_nexthop_global
,
8959 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8960 * Int/Ext/Local, Atomic, best */
8962 json_object_string_add(json_path
, "origin",
8963 bgp_origin_long_str
[attr
->origin
]);
8965 vty_out(vty
, " Origin %s",
8966 bgp_origin_long_str
[attr
->origin
]);
8968 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8971 * Adding "metric" field to match with
8972 * corresponding CLI. "med" will be
8973 * deprecated in future.
8975 json_object_int_add(json_path
, "med", attr
->med
);
8976 json_object_int_add(json_path
, "metric", attr
->med
);
8978 vty_out(vty
, ", metric %u", attr
->med
);
8981 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8983 json_object_int_add(json_path
, "localpref",
8986 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8989 if (attr
->weight
!= 0) {
8991 json_object_int_add(json_path
, "weight", attr
->weight
);
8993 vty_out(vty
, ", weight %u", attr
->weight
);
8996 if (attr
->tag
!= 0) {
8998 json_object_int_add(json_path
, "tag", attr
->tag
);
9000 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
9003 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
9005 json_object_boolean_false_add(json_path
, "valid");
9007 vty_out(vty
, ", invalid");
9008 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
9010 json_object_boolean_true_add(json_path
, "valid");
9012 vty_out(vty
, ", valid");
9015 if (path
->peer
!= bgp
->peer_self
) {
9016 if (path
->peer
->as
== path
->peer
->local_as
) {
9017 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9019 json_object_string_add(
9023 vty_out(vty
, ", confed-internal");
9026 json_object_string_add(
9027 json_peer
, "type", "internal");
9029 vty_out(vty
, ", internal");
9032 if (bgp_confederation_peers_check(bgp
,
9035 json_object_string_add(
9039 vty_out(vty
, ", confed-external");
9042 json_object_string_add(
9043 json_peer
, "type", "external");
9045 vty_out(vty
, ", external");
9048 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9050 json_object_boolean_true_add(json_path
, "aggregated");
9051 json_object_boolean_true_add(json_path
, "local");
9053 vty_out(vty
, ", aggregated, local");
9055 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9057 json_object_boolean_true_add(json_path
, "sourced");
9059 vty_out(vty
, ", sourced");
9062 json_object_boolean_true_add(json_path
, "sourced");
9063 json_object_boolean_true_add(json_path
, "local");
9065 vty_out(vty
, ", sourced, local");
9069 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9071 json_object_boolean_true_add(json_path
,
9074 vty_out(vty
, ", atomic-aggregate");
9077 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9078 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9079 && bgp_path_info_mpath_count(path
))) {
9081 json_object_boolean_true_add(json_path
, "multipath");
9083 vty_out(vty
, ", multipath");
9086 // Mark the bestpath(s)
9087 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9088 first_as
= aspath_get_first_as(attr
->aspath
);
9092 json_bestpath
= json_object_new_object();
9093 json_object_int_add(json_bestpath
, "bestpathFromAs",
9097 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9099 vty_out(vty
, ", bestpath-from-AS Local");
9103 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9106 json_bestpath
= json_object_new_object();
9107 json_object_boolean_true_add(json_bestpath
, "overall");
9108 json_object_string_add(
9109 json_bestpath
, "selectionReason",
9110 bgp_path_selection_reason2str(bn
->reason
));
9112 vty_out(vty
, ", best");
9113 vty_out(vty
, " (%s)",
9114 bgp_path_selection_reason2str(bn
->reason
));
9119 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9124 /* Line 4 display Community */
9125 if (attr
->community
) {
9127 if (!attr
->community
->json
)
9128 community_str(attr
->community
, true);
9129 json_object_lock(attr
->community
->json
);
9130 json_object_object_add(json_path
, "community",
9131 attr
->community
->json
);
9133 vty_out(vty
, " Community: %s\n",
9134 attr
->community
->str
);
9138 /* Line 5 display Extended-community */
9139 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9141 json_ext_community
= json_object_new_object();
9142 json_object_string_add(json_ext_community
, "string",
9143 attr
->ecommunity
->str
);
9144 json_object_object_add(json_path
, "extendedCommunity",
9145 json_ext_community
);
9147 vty_out(vty
, " Extended Community: %s\n",
9148 attr
->ecommunity
->str
);
9152 /* Line 6 display Large community */
9153 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9155 if (!attr
->lcommunity
->json
)
9156 lcommunity_str(attr
->lcommunity
, true);
9157 json_object_lock(attr
->lcommunity
->json
);
9158 json_object_object_add(json_path
, "largeCommunity",
9159 attr
->lcommunity
->json
);
9161 vty_out(vty
, " Large Community: %s\n",
9162 attr
->lcommunity
->str
);
9166 /* Line 7 display Originator, Cluster-id */
9167 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9168 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9169 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9171 json_object_string_add(
9172 json_path
, "originatorId",
9173 inet_ntoa(attr
->originator_id
));
9175 vty_out(vty
, " Originator: %s",
9176 inet_ntoa(attr
->originator_id
));
9179 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9183 json_cluster_list
= json_object_new_object();
9184 json_cluster_list_list
=
9185 json_object_new_array();
9187 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9189 json_string
= json_object_new_string(
9190 inet_ntoa(attr
->cluster
9192 json_object_array_add(
9193 json_cluster_list_list
,
9198 * struct cluster_list does not have
9199 * "str" variable like aspath and community
9200 * do. Add this someday if someone asks
9202 * json_object_string_add(json_cluster_list,
9203 * "string", attr->cluster->str);
9205 json_object_object_add(json_cluster_list
,
9207 json_cluster_list_list
);
9208 json_object_object_add(json_path
, "clusterList",
9211 vty_out(vty
, ", Cluster list: ");
9213 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9216 inet_ntoa(attr
->cluster
9226 if (path
->extra
&& path
->extra
->damp_info
)
9227 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9230 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9231 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9232 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9235 json_object_int_add(json_path
, "remoteLabel", label
);
9237 vty_out(vty
, " Remote label: %d\n", label
);
9241 if (path
->extra
&& path
->extra
->num_sids
> 0 && safi
!= SAFI_EVPN
) {
9242 inet_ntop(AF_INET6
, &path
->extra
->sid
, buf
, sizeof(buf
));
9244 json_object_string_add(json_path
, "remoteSid", buf
);
9246 vty_out(vty
, " Remote SID: %s\n", buf
);
9250 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9252 json_object_int_add(json_path
, "labelIndex",
9255 vty_out(vty
, " Label Index: %d\n",
9259 /* Line 8 display Addpath IDs */
9260 if (path
->addpath_rx_id
9261 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9263 json_object_int_add(json_path
, "addpathRxId",
9264 path
->addpath_rx_id
);
9266 /* Keep backwards compatibility with the old API
9267 * by putting TX All's ID in the old field
9269 json_object_int_add(
9270 json_path
, "addpathTxId",
9272 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9274 /* ... but create a specific field for each
9277 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9278 json_object_int_add(
9280 bgp_addpath_names(i
)->id_json_name
,
9281 path
->tx_addpath
.addpath_tx_id
[i
]);
9284 vty_out(vty
, " AddPath ID: RX %u, ",
9285 path
->addpath_rx_id
);
9287 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9291 /* If we used addpath to TX a non-bestpath we need to display
9292 * "Advertised to" on a path-by-path basis
9294 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9297 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9299 bgp_addpath_encode_tx(peer
, afi
, safi
);
9300 has_adj
= bgp_adj_out_lookup(
9302 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9303 &path
->tx_addpath
));
9305 if ((addpath_capable
&& has_adj
)
9306 || (!addpath_capable
&& has_adj
9307 && CHECK_FLAG(path
->flags
,
9308 BGP_PATH_SELECTED
))) {
9309 if (json_path
&& !json_adv_to
)
9310 json_adv_to
= json_object_new_object();
9312 route_vty_out_advertised_to(
9314 " Advertised to:", json_adv_to
);
9320 json_object_object_add(
9321 json_path
, "advertisedTo", json_adv_to
);
9330 /* Line 9 display Uptime */
9331 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9333 json_last_update
= json_object_new_object();
9334 json_object_int_add(json_last_update
, "epoch", tbuf
);
9335 json_object_string_add(json_last_update
, "string",
9337 json_object_object_add(json_path
, "lastUpdate",
9340 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9342 /* Line 10 display PMSI tunnel attribute, if present */
9343 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9345 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9346 PMSI_TNLTYPE_STR_DEFAULT
);
9349 json_pmsi
= json_object_new_object();
9350 json_object_string_add(json_pmsi
, "tunnelType", str
);
9351 json_object_int_add(json_pmsi
, "label",
9352 label2vni(&attr
->label
));
9353 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9355 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9356 str
, label2vni(&attr
->label
));
9359 /* We've constructed the json object for this path, add it to the json
9363 if (json_nexthop_global
|| json_nexthop_ll
) {
9364 json_nexthops
= json_object_new_array();
9366 if (json_nexthop_global
)
9367 json_object_array_add(json_nexthops
,
9368 json_nexthop_global
);
9370 if (json_nexthop_ll
)
9371 json_object_array_add(json_nexthops
,
9374 json_object_object_add(json_path
, "nexthops",
9378 json_object_object_add(json_path
, "peer", json_peer
);
9379 json_object_array_add(json_paths
, json_path
);
9383 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9384 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9385 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9387 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9388 const char *prefix_list_str
, afi_t afi
,
9389 safi_t safi
, enum bgp_show_type type
);
9390 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9391 const char *filter
, afi_t afi
, safi_t safi
,
9392 enum bgp_show_type type
);
9393 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9394 const char *rmap_str
, afi_t afi
, safi_t safi
,
9395 enum bgp_show_type type
);
9396 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9397 const char *com
, int exact
, afi_t afi
,
9399 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9400 const char *prefix
, afi_t afi
, safi_t safi
,
9401 enum bgp_show_type type
);
9402 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9403 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9405 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9406 const char *comstr
, int exact
, afi_t afi
,
9407 safi_t safi
, bool use_json
);
9410 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9411 struct bgp_table
*table
, enum bgp_show_type type
,
9412 void *output_arg
, bool use_json
, char *rd
,
9413 int is_last
, unsigned long *output_cum
,
9414 unsigned long *total_cum
,
9415 unsigned long *json_header_depth
)
9417 struct bgp_path_info
*pi
;
9418 struct bgp_node
*rn
;
9421 unsigned long output_count
= 0;
9422 unsigned long total_count
= 0;
9425 json_object
*json_paths
= NULL
;
9428 if (output_cum
&& *output_cum
!= 0)
9431 if (use_json
&& !*json_header_depth
) {
9433 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9434 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9435 " \"localAS\": %u,\n \"routes\": { ",
9436 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9437 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9440 table
->version
, inet_ntoa(bgp
->router_id
),
9441 bgp
->default_local_pref
, bgp
->as
);
9442 *json_header_depth
= 2;
9444 vty_out(vty
, " \"routeDistinguishers\" : {");
9445 ++*json_header_depth
;
9449 if (use_json
&& rd
) {
9450 vty_out(vty
, " \"%s\" : { ", rd
);
9453 /* Start processing of routes. */
9454 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9455 pi
= bgp_node_get_bgp_path_info(rn
);
9461 json_paths
= json_object_new_array();
9465 for (; pi
; pi
= pi
->next
) {
9467 if (type
== bgp_show_type_flap_statistics
9468 || type
== bgp_show_type_flap_neighbor
9469 || type
== bgp_show_type_dampend_paths
9470 || type
== bgp_show_type_damp_neighbor
) {
9471 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9474 if (type
== bgp_show_type_regexp
) {
9475 regex_t
*regex
= output_arg
;
9477 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9481 if (type
== bgp_show_type_prefix_list
) {
9482 struct prefix_list
*plist
= output_arg
;
9484 if (prefix_list_apply(plist
, &rn
->p
)
9488 if (type
== bgp_show_type_filter_list
) {
9489 struct as_list
*as_list
= output_arg
;
9491 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9492 != AS_FILTER_PERMIT
)
9495 if (type
== bgp_show_type_route_map
) {
9496 struct route_map
*rmap
= output_arg
;
9497 struct bgp_path_info path
;
9498 struct attr dummy_attr
;
9499 route_map_result_t ret
;
9501 dummy_attr
= *pi
->attr
;
9503 path
.peer
= pi
->peer
;
9504 path
.attr
= &dummy_attr
;
9506 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9508 if (ret
== RMAP_DENYMATCH
)
9511 if (type
== bgp_show_type_neighbor
9512 || type
== bgp_show_type_flap_neighbor
9513 || type
== bgp_show_type_damp_neighbor
) {
9514 union sockunion
*su
= output_arg
;
9516 if (pi
->peer
== NULL
9517 || pi
->peer
->su_remote
== NULL
9518 || !sockunion_same(pi
->peer
->su_remote
, su
))
9521 if (type
== bgp_show_type_cidr_only
) {
9522 uint32_t destination
;
9524 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9525 if (IN_CLASSC(destination
)
9526 && rn
->p
.prefixlen
== 24)
9528 if (IN_CLASSB(destination
)
9529 && rn
->p
.prefixlen
== 16)
9531 if (IN_CLASSA(destination
)
9532 && rn
->p
.prefixlen
== 8)
9535 if (type
== bgp_show_type_prefix_longer
) {
9537 if (!prefix_match(p
, &rn
->p
))
9540 if (type
== bgp_show_type_community_all
) {
9541 if (!pi
->attr
->community
)
9544 if (type
== bgp_show_type_community
) {
9545 struct community
*com
= output_arg
;
9547 if (!pi
->attr
->community
9548 || !community_match(pi
->attr
->community
,
9552 if (type
== bgp_show_type_community_exact
) {
9553 struct community
*com
= output_arg
;
9555 if (!pi
->attr
->community
9556 || !community_cmp(pi
->attr
->community
, com
))
9559 if (type
== bgp_show_type_community_list
) {
9560 struct community_list
*list
= output_arg
;
9562 if (!community_list_match(pi
->attr
->community
,
9566 if (type
== bgp_show_type_community_list_exact
) {
9567 struct community_list
*list
= output_arg
;
9569 if (!community_list_exact_match(
9570 pi
->attr
->community
, list
))
9573 if (type
== bgp_show_type_lcommunity
) {
9574 struct lcommunity
*lcom
= output_arg
;
9576 if (!pi
->attr
->lcommunity
9577 || !lcommunity_match(pi
->attr
->lcommunity
,
9582 if (type
== bgp_show_type_lcommunity_exact
) {
9583 struct lcommunity
*lcom
= output_arg
;
9585 if (!pi
->attr
->lcommunity
9586 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9590 if (type
== bgp_show_type_lcommunity_list
) {
9591 struct community_list
*list
= output_arg
;
9593 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9598 == bgp_show_type_lcommunity_list_exact
) {
9599 struct community_list
*list
= output_arg
;
9601 if (!lcommunity_list_exact_match(
9602 pi
->attr
->lcommunity
, list
))
9605 if (type
== bgp_show_type_lcommunity_all
) {
9606 if (!pi
->attr
->lcommunity
)
9609 if (type
== bgp_show_type_dampend_paths
9610 || type
== bgp_show_type_damp_neighbor
) {
9611 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9612 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9616 if (!use_json
&& header
) {
9617 vty_out(vty
, "BGP table version is %" PRIu64
9618 ", local router ID is %s, vrf id ",
9620 inet_ntoa(bgp
->router_id
));
9621 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9622 vty_out(vty
, "%s", VRFID_NONE_STR
);
9624 vty_out(vty
, "%u", bgp
->vrf_id
);
9626 vty_out(vty
, "Default local pref %u, ",
9627 bgp
->default_local_pref
);
9628 vty_out(vty
, "local AS %u\n", bgp
->as
);
9629 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9630 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9631 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9632 if (type
== bgp_show_type_dampend_paths
9633 || type
== bgp_show_type_damp_neighbor
)
9634 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9635 else if (type
== bgp_show_type_flap_statistics
9636 || type
== bgp_show_type_flap_neighbor
)
9637 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9639 vty_out(vty
, BGP_SHOW_HEADER
);
9642 if (rd
!= NULL
&& !display
&& !output_count
) {
9645 "Route Distinguisher: %s\n",
9648 if (type
== bgp_show_type_dampend_paths
9649 || type
== bgp_show_type_damp_neighbor
)
9650 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9651 safi
, use_json
, json_paths
);
9652 else if (type
== bgp_show_type_flap_statistics
9653 || type
== bgp_show_type_flap_neighbor
)
9654 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9655 safi
, use_json
, json_paths
);
9657 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9669 if (p
->family
== AF_FLOWSPEC
) {
9670 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9672 bgp_fs_nlri_get_string((unsigned char *)
9673 p
->u
.prefix_flowspec
.ptr
,
9674 p
->u
.prefix_flowspec
9677 NLRI_STRING_FORMAT_MIN
,
9680 vty_out(vty
, "\"%s/%d\": ",
9682 p
->u
.prefix_flowspec
.prefixlen
);
9684 vty_out(vty
, ",\"%s/%d\": ",
9686 p
->u
.prefix_flowspec
.prefixlen
);
9688 prefix2str(p
, buf2
, sizeof(buf2
));
9690 vty_out(vty
, "\"%s\": ", buf2
);
9692 vty_out(vty
, ",\"%s\": ", buf2
);
9695 json_object_to_json_string_ext(
9696 json_paths
, JSON_C_TO_STRING_PRETTY
));
9697 json_object_free(json_paths
);
9701 json_object_free(json_paths
);
9705 output_count
+= *output_cum
;
9706 *output_cum
= output_count
;
9709 total_count
+= *total_cum
;
9710 *total_cum
= total_count
;
9714 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9718 for (i
= 0; i
< *json_header_depth
; ++i
)
9719 vty_out(vty
, " } ");
9724 /* No route is displayed */
9725 if (output_count
== 0) {
9726 if (type
== bgp_show_type_normal
)
9728 "No BGP prefixes displayed, %ld exist\n",
9732 "\nDisplayed %ld routes and %ld total paths\n",
9733 output_count
, total_count
);
9740 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9741 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9742 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9744 struct bgp_node
*rn
, *next
;
9745 unsigned long output_cum
= 0;
9746 unsigned long total_cum
= 0;
9747 unsigned long json_header_depth
= 0;
9748 struct bgp_table
*itable
;
9751 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9753 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9754 next
= bgp_route_next(rn
);
9755 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9758 itable
= bgp_node_get_bgp_table_info(rn
);
9759 if (itable
!= NULL
) {
9760 struct prefix_rd prd
;
9761 char rd
[RD_ADDRSTRLEN
];
9763 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9764 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9765 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9766 use_json
, rd
, next
== NULL
, &output_cum
,
9767 &total_cum
, &json_header_depth
);
9773 if (output_cum
== 0)
9774 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9778 "\nDisplayed %ld routes and %ld total paths\n",
9779 output_cum
, total_cum
);
9783 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9784 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9786 struct bgp_table
*table
;
9787 unsigned long json_header_depth
= 0;
9790 bgp
= bgp_get_default();
9795 vty_out(vty
, "No BGP process is configured\n");
9797 vty_out(vty
, "{}\n");
9801 table
= bgp
->rib
[afi
][safi
];
9802 /* use MPLS and ENCAP specific shows until they are merged */
9803 if (safi
== SAFI_MPLS_VPN
) {
9804 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9805 output_arg
, use_json
);
9808 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9809 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9810 output_arg
, use_json
,
9813 /* labeled-unicast routes live in the unicast table */
9814 else if (safi
== SAFI_LABELED_UNICAST
)
9815 safi
= SAFI_UNICAST
;
9817 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9818 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9821 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9822 safi_t safi
, bool use_json
)
9824 struct listnode
*node
, *nnode
;
9827 bool route_output
= false;
9830 vty_out(vty
, "{\n");
9832 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9833 route_output
= true;
9836 vty_out(vty
, ",\n");
9840 vty_out(vty
, "\"%s\":",
9841 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9845 vty_out(vty
, "\nInstance %s:\n",
9846 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9850 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9855 vty_out(vty
, "}\n");
9856 else if (!route_output
)
9857 vty_out(vty
, "%% BGP instance not found\n");
9860 /* Header of detailed BGP route information */
9861 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9862 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9863 afi_t afi
, safi_t safi
, json_object
*json
)
9865 struct bgp_path_info
*pi
;
9868 struct listnode
*node
, *nnode
;
9869 char buf1
[RD_ADDRSTRLEN
];
9870 char buf2
[INET6_ADDRSTRLEN
];
9871 char buf3
[EVPN_ROUTE_STRLEN
];
9872 char prefix_str
[BUFSIZ
];
9877 int route_filter_translated_v4
= 0;
9878 int route_filter_v4
= 0;
9879 int route_filter_translated_v6
= 0;
9880 int route_filter_v6
= 0;
9883 int accept_own_nexthop
= 0;
9886 int no_advertise
= 0;
9890 int has_valid_label
= 0;
9891 mpls_label_t label
= 0;
9892 json_object
*json_adv_to
= NULL
;
9895 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9897 if (has_valid_label
)
9898 label
= label_pton(&rn
->local_label
);
9900 if (safi
== SAFI_EVPN
) {
9903 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9904 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9905 : "", prd
? ":" : "",
9906 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9907 buf3
, sizeof(buf3
)));
9909 json_object_string_add(json
, "rd",
9910 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9912 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9916 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9917 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9918 ? prefix_rd2str(prd
, buf1
,
9921 safi
== SAFI_MPLS_VPN
? ":" : "",
9922 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9927 json_object_string_add(json
, "prefix",
9928 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9931 if (has_valid_label
) {
9933 json_object_int_add(json
, "localLabel", label
);
9935 vty_out(vty
, "Local label: %d\n", label
);
9939 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9940 vty_out(vty
, "not allocated\n");
9942 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9944 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9946 if (pi
->extra
&& pi
->extra
->suppress
)
9949 if (pi
->attr
->community
== NULL
)
9952 no_advertise
+= community_include(
9953 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9954 no_export
+= community_include(pi
->attr
->community
,
9955 COMMUNITY_NO_EXPORT
);
9956 local_as
+= community_include(pi
->attr
->community
,
9957 COMMUNITY_LOCAL_AS
);
9958 accept_own
+= community_include(pi
->attr
->community
,
9959 COMMUNITY_ACCEPT_OWN
);
9960 route_filter_translated_v4
+= community_include(
9961 pi
->attr
->community
,
9962 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9963 route_filter_translated_v6
+= community_include(
9964 pi
->attr
->community
,
9965 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9966 route_filter_v4
+= community_include(
9967 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9968 route_filter_v6
+= community_include(
9969 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9970 llgr_stale
+= community_include(pi
->attr
->community
,
9971 COMMUNITY_LLGR_STALE
);
9972 no_llgr
+= community_include(pi
->attr
->community
,
9974 accept_own_nexthop
+=
9975 community_include(pi
->attr
->community
,
9976 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9977 blackhole
+= community_include(pi
->attr
->community
,
9978 COMMUNITY_BLACKHOLE
);
9979 no_peer
+= community_include(pi
->attr
->community
,
9985 vty_out(vty
, "Paths: (%d available", count
);
9987 vty_out(vty
, ", best #%d", best
);
9988 if (safi
== SAFI_UNICAST
) {
9989 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9990 vty_out(vty
, ", table %s",
9993 vty_out(vty
, ", vrf %s",
9997 vty_out(vty
, ", no best path");
10001 ", accept own local route exported and imported in different VRF");
10002 else if (route_filter_translated_v4
)
10004 ", mark translated RTs for VPNv4 route filtering");
10005 else if (route_filter_v4
)
10007 ", attach RT as-is for VPNv4 route filtering");
10008 else if (route_filter_translated_v6
)
10010 ", mark translated RTs for VPNv6 route filtering");
10011 else if (route_filter_v6
)
10013 ", attach RT as-is for VPNv6 route filtering");
10014 else if (llgr_stale
)
10016 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10019 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10020 else if (accept_own_nexthop
)
10022 ", accept local nexthop");
10023 else if (blackhole
)
10024 vty_out(vty
, ", inform peer to blackhole prefix");
10025 else if (no_export
)
10026 vty_out(vty
, ", not advertised to EBGP peer");
10027 else if (no_advertise
)
10028 vty_out(vty
, ", not advertised to any peer");
10030 vty_out(vty
, ", not advertised outside local AS");
10033 ", inform EBGP peer not to advertise to their EBGP peers");
10037 ", Advertisements suppressed by an aggregate.");
10038 vty_out(vty
, ")\n");
10041 /* If we are not using addpath then we can display Advertised to and
10043 * show what peers we advertised the bestpath to. If we are using
10045 * though then we must display Advertised to on a path-by-path basis. */
10046 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10047 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10048 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
10049 if (json
&& !json_adv_to
)
10050 json_adv_to
= json_object_new_object();
10052 route_vty_out_advertised_to(
10054 " Advertised to non peer-group peers:\n ",
10061 json_object_object_add(json
, "advertisedTo",
10066 vty_out(vty
, " Not advertised to any peer");
10067 vty_out(vty
, "\n");
10072 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10073 struct bgp_node
*bgp_node
, struct vty
*vty
,
10074 struct bgp
*bgp
, afi_t afi
,
10075 safi_t safi
, json_object
*json
,
10076 enum bgp_path_type pathtype
, int *display
)
10078 struct bgp_path_info
*pi
;
10080 char rdbuf
[RD_ADDRSTRLEN
];
10081 json_object
*json_header
= NULL
;
10082 json_object
*json_paths
= NULL
;
10084 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
10087 if (json
&& !json_paths
) {
10088 /* Instantiate json_paths only if path is valid */
10089 json_paths
= json_object_new_array();
10091 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10092 json_header
= json_object_new_object();
10094 json_header
= json
;
10098 route_vty_out_detail_header(
10099 vty
, bgp
, bgp_node
, pfx_rd
,
10100 AFI_IP
, safi
, json_header
);
10105 if (pathtype
== BGP_PATH_SHOW_ALL
10106 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10107 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10108 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10109 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10110 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10111 route_vty_out_detail(vty
, bgp
, bgp_node
,
10116 if (json
&& json_paths
) {
10117 json_object_object_add(json_header
, "paths", json_paths
);
10120 json_object_object_add(json
, rdbuf
, json_header
);
10124 /* Display specified route of BGP table. */
10125 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10126 struct bgp_table
*rib
, const char *ip_str
,
10127 afi_t afi
, safi_t safi
,
10128 struct prefix_rd
*prd
, int prefix_check
,
10129 enum bgp_path_type pathtype
, bool use_json
)
10133 struct prefix match
;
10134 struct bgp_node
*rn
;
10135 struct bgp_node
*rm
;
10136 struct bgp_table
*table
;
10137 json_object
*json
= NULL
;
10138 json_object
*json_paths
= NULL
;
10140 /* Check IP address argument. */
10141 ret
= str2prefix(ip_str
, &match
);
10143 vty_out(vty
, "address is malformed\n");
10144 return CMD_WARNING
;
10147 match
.family
= afi2family(afi
);
10150 json
= json_object_new_object();
10152 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10153 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10154 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10156 table
= bgp_node_get_bgp_table_info(rn
);
10160 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10164 && rm
->p
.prefixlen
!= match
.prefixlen
) {
10165 bgp_unlock_node(rm
);
10169 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10170 vty
, bgp
, afi
, safi
, json
,
10171 pathtype
, &display
);
10173 bgp_unlock_node(rm
);
10175 } else if (safi
== SAFI_EVPN
) {
10176 struct bgp_node
*longest_pfx
;
10177 bool is_exact_pfxlen_match
= FALSE
;
10179 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10180 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10182 table
= bgp_node_get_bgp_table_info(rn
);
10186 longest_pfx
= NULL
;
10187 is_exact_pfxlen_match
= FALSE
;
10189 * Search through all the prefixes for a match. The
10190 * pfx's are enumerated in ascending order of pfxlens.
10191 * So, the last pfx match is the longest match. Set
10192 * is_exact_pfxlen_match when we get exact pfxlen match
10194 for (rm
= bgp_table_top(table
); rm
;
10195 rm
= bgp_route_next(rm
)) {
10197 * Get prefixlen of the ip-prefix within type5
10200 if (evpn_type5_prefix_match(&rm
->p
,
10201 &match
) && rm
->info
) {
10204 bgp_evpn_get_type5_prefixlen(&rm
->p
);
10205 if (type5_pfxlen
== match
.prefixlen
) {
10206 is_exact_pfxlen_match
= TRUE
;
10207 bgp_unlock_node(rm
);
10216 if (prefix_check
&& !is_exact_pfxlen_match
)
10222 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10223 vty
, bgp
, afi
, safi
, json
,
10224 pathtype
, &display
);
10226 bgp_unlock_node(rm
);
10228 } else if (safi
== SAFI_FLOWSPEC
) {
10230 json_paths
= json_object_new_array();
10232 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10233 &match
, prefix_check
,
10237 if (use_json
&& display
)
10238 json_object_object_add(json
, "paths", json_paths
);
10240 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
10242 || rn
->p
.prefixlen
== match
.prefixlen
) {
10243 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
10245 pathtype
, &display
);
10248 bgp_unlock_node(rn
);
10253 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10254 json
, JSON_C_TO_STRING_PRETTY
|
10255 JSON_C_TO_STRING_NOSLASHESCAPE
));
10256 json_object_free(json
);
10259 vty_out(vty
, "%% Network not in table\n");
10260 return CMD_WARNING
;
10264 return CMD_SUCCESS
;
10267 /* Display specified route of Main RIB */
10268 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10269 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10270 int prefix_check
, enum bgp_path_type pathtype
,
10274 bgp
= bgp_get_default();
10277 vty_out(vty
, "No BGP process is configured\n");
10279 vty_out(vty
, "{}\n");
10280 return CMD_WARNING
;
10284 /* labeled-unicast routes live in the unicast table */
10285 if (safi
== SAFI_LABELED_UNICAST
)
10286 safi
= SAFI_UNICAST
;
10288 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10289 afi
, safi
, prd
, prefix_check
, pathtype
,
10293 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10294 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10295 safi_t safi
, bool uj
)
10297 struct lcommunity
*lcom
;
10303 b
= buffer_new(1024);
10304 for (i
= 0; i
< argc
; i
++) {
10306 buffer_putc(b
, ' ');
10308 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10310 buffer_putstr(b
, argv
[i
]->arg
);
10314 buffer_putc(b
, '\0');
10316 str
= buffer_getstr(b
);
10319 lcom
= lcommunity_str2com(str
);
10320 XFREE(MTYPE_TMP
, str
);
10322 vty_out(vty
, "%% Large-community malformed\n");
10323 return CMD_WARNING
;
10326 return bgp_show(vty
, bgp
, afi
, safi
,
10327 (exact
? bgp_show_type_lcommunity_exact
10328 : bgp_show_type_lcommunity
),
10332 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10333 const char *lcom
, bool exact
, afi_t afi
,
10334 safi_t safi
, bool uj
)
10336 struct community_list
*list
;
10338 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10339 LARGE_COMMUNITY_LIST_MASTER
);
10340 if (list
== NULL
) {
10341 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10343 return CMD_WARNING
;
10346 return bgp_show(vty
, bgp
, afi
, safi
,
10347 (exact
? bgp_show_type_lcommunity_list_exact
10348 : bgp_show_type_lcommunity_list
),
10352 DEFUN (show_ip_bgp_large_community_list
,
10353 show_ip_bgp_large_community_list_cmd
,
10354 "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]",
10358 BGP_INSTANCE_HELP_STR
10360 BGP_SAFI_WITH_LABEL_HELP_STR
10361 "Display routes matching the large-community-list\n"
10362 "large-community-list number\n"
10363 "large-community-list name\n"
10364 "Exact match of the large-communities\n"
10368 afi_t afi
= AFI_IP6
;
10369 safi_t safi
= SAFI_UNICAST
;
10371 bool exact_match
= 0;
10373 if (argv_find(argv
, argc
, "ip", &idx
))
10375 if (argv_find(argv
, argc
, "view", &idx
)
10376 || argv_find(argv
, argc
, "vrf", &idx
))
10377 vrf
= argv
[++idx
]->arg
;
10378 if (argv_find(argv
, argc
, "ipv4", &idx
)
10379 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10380 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10381 if (argv_find(argv
, argc
, "unicast", &idx
)
10382 || argv_find(argv
, argc
, "multicast", &idx
))
10383 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10386 bool uj
= use_json(argc
, argv
);
10388 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10390 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10391 return CMD_WARNING
;
10394 argv_find(argv
, argc
, "large-community-list", &idx
);
10396 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10398 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10401 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10402 exact_match
, afi
, safi
, uj
);
10404 DEFUN (show_ip_bgp_large_community
,
10405 show_ip_bgp_large_community_cmd
,
10406 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10410 BGP_INSTANCE_HELP_STR
10412 BGP_SAFI_WITH_LABEL_HELP_STR
10413 "Display routes matching the large-communities\n"
10414 "List of large-community numbers\n"
10415 "Exact match of the large-communities\n"
10419 afi_t afi
= AFI_IP6
;
10420 safi_t safi
= SAFI_UNICAST
;
10422 bool exact_match
= 0;
10424 if (argv_find(argv
, argc
, "ip", &idx
))
10426 if (argv_find(argv
, argc
, "view", &idx
)
10427 || argv_find(argv
, argc
, "vrf", &idx
))
10428 vrf
= argv
[++idx
]->arg
;
10429 if (argv_find(argv
, argc
, "ipv4", &idx
)
10430 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10431 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10432 if (argv_find(argv
, argc
, "unicast", &idx
)
10433 || argv_find(argv
, argc
, "multicast", &idx
))
10434 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10437 bool uj
= use_json(argc
, argv
);
10439 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10441 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10442 return CMD_WARNING
;
10445 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10446 if (argv_find(argv
, argc
, "exact-match", &idx
))
10448 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10449 exact_match
, afi
, safi
, uj
);
10451 return bgp_show(vty
, bgp
, afi
, safi
,
10452 bgp_show_type_lcommunity_all
, NULL
, uj
);
10455 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10459 /* BGP route print out function without JSON */
10460 DEFUN (show_ip_bgp
,
10462 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10463 <dampening <parameters>\
10468 |community-list <(1-500)|WORD> [exact-match]\
10469 |A.B.C.D/M longer-prefixes\
10470 |X:X::X:X/M longer-prefixes\
10475 BGP_INSTANCE_HELP_STR
10477 BGP_SAFI_WITH_LABEL_HELP_STR
10478 "Display detailed information about dampening\n"
10479 "Display detail of configured dampening parameters\n"
10480 "Display routes matching the route-map\n"
10481 "A route-map to match on\n"
10482 "Display routes conforming to the prefix-list\n"
10483 "Prefix-list name\n"
10484 "Display routes conforming to the filter-list\n"
10485 "Regular expression access list name\n"
10486 "BGP RIB advertisement statistics\n"
10487 "Display routes matching the community-list\n"
10488 "community-list number\n"
10489 "community-list name\n"
10490 "Exact match of the communities\n"
10492 "Display route and more specific routes\n"
10494 "Display route and more specific routes\n")
10496 afi_t afi
= AFI_IP6
;
10497 safi_t safi
= SAFI_UNICAST
;
10498 int exact_match
= 0;
10499 struct bgp
*bgp
= NULL
;
10502 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10505 return CMD_WARNING
;
10507 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10508 if (argv_find(argv
, argc
, "parameters", &idx
))
10509 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10512 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10513 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10514 safi
, bgp_show_type_prefix_list
);
10516 if (argv_find(argv
, argc
, "filter-list", &idx
))
10517 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10518 safi
, bgp_show_type_filter_list
);
10520 if (argv_find(argv
, argc
, "statistics", &idx
))
10521 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10523 if (argv_find(argv
, argc
, "route-map", &idx
))
10524 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10525 safi
, bgp_show_type_route_map
);
10527 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10528 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10529 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10531 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10532 exact_match
, afi
, safi
);
10534 /* prefix-longer */
10535 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10536 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10537 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10539 bgp_show_type_prefix_longer
);
10541 return CMD_WARNING
;
10544 /* BGP route print out function with JSON */
10545 DEFUN (show_ip_bgp_json
,
10546 show_ip_bgp_json_cmd
,
10547 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10549 |dampening <flap-statistics|dampened-paths>\
10550 |community [AA:NN|local-AS|no-advertise|no-export\
10551 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10552 |accept-own|accept-own-nexthop|route-filter-v6\
10553 |route-filter-v4|route-filter-translated-v6\
10554 |route-filter-translated-v4] [exact-match]\
10559 BGP_INSTANCE_HELP_STR
10561 BGP_SAFI_WITH_LABEL_HELP_STR
10562 "Display only routes with non-natural netmasks\n"
10563 "Display detailed information about dampening\n"
10564 "Display flap statistics of routes\n"
10565 "Display paths suppressed due to dampening\n"
10566 "Display routes matching the communities\n"
10568 "Do not send outside local AS (well-known community)\n"
10569 "Do not advertise to any peer (well-known community)\n"
10570 "Do not export to next AS (well-known community)\n"
10571 "Graceful shutdown (well-known community)\n"
10572 "Do not export to any peer (well-known community)\n"
10573 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10574 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10575 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10576 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10577 "Should accept VPN route with local nexthop (well-known community)\n"
10578 "RT VPNv6 route filtering (well-known community)\n"
10579 "RT VPNv4 route filtering (well-known community)\n"
10580 "RT translated VPNv6 route filtering (well-known community)\n"
10581 "RT translated VPNv4 route filtering (well-known community)\n"
10582 "Exact match of the communities\n"
10585 afi_t afi
= AFI_IP6
;
10586 safi_t safi
= SAFI_UNICAST
;
10587 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10588 struct bgp
*bgp
= NULL
;
10590 int exact_match
= 0;
10591 bool uj
= use_json(argc
, argv
);
10596 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10599 return CMD_WARNING
;
10601 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10602 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10605 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10606 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10607 return bgp_show(vty
, bgp
, afi
, safi
,
10608 bgp_show_type_dampend_paths
, NULL
, uj
);
10609 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10610 return bgp_show(vty
, bgp
, afi
, safi
,
10611 bgp_show_type_flap_statistics
, NULL
,
10615 if (argv_find(argv
, argc
, "community", &idx
)) {
10616 char *maybecomm
= NULL
;
10617 char *community
= NULL
;
10619 if (idx
+ 1 < argc
) {
10620 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10621 maybecomm
= argv
[idx
+ 1]->arg
;
10623 maybecomm
= argv
[idx
+ 1]->text
;
10626 if (maybecomm
&& !strmatch(maybecomm
, "json")
10627 && !strmatch(maybecomm
, "exact-match"))
10628 community
= maybecomm
;
10630 if (argv_find(argv
, argc
, "exact-match", &idx
))
10634 return bgp_show_community(vty
, bgp
, community
,
10635 exact_match
, afi
, safi
, uj
);
10637 return (bgp_show(vty
, bgp
, afi
, safi
,
10638 bgp_show_type_community_all
, NULL
,
10642 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10645 DEFUN (show_ip_bgp_route
,
10646 show_ip_bgp_route_cmd
,
10647 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10648 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10652 BGP_INSTANCE_HELP_STR
10654 BGP_SAFI_WITH_LABEL_HELP_STR
10655 "Network in the BGP routing table to display\n"
10657 "Network in the BGP routing table to display\n"
10659 "Display only the bestpath\n"
10660 "Display only multipaths\n"
10663 int prefix_check
= 0;
10665 afi_t afi
= AFI_IP6
;
10666 safi_t safi
= SAFI_UNICAST
;
10667 char *prefix
= NULL
;
10668 struct bgp
*bgp
= NULL
;
10669 enum bgp_path_type path_type
;
10670 bool uj
= use_json(argc
, argv
);
10674 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10677 return CMD_WARNING
;
10681 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10682 return CMD_WARNING
;
10685 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10686 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10687 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10689 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10690 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10693 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10694 && afi
!= AFI_IP6
) {
10696 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10697 return CMD_WARNING
;
10699 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10700 && afi
!= AFI_IP
) {
10702 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10703 return CMD_WARNING
;
10706 prefix
= argv
[idx
]->arg
;
10708 /* [<bestpath|multipath>] */
10709 if (argv_find(argv
, argc
, "bestpath", &idx
))
10710 path_type
= BGP_PATH_SHOW_BESTPATH
;
10711 else if (argv_find(argv
, argc
, "multipath", &idx
))
10712 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10714 path_type
= BGP_PATH_SHOW_ALL
;
10716 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10720 DEFUN (show_ip_bgp_regexp
,
10721 show_ip_bgp_regexp_cmd
,
10722 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10726 BGP_INSTANCE_HELP_STR
10728 BGP_SAFI_WITH_LABEL_HELP_STR
10729 "Display routes matching the AS path regular expression\n"
10730 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10733 afi_t afi
= AFI_IP6
;
10734 safi_t safi
= SAFI_UNICAST
;
10735 struct bgp
*bgp
= NULL
;
10736 bool uj
= use_json(argc
, argv
);
10737 char *regstr
= NULL
;
10740 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10743 return CMD_WARNING
;
10745 // get index of regex
10746 if (argv_find(argv
, argc
, "REGEX", &idx
))
10747 regstr
= argv
[idx
]->arg
;
10750 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10751 bgp_show_type_regexp
, uj
);
10754 DEFUN (show_ip_bgp_instance_all
,
10755 show_ip_bgp_instance_all_cmd
,
10756 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10760 BGP_INSTANCE_ALL_HELP_STR
10762 BGP_SAFI_WITH_LABEL_HELP_STR
10765 afi_t afi
= AFI_IP
;
10766 safi_t safi
= SAFI_UNICAST
;
10767 struct bgp
*bgp
= NULL
;
10769 bool uj
= use_json(argc
, argv
);
10774 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10777 return CMD_WARNING
;
10779 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10780 return CMD_SUCCESS
;
10783 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10784 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10790 if (!config_bgp_aspath_validate(regstr
)) {
10791 vty_out(vty
, "Invalid character in REGEX %s\n",
10793 return CMD_WARNING_CONFIG_FAILED
;
10796 regex
= bgp_regcomp(regstr
);
10798 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10799 return CMD_WARNING
;
10802 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
10803 bgp_regex_free(regex
);
10807 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10808 const char *prefix_list_str
, afi_t afi
,
10809 safi_t safi
, enum bgp_show_type type
)
10811 struct prefix_list
*plist
;
10813 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10814 if (plist
== NULL
) {
10815 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10817 return CMD_WARNING
;
10820 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10823 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10824 const char *filter
, afi_t afi
, safi_t safi
,
10825 enum bgp_show_type type
)
10827 struct as_list
*as_list
;
10829 as_list
= as_list_lookup(filter
);
10830 if (as_list
== NULL
) {
10831 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10833 return CMD_WARNING
;
10836 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10839 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10840 const char *rmap_str
, afi_t afi
, safi_t safi
,
10841 enum bgp_show_type type
)
10843 struct route_map
*rmap
;
10845 rmap
= route_map_lookup_by_name(rmap_str
);
10847 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10848 return CMD_WARNING
;
10851 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10854 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10855 const char *comstr
, int exact
, afi_t afi
,
10856 safi_t safi
, bool use_json
)
10858 struct community
*com
;
10861 com
= community_str2com(comstr
);
10863 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10864 return CMD_WARNING
;
10867 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10868 (exact
? bgp_show_type_community_exact
10869 : bgp_show_type_community
),
10871 community_free(&com
);
10876 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10877 const char *com
, int exact
, afi_t afi
,
10880 struct community_list
*list
;
10882 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10883 if (list
== NULL
) {
10884 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10885 return CMD_WARNING
;
10888 return bgp_show(vty
, bgp
, afi
, safi
,
10889 (exact
? bgp_show_type_community_list_exact
10890 : bgp_show_type_community_list
),
10894 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10895 const char *prefix
, afi_t afi
, safi_t safi
,
10896 enum bgp_show_type type
)
10903 ret
= str2prefix(prefix
, p
);
10905 vty_out(vty
, "%% Malformed Prefix\n");
10906 return CMD_WARNING
;
10909 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10915 BGP_STATS_MAXBITLEN
= 0,
10917 BGP_STATS_PREFIXES
,
10919 BGP_STATS_UNAGGREGATEABLE
,
10920 BGP_STATS_MAX_AGGREGATEABLE
,
10921 BGP_STATS_AGGREGATES
,
10923 BGP_STATS_ASPATH_COUNT
,
10924 BGP_STATS_ASPATH_MAXHOPS
,
10925 BGP_STATS_ASPATH_TOTHOPS
,
10926 BGP_STATS_ASPATH_MAXSIZE
,
10927 BGP_STATS_ASPATH_TOTSIZE
,
10928 BGP_STATS_ASN_HIGHEST
,
10932 static const char *const table_stats_strs
[] = {
10933 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10934 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10935 [BGP_STATS_RIB
] = "Total Advertisements",
10936 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10937 [BGP_STATS_MAX_AGGREGATEABLE
] =
10938 "Maximum aggregateable prefixes",
10939 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10940 [BGP_STATS_SPACE
] = "Address space advertised",
10941 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10942 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10943 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10944 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10945 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10946 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10947 [BGP_STATS_MAX
] = NULL
,
10950 struct bgp_table_stats
{
10951 struct bgp_table
*table
;
10952 unsigned long long counts
[BGP_STATS_MAX
];
10953 double total_space
;
10957 #define TALLY_SIGFIG 100000
10958 static unsigned long
10959 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10961 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10962 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10963 unsigned long ret
= newtot
/ count
;
10965 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10972 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10973 struct bgp_table_stats
*ts
, unsigned int space
)
10975 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10976 struct bgp_path_info
*pi
;
10981 if (!bgp_node_has_bgp_path_info_data(rn
))
10984 ts
->counts
[BGP_STATS_PREFIXES
]++;
10985 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10988 ts
->counts
[BGP_STATS_AVGPLEN
]
10989 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10990 ts
->counts
[BGP_STATS_AVGPLEN
],
10994 /* check if the prefix is included by any other announcements */
10995 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10996 prn
= bgp_node_parent_nolock(prn
);
10998 if (prn
== NULL
|| prn
== top
) {
10999 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
11000 /* announced address space */
11002 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
11003 } else if (bgp_node_has_bgp_path_info_data(prn
))
11004 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
11007 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11008 ts
->counts
[BGP_STATS_RIB
]++;
11010 if (CHECK_FLAG(pi
->attr
->flag
,
11011 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
11012 ts
->counts
[BGP_STATS_AGGREGATES
]++;
11014 /* as-path stats */
11015 if (pi
->attr
->aspath
) {
11016 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
11017 unsigned int size
= aspath_size(pi
->attr
->aspath
);
11018 as_t highest
= aspath_highest(pi
->attr
->aspath
);
11020 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
11022 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
11023 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
11025 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11026 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11028 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11029 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11031 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11032 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11033 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11035 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11036 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11037 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11040 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11041 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11046 static int bgp_table_stats_walker(struct thread
*t
)
11048 struct bgp_node
*rn
, *nrn
;
11049 struct bgp_node
*top
;
11050 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11051 unsigned int space
= 0;
11053 if (!(top
= bgp_table_top(ts
->table
)))
11056 switch (ts
->table
->afi
) {
11058 space
= IPV4_MAX_BITLEN
;
11061 space
= IPV6_MAX_BITLEN
;
11067 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11069 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
11070 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
11071 struct bgp_table
*table
;
11073 table
= bgp_node_get_bgp_table_info(rn
);
11077 top
= bgp_table_top(table
);
11078 for (nrn
= bgp_table_top(table
); nrn
;
11079 nrn
= bgp_route_next(nrn
))
11080 bgp_table_stats_rn(nrn
, top
, ts
, space
);
11082 bgp_table_stats_rn(rn
, top
, ts
, space
);
11089 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11092 struct bgp_table_stats ts
;
11095 if (!bgp
->rib
[afi
][safi
]) {
11096 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11098 return CMD_WARNING
;
11101 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
11103 /* labeled-unicast routes live in the unicast table */
11104 if (safi
== SAFI_LABELED_UNICAST
)
11105 safi
= SAFI_UNICAST
;
11107 memset(&ts
, 0, sizeof(ts
));
11108 ts
.table
= bgp
->rib
[afi
][safi
];
11109 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11111 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11112 if (!table_stats_strs
[i
])
11117 case BGP_STATS_ASPATH_AVGHOPS
:
11118 case BGP_STATS_ASPATH_AVGSIZE
:
11119 case BGP_STATS_AVGPLEN
:
11120 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11121 vty_out (vty
, "%12.2f",
11122 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11125 case BGP_STATS_ASPATH_TOTHOPS
:
11126 case BGP_STATS_ASPATH_TOTSIZE
:
11127 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11128 vty_out(vty
, "%12.2f",
11130 ? (float)ts
.counts
[i
]
11132 [BGP_STATS_ASPATH_COUNT
]
11135 case BGP_STATS_TOTPLEN
:
11136 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11137 vty_out(vty
, "%12.2f",
11139 ? (float)ts
.counts
[i
]
11141 [BGP_STATS_PREFIXES
]
11144 case BGP_STATS_SPACE
:
11145 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11146 vty_out(vty
, "%12g\n", ts
.total_space
);
11148 if (afi
== AFI_IP6
) {
11149 vty_out(vty
, "%30s: ", "/32 equivalent ");
11150 vty_out(vty
, "%12g\n",
11151 ts
.total_space
* pow(2.0, -128 + 32));
11152 vty_out(vty
, "%30s: ", "/48 equivalent ");
11153 vty_out(vty
, "%12g\n",
11154 ts
.total_space
* pow(2.0, -128 + 48));
11156 vty_out(vty
, "%30s: ", "% announced ");
11157 vty_out(vty
, "%12.2f\n",
11158 ts
.total_space
* 100. * pow(2.0, -32));
11159 vty_out(vty
, "%30s: ", "/8 equivalent ");
11160 vty_out(vty
, "%12.2f\n",
11161 ts
.total_space
* pow(2.0, -32 + 8));
11162 vty_out(vty
, "%30s: ", "/24 equivalent ");
11163 vty_out(vty
, "%12.2f\n",
11164 ts
.total_space
* pow(2.0, -32 + 24));
11168 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11169 vty_out(vty
, "%12llu", ts
.counts
[i
]);
11172 vty_out(vty
, "\n");
11174 return CMD_SUCCESS
;
11186 PCOUNT_PFCNT
, /* the figure we display to users */
11190 static const char *const pcount_strs
[] = {
11191 [PCOUNT_ADJ_IN
] = "Adj-in",
11192 [PCOUNT_DAMPED
] = "Damped",
11193 [PCOUNT_REMOVED
] = "Removed",
11194 [PCOUNT_HISTORY
] = "History",
11195 [PCOUNT_STALE
] = "Stale",
11196 [PCOUNT_VALID
] = "Valid",
11197 [PCOUNT_ALL
] = "All RIB",
11198 [PCOUNT_COUNTED
] = "PfxCt counted",
11199 [PCOUNT_PFCNT
] = "Useable",
11200 [PCOUNT_MAX
] = NULL
,
11203 struct peer_pcounts
{
11204 unsigned int count
[PCOUNT_MAX
];
11205 const struct peer
*peer
;
11206 const struct bgp_table
*table
;
11210 static void bgp_peer_count_proc(struct bgp_node
*rn
,
11211 struct peer_pcounts
*pc
)
11213 const struct bgp_adj_in
*ain
;
11214 const struct bgp_path_info
*pi
;
11215 const struct peer
*peer
= pc
->peer
;
11217 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11218 if (ain
->peer
== peer
)
11219 pc
->count
[PCOUNT_ADJ_IN
]++;
11221 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11223 if (pi
->peer
!= peer
)
11226 pc
->count
[PCOUNT_ALL
]++;
11228 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11229 pc
->count
[PCOUNT_DAMPED
]++;
11230 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11231 pc
->count
[PCOUNT_HISTORY
]++;
11232 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11233 pc
->count
[PCOUNT_REMOVED
]++;
11234 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11235 pc
->count
[PCOUNT_STALE
]++;
11236 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11237 pc
->count
[PCOUNT_VALID
]++;
11238 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11239 pc
->count
[PCOUNT_PFCNT
]++;
11241 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11242 pc
->count
[PCOUNT_COUNTED
]++;
11243 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11245 EC_LIB_DEVELOPMENT
,
11246 "Attempting to count but flags say it is unusable");
11248 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11250 EC_LIB_DEVELOPMENT
,
11251 "Not counted but flags say we should");
11256 static int bgp_peer_count_walker(struct thread
*t
)
11258 struct bgp_node
*rn
, *rm
;
11259 const struct bgp_table
*table
;
11260 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11262 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11263 || pc
->safi
== SAFI_EVPN
) {
11264 /* Special handling for 2-level routing tables. */
11265 for (rn
= bgp_table_top(pc
->table
); rn
;
11266 rn
= bgp_route_next(rn
)) {
11267 table
= bgp_node_get_bgp_table_info(rn
);
11269 for (rm
= bgp_table_top(table
); rm
;
11270 rm
= bgp_route_next(rm
))
11271 bgp_peer_count_proc(rm
, pc
);
11274 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11275 bgp_peer_count_proc(rn
, pc
);
11280 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11281 safi_t safi
, bool use_json
)
11283 struct peer_pcounts pcounts
= {.peer
= peer
};
11285 json_object
*json
= NULL
;
11286 json_object
*json_loop
= NULL
;
11289 json
= json_object_new_object();
11290 json_loop
= json_object_new_object();
11293 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11294 || !peer
->bgp
->rib
[afi
][safi
]) {
11296 json_object_string_add(
11298 "No such neighbor or address family");
11299 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11300 json_object_free(json
);
11302 vty_out(vty
, "%% No such neighbor or address family\n");
11304 return CMD_WARNING
;
11307 memset(&pcounts
, 0, sizeof(pcounts
));
11308 pcounts
.peer
= peer
;
11309 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11310 pcounts
.safi
= safi
;
11312 /* in-place call via thread subsystem so as to record execution time
11313 * stats for the thread-walk (i.e. ensure this can't be blamed on
11314 * on just vty_read()).
11316 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11319 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11320 json_object_string_add(json
, "multiProtocol",
11321 get_afi_safi_str(afi
, safi
, true));
11322 json_object_int_add(json
, "pfxCounter",
11323 peer
->pcount
[afi
][safi
]);
11325 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11326 json_object_int_add(json_loop
, pcount_strs
[i
],
11329 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11331 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11332 json_object_string_add(json
, "pfxctDriftFor",
11334 json_object_string_add(
11335 json
, "recommended",
11336 "Please report this bug, with the above command output");
11338 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11339 json
, JSON_C_TO_STRING_PRETTY
));
11340 json_object_free(json
);
11344 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11345 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11346 peer
->hostname
, peer
->host
,
11347 get_afi_safi_str(afi
, safi
, false));
11349 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11350 get_afi_safi_str(afi
, safi
, false));
11353 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11354 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11356 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11357 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11360 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11361 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11363 "Please report this bug, with the above command output\n");
11367 return CMD_SUCCESS
;
11370 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11371 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11373 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11377 BGP_INSTANCE_HELP_STR
11380 "Detailed information on TCP and BGP neighbor connections\n"
11381 "Neighbor to display information about\n"
11382 "Neighbor to display information about\n"
11383 "Neighbor on BGP configured interface\n"
11384 "Display detailed prefix count information\n"
11387 afi_t afi
= AFI_IP6
;
11388 safi_t safi
= SAFI_UNICAST
;
11391 struct bgp
*bgp
= NULL
;
11392 bool uj
= use_json(argc
, argv
);
11397 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11400 return CMD_WARNING
;
11402 argv_find(argv
, argc
, "neighbors", &idx
);
11403 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11405 return CMD_WARNING
;
11407 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11410 #ifdef KEEP_OLD_VPN_COMMANDS
11411 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11412 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11413 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11418 "Display information about all VPNv4 NLRIs\n"
11419 "Detailed information on TCP and BGP neighbor connections\n"
11420 "Neighbor to display information about\n"
11421 "Neighbor to display information about\n"
11422 "Neighbor on BGP configured interface\n"
11423 "Display detailed prefix count information\n"
11428 bool uj
= use_json(argc
, argv
);
11430 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11432 return CMD_WARNING
;
11434 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11437 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11438 show_ip_bgp_vpn_all_route_prefix_cmd
,
11439 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11444 "Display information about all VPNv4 NLRIs\n"
11445 "Network in the BGP routing table to display\n"
11446 "Network in the BGP routing table to display\n"
11450 char *network
= NULL
;
11451 struct bgp
*bgp
= bgp_get_default();
11453 vty_out(vty
, "Can't find default instance\n");
11454 return CMD_WARNING
;
11457 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11458 network
= argv
[idx
]->arg
;
11459 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11460 network
= argv
[idx
]->arg
;
11462 vty_out(vty
, "Unable to figure out Network\n");
11463 return CMD_WARNING
;
11466 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11467 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11469 #endif /* KEEP_OLD_VPN_COMMANDS */
11471 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11472 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11473 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11478 "Network in the BGP routing table to display\n"
11479 "Network in the BGP routing table to display\n"
11480 "Network in the BGP routing table to display\n"
11481 "Network in the BGP routing table to display\n"
11485 char *network
= NULL
;
11486 int prefix_check
= 0;
11488 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11489 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11490 network
= argv
[idx
]->arg
;
11491 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11492 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11493 network
= argv
[idx
]->arg
;
11496 vty_out(vty
, "Unable to figure out Network\n");
11497 return CMD_WARNING
;
11499 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11500 prefix_check
, BGP_PATH_SHOW_ALL
,
11501 use_json(argc
, argv
));
11504 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11505 safi_t safi
, enum bgp_show_adj_route_type type
,
11506 const char *rmap_name
, bool use_json
,
11509 struct bgp_table
*table
;
11510 struct bgp_adj_in
*ain
;
11511 struct bgp_adj_out
*adj
;
11512 unsigned long output_count
;
11513 unsigned long filtered_count
;
11514 struct bgp_node
*rn
;
11520 struct update_subgroup
*subgrp
;
11521 json_object
*json_scode
= NULL
;
11522 json_object
*json_ocode
= NULL
;
11523 json_object
*json_ar
= NULL
;
11524 struct peer_af
*paf
;
11525 bool route_filtered
;
11528 json_scode
= json_object_new_object();
11529 json_ocode
= json_object_new_object();
11530 json_ar
= json_object_new_object();
11532 json_object_string_add(json_scode
, "suppressed", "s");
11533 json_object_string_add(json_scode
, "damped", "d");
11534 json_object_string_add(json_scode
, "history", "h");
11535 json_object_string_add(json_scode
, "valid", "*");
11536 json_object_string_add(json_scode
, "best", ">");
11537 json_object_string_add(json_scode
, "multipath", "=");
11538 json_object_string_add(json_scode
, "internal", "i");
11539 json_object_string_add(json_scode
, "ribFailure", "r");
11540 json_object_string_add(json_scode
, "stale", "S");
11541 json_object_string_add(json_scode
, "removed", "R");
11543 json_object_string_add(json_ocode
, "igp", "i");
11544 json_object_string_add(json_ocode
, "egp", "e");
11545 json_object_string_add(json_ocode
, "incomplete", "?");
11552 json_object_string_add(json
, "alert", "no BGP");
11553 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11554 json_object_free(json
);
11556 vty_out(vty
, "%% No bgp\n");
11560 /* labeled-unicast routes live in the unicast table */
11561 if (safi
== SAFI_LABELED_UNICAST
)
11562 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11564 table
= bgp
->rib
[afi
][safi
];
11566 output_count
= filtered_count
= 0;
11567 subgrp
= peer_subgroup(peer
, afi
, safi
);
11569 if (type
== bgp_show_adj_route_advertised
&& subgrp
11570 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11572 json_object_int_add(json
, "bgpTableVersion",
11574 json_object_string_add(json
, "bgpLocalRouterId",
11575 inet_ntoa(bgp
->router_id
));
11576 json_object_int_add(json
, "defaultLocPrf",
11577 bgp
->default_local_pref
);
11578 json_object_int_add(json
, "localAS", bgp
->as
);
11579 json_object_object_add(json
, "bgpStatusCodes",
11581 json_object_object_add(json
, "bgpOriginCodes",
11583 json_object_string_add(
11584 json
, "bgpOriginatingDefaultNetwork",
11585 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11587 vty_out(vty
, "BGP table version is %" PRIu64
11588 ", local router ID is %s, vrf id ",
11589 table
->version
, inet_ntoa(bgp
->router_id
));
11590 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11591 vty_out(vty
, "%s", VRFID_NONE_STR
);
11593 vty_out(vty
, "%u", bgp
->vrf_id
);
11594 vty_out(vty
, "\n");
11595 vty_out(vty
, "Default local pref %u, ",
11596 bgp
->default_local_pref
);
11597 vty_out(vty
, "local AS %u\n", bgp
->as
);
11598 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11599 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11600 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11602 vty_out(vty
, "Originating default network %s\n\n",
11603 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11608 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11609 if (type
== bgp_show_adj_route_received
11610 || type
== bgp_show_adj_route_filtered
) {
11611 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11612 if (ain
->peer
!= peer
)
11617 json_object_int_add(
11618 json
, "bgpTableVersion",
11620 json_object_string_add(
11622 "bgpLocalRouterId",
11625 json_object_int_add(json
,
11627 bgp
->default_local_pref
);
11628 json_object_int_add(json
,
11629 "localAS", bgp
->as
);
11630 json_object_object_add(
11631 json
, "bgpStatusCodes",
11633 json_object_object_add(
11634 json
, "bgpOriginCodes",
11638 "BGP table version is 0, local router ID is %s, vrf id ",
11641 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11647 vty_out(vty
, "\n");
11649 "Default local pref %u, ",
11650 bgp
->default_local_pref
);
11651 vty_out(vty
, "local AS %u\n",
11654 BGP_SHOW_SCODE_HEADER
);
11656 BGP_SHOW_NCODE_HEADER
);
11658 BGP_SHOW_OCODE_HEADER
);
11664 vty_out(vty
, BGP_SHOW_HEADER
);
11669 route_filtered
= false;
11671 /* Filter prefix using distribute list,
11672 * filter list or prefix list
11674 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11675 safi
)) == FILTER_DENY
)
11676 route_filtered
= true;
11678 /* Filter prefix using route-map */
11679 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11680 afi
, safi
, rmap_name
, NULL
, 0,
11683 if (type
== bgp_show_adj_route_filtered
&&
11684 !route_filtered
&& ret
!= RMAP_DENY
) {
11685 bgp_attr_undup(&attr
, ain
->attr
);
11689 if (type
== bgp_show_adj_route_received
&&
11690 (route_filtered
|| ret
== RMAP_DENY
))
11693 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11694 use_json
, json_ar
);
11695 bgp_attr_undup(&attr
, ain
->attr
);
11698 } else if (type
== bgp_show_adj_route_advertised
) {
11699 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11700 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11701 if (paf
->peer
!= peer
|| !adj
->attr
)
11706 json_object_int_add(
11710 json_object_string_add(
11712 "bgpLocalRouterId",
11715 json_object_int_add(
11716 json
, "defaultLocPrf",
11717 bgp
->default_local_pref
11719 json_object_int_add(
11722 json_object_object_add(
11726 json_object_object_add(
11732 "BGP table version is %" PRIu64
11733 ", local router ID is %s, vrf id ",
11746 vty_out(vty
, "\n");
11748 "Default local pref %u, ",
11749 bgp
->default_local_pref
11755 BGP_SHOW_SCODE_HEADER
);
11757 BGP_SHOW_NCODE_HEADER
);
11759 BGP_SHOW_OCODE_HEADER
);
11771 ret
= bgp_output_modifier(
11772 peer
, &rn
->p
, &attr
, afi
, safi
,
11775 if (ret
!= RMAP_DENY
) {
11776 route_vty_out_tmp(vty
, &rn
->p
,
11785 bgp_attr_undup(&attr
, adj
->attr
);
11791 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11792 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11793 json_object_int_add(json
, "filteredPrefixCounter",
11796 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11797 json
, JSON_C_TO_STRING_PRETTY
));
11798 json_object_free(json
);
11799 } else if (output_count
> 0) {
11800 if (filtered_count
> 0)
11802 "\nTotal number of prefixes %ld (%ld filtered)\n",
11803 output_count
, filtered_count
);
11805 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11810 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11811 safi_t safi
, enum bgp_show_adj_route_type type
,
11812 const char *rmap_name
, bool use_json
)
11814 json_object
*json
= NULL
;
11817 json
= json_object_new_object();
11819 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11821 json_object_string_add(
11823 "No such neighbor or address family");
11824 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11825 json_object_free(json
);
11827 vty_out(vty
, "%% No such neighbor or address family\n");
11829 return CMD_WARNING
;
11832 if ((type
== bgp_show_adj_route_received
11833 || type
== bgp_show_adj_route_filtered
)
11834 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11835 PEER_FLAG_SOFT_RECONFIG
)) {
11837 json_object_string_add(
11839 "Inbound soft reconfiguration not enabled");
11840 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11841 json_object_free(json
);
11844 "%% Inbound soft reconfiguration not enabled\n");
11846 return CMD_WARNING
;
11849 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11851 return CMD_SUCCESS
;
11854 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11855 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11856 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11857 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11861 BGP_INSTANCE_HELP_STR
11863 BGP_SAFI_WITH_LABEL_HELP_STR
11864 "Detailed information on TCP and BGP neighbor connections\n"
11865 "Neighbor to display information about\n"
11866 "Neighbor to display information about\n"
11867 "Neighbor on BGP configured interface\n"
11868 "Display the routes advertised to a BGP neighbor\n"
11869 "Display the received routes from neighbor\n"
11870 "Display the filtered routes received from neighbor\n"
11871 "Route-map to modify the attributes\n"
11872 "Name of the route map\n"
11875 afi_t afi
= AFI_IP6
;
11876 safi_t safi
= SAFI_UNICAST
;
11877 char *rmap_name
= NULL
;
11878 char *peerstr
= NULL
;
11879 struct bgp
*bgp
= NULL
;
11881 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11883 bool uj
= use_json(argc
, argv
);
11888 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11891 return CMD_WARNING
;
11893 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11894 argv_find(argv
, argc
, "neighbors", &idx
);
11895 peerstr
= argv
[++idx
]->arg
;
11897 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11899 return CMD_WARNING
;
11901 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11902 type
= bgp_show_adj_route_advertised
;
11903 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11904 type
= bgp_show_adj_route_received
;
11905 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11906 type
= bgp_show_adj_route_filtered
;
11908 if (argv_find(argv
, argc
, "route-map", &idx
))
11909 rmap_name
= argv
[++idx
]->arg
;
11911 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11914 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11915 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11916 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11922 "Address Family modifier\n"
11923 "Detailed information on TCP and BGP neighbor connections\n"
11924 "Neighbor to display information about\n"
11925 "Neighbor to display information about\n"
11926 "Neighbor on BGP configured interface\n"
11927 "Display information received from a BGP neighbor\n"
11928 "Display the prefixlist filter\n"
11931 afi_t afi
= AFI_IP6
;
11932 safi_t safi
= SAFI_UNICAST
;
11933 char *peerstr
= NULL
;
11936 union sockunion su
;
11942 /* show [ip] bgp */
11943 if (argv_find(argv
, argc
, "ip", &idx
))
11945 /* [<ipv4|ipv6> [unicast]] */
11946 if (argv_find(argv
, argc
, "ipv4", &idx
))
11948 if (argv_find(argv
, argc
, "ipv6", &idx
))
11950 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11951 argv_find(argv
, argc
, "neighbors", &idx
);
11952 peerstr
= argv
[++idx
]->arg
;
11954 bool uj
= use_json(argc
, argv
);
11956 ret
= str2sockunion(peerstr
, &su
);
11958 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11961 vty_out(vty
, "{}\n");
11964 "%% Malformed address or name: %s\n",
11966 return CMD_WARNING
;
11969 peer
= peer_lookup(NULL
, &su
);
11972 vty_out(vty
, "{}\n");
11974 vty_out(vty
, "No peer\n");
11975 return CMD_WARNING
;
11979 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11980 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11983 vty_out(vty
, "Address Family: %s\n",
11984 get_afi_safi_str(afi
, safi
, false));
11985 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11988 vty_out(vty
, "{}\n");
11990 vty_out(vty
, "No functional output\n");
11993 return CMD_SUCCESS
;
11996 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11997 afi_t afi
, safi_t safi
,
11998 enum bgp_show_type type
, bool use_json
)
12000 /* labeled-unicast routes live in the unicast table */
12001 if (safi
== SAFI_LABELED_UNICAST
)
12002 safi
= SAFI_UNICAST
;
12004 if (!peer
|| !peer
->afc
[afi
][safi
]) {
12006 json_object
*json_no
= NULL
;
12007 json_no
= json_object_new_object();
12008 json_object_string_add(
12009 json_no
, "warning",
12010 "No such neighbor or address family");
12011 vty_out(vty
, "%s\n",
12012 json_object_to_json_string(json_no
));
12013 json_object_free(json_no
);
12015 vty_out(vty
, "%% No such neighbor or address family\n");
12016 return CMD_WARNING
;
12019 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
12022 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
12023 show_ip_bgp_flowspec_routes_detailed_cmd
,
12024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12028 BGP_INSTANCE_HELP_STR
12031 "Detailed information on flowspec entries\n"
12034 afi_t afi
= AFI_IP
;
12035 safi_t safi
= SAFI_UNICAST
;
12036 struct bgp
*bgp
= NULL
;
12038 bool uj
= use_json(argc
, argv
);
12043 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12046 return CMD_WARNING
;
12048 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
12051 DEFUN (show_ip_bgp_neighbor_routes
,
12052 show_ip_bgp_neighbor_routes_cmd
,
12053 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12054 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
12058 BGP_INSTANCE_HELP_STR
12060 BGP_SAFI_WITH_LABEL_HELP_STR
12061 "Detailed information on TCP and BGP neighbor connections\n"
12062 "Neighbor to display information about\n"
12063 "Neighbor to display information about\n"
12064 "Neighbor on BGP configured interface\n"
12065 "Display flap statistics of the routes learned from neighbor\n"
12066 "Display the dampened routes received from neighbor\n"
12067 "Display routes learned from neighbor\n"
12070 char *peerstr
= NULL
;
12071 struct bgp
*bgp
= NULL
;
12072 afi_t afi
= AFI_IP6
;
12073 safi_t safi
= SAFI_UNICAST
;
12075 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12077 bool uj
= use_json(argc
, argv
);
12082 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12085 return CMD_WARNING
;
12087 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12088 argv_find(argv
, argc
, "neighbors", &idx
);
12089 peerstr
= argv
[++idx
]->arg
;
12091 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12093 return CMD_WARNING
;
12095 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12096 sh_type
= bgp_show_type_flap_neighbor
;
12097 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12098 sh_type
= bgp_show_type_damp_neighbor
;
12099 else if (argv_find(argv
, argc
, "routes", &idx
))
12100 sh_type
= bgp_show_type_neighbor
;
12102 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12105 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12107 struct bgp_distance
{
12108 /* Distance value for the IP source prefix. */
12111 /* Name of the access-list to be matched. */
12115 DEFUN (show_bgp_afi_vpn_rd_route
,
12116 show_bgp_afi_vpn_rd_route_cmd
,
12117 "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]",
12121 "Address Family modifier\n"
12122 "Display information for a route distinguisher\n"
12123 "Route Distinguisher\n"
12124 "Network in the BGP routing table to display\n"
12125 "Network in the BGP routing table to display\n"
12129 struct prefix_rd prd
;
12130 afi_t afi
= AFI_MAX
;
12133 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12134 vty_out(vty
, "%% Malformed Address Family\n");
12135 return CMD_WARNING
;
12138 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12140 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12141 return CMD_WARNING
;
12144 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12145 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12148 static struct bgp_distance
*bgp_distance_new(void)
12150 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12153 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12155 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12158 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12159 const char *ip_str
, const char *access_list_str
)
12166 struct bgp_node
*rn
;
12167 struct bgp_distance
*bdistance
;
12169 afi
= bgp_node_afi(vty
);
12170 safi
= bgp_node_safi(vty
);
12172 ret
= str2prefix(ip_str
, &p
);
12174 vty_out(vty
, "Malformed prefix\n");
12175 return CMD_WARNING_CONFIG_FAILED
;
12178 distance
= atoi(distance_str
);
12180 /* Get BGP distance node. */
12181 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
12182 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12184 bgp_unlock_node(rn
);
12186 bdistance
= bgp_distance_new();
12187 bgp_node_set_bgp_distance_info(rn
, bdistance
);
12190 /* Set distance value. */
12191 bdistance
->distance
= distance
;
12193 /* Reset access-list configuration. */
12194 if (bdistance
->access_list
) {
12195 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12196 bdistance
->access_list
= NULL
;
12198 if (access_list_str
)
12199 bdistance
->access_list
=
12200 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12202 return CMD_SUCCESS
;
12205 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12206 const char *ip_str
, const char *access_list_str
)
12213 struct bgp_node
*rn
;
12214 struct bgp_distance
*bdistance
;
12216 afi
= bgp_node_afi(vty
);
12217 safi
= bgp_node_safi(vty
);
12219 ret
= str2prefix(ip_str
, &p
);
12221 vty_out(vty
, "Malformed prefix\n");
12222 return CMD_WARNING_CONFIG_FAILED
;
12225 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
12226 (struct prefix
*)&p
);
12228 vty_out(vty
, "Can't find specified prefix\n");
12229 return CMD_WARNING_CONFIG_FAILED
;
12232 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12233 distance
= atoi(distance_str
);
12235 if (bdistance
->distance
!= distance
) {
12236 vty_out(vty
, "Distance does not match configured\n");
12237 return CMD_WARNING_CONFIG_FAILED
;
12240 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12241 bgp_distance_free(bdistance
);
12243 bgp_node_set_bgp_path_info(rn
, NULL
);
12244 bgp_unlock_node(rn
);
12245 bgp_unlock_node(rn
);
12247 return CMD_SUCCESS
;
12250 /* Apply BGP information to distance method. */
12251 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
12252 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12254 struct bgp_node
*rn
;
12257 struct bgp_distance
*bdistance
;
12258 struct access_list
*alist
;
12259 struct bgp_static
*bgp_static
;
12264 peer
= pinfo
->peer
;
12266 if (pinfo
->attr
->distance
)
12267 return pinfo
->attr
->distance
;
12269 /* Check source address. */
12270 sockunion2hostprefix(&peer
->su
, &q
);
12271 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12273 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12274 bgp_unlock_node(rn
);
12276 if (bdistance
->access_list
) {
12277 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12279 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12280 return bdistance
->distance
;
12282 return bdistance
->distance
;
12285 /* Backdoor check. */
12286 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12288 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12289 bgp_unlock_node(rn
);
12291 if (bgp_static
->backdoor
) {
12292 if (bgp
->distance_local
[afi
][safi
])
12293 return bgp
->distance_local
[afi
][safi
];
12295 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12299 if (peer
->sort
== BGP_PEER_EBGP
) {
12300 if (bgp
->distance_ebgp
[afi
][safi
])
12301 return bgp
->distance_ebgp
[afi
][safi
];
12302 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12304 if (bgp
->distance_ibgp
[afi
][safi
])
12305 return bgp
->distance_ibgp
[afi
][safi
];
12306 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12310 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12311 * we should tell ZEBRA update the routes for a specific
12312 * AFI/SAFI to reflect changes in RIB.
12314 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12316 safi_t update_safi
)
12321 FOREACH_AFI_SAFI (afi
, safi
) {
12322 if (!bgp_fibupd_safi(safi
))
12325 if (afi
!= update_afi
&& safi
!= update_safi
)
12328 if (BGP_DEBUG(zebra
, ZEBRA
))
12330 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12331 __func__
, afi
, safi
);
12332 bgp_zebra_announce_table(bgp
, afi
, safi
);
12336 DEFUN (bgp_distance
,
12338 "distance bgp (1-255) (1-255) (1-255)",
12339 "Define an administrative distance\n"
12341 "Distance for routes external to the AS\n"
12342 "Distance for routes internal to the AS\n"
12343 "Distance for local routes\n")
12345 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12346 int idx_number
= 2;
12347 int idx_number_2
= 3;
12348 int idx_number_3
= 4;
12349 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12350 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12351 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12355 afi
= bgp_node_afi(vty
);
12356 safi
= bgp_node_safi(vty
);
12358 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12359 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12360 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12361 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12362 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12363 bgp
->distance_local
[afi
][safi
] = distance_local
;
12364 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12366 return CMD_SUCCESS
;
12369 DEFUN (no_bgp_distance
,
12370 no_bgp_distance_cmd
,
12371 "no distance bgp [(1-255) (1-255) (1-255)]",
12373 "Define an administrative distance\n"
12375 "Distance for routes external to the AS\n"
12376 "Distance for routes internal to the AS\n"
12377 "Distance for local routes\n")
12379 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12383 afi
= bgp_node_afi(vty
);
12384 safi
= bgp_node_safi(vty
);
12386 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12387 || bgp
->distance_ibgp
[afi
][safi
] != 0
12388 || bgp
->distance_local
[afi
][safi
] != 0) {
12389 bgp
->distance_ebgp
[afi
][safi
] = 0;
12390 bgp
->distance_ibgp
[afi
][safi
] = 0;
12391 bgp
->distance_local
[afi
][safi
] = 0;
12392 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12394 return CMD_SUCCESS
;
12398 DEFUN (bgp_distance_source
,
12399 bgp_distance_source_cmd
,
12400 "distance (1-255) A.B.C.D/M",
12401 "Define an administrative distance\n"
12402 "Administrative distance\n"
12403 "IP source prefix\n")
12405 int idx_number
= 1;
12406 int idx_ipv4_prefixlen
= 2;
12407 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12408 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12409 return CMD_SUCCESS
;
12412 DEFUN (no_bgp_distance_source
,
12413 no_bgp_distance_source_cmd
,
12414 "no distance (1-255) A.B.C.D/M",
12416 "Define an administrative distance\n"
12417 "Administrative distance\n"
12418 "IP source prefix\n")
12420 int idx_number
= 2;
12421 int idx_ipv4_prefixlen
= 3;
12422 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12423 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12424 return CMD_SUCCESS
;
12427 DEFUN (bgp_distance_source_access_list
,
12428 bgp_distance_source_access_list_cmd
,
12429 "distance (1-255) A.B.C.D/M WORD",
12430 "Define an administrative distance\n"
12431 "Administrative distance\n"
12432 "IP source prefix\n"
12433 "Access list name\n")
12435 int idx_number
= 1;
12436 int idx_ipv4_prefixlen
= 2;
12438 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12439 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12440 return CMD_SUCCESS
;
12443 DEFUN (no_bgp_distance_source_access_list
,
12444 no_bgp_distance_source_access_list_cmd
,
12445 "no distance (1-255) A.B.C.D/M WORD",
12447 "Define an administrative distance\n"
12448 "Administrative distance\n"
12449 "IP source prefix\n"
12450 "Access list name\n")
12452 int idx_number
= 2;
12453 int idx_ipv4_prefixlen
= 3;
12455 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12456 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12457 return CMD_SUCCESS
;
12460 DEFUN (ipv6_bgp_distance_source
,
12461 ipv6_bgp_distance_source_cmd
,
12462 "distance (1-255) X:X::X:X/M",
12463 "Define an administrative distance\n"
12464 "Administrative distance\n"
12465 "IP source prefix\n")
12467 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12468 return CMD_SUCCESS
;
12471 DEFUN (no_ipv6_bgp_distance_source
,
12472 no_ipv6_bgp_distance_source_cmd
,
12473 "no distance (1-255) X:X::X:X/M",
12475 "Define an administrative distance\n"
12476 "Administrative distance\n"
12477 "IP source prefix\n")
12479 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12480 return CMD_SUCCESS
;
12483 DEFUN (ipv6_bgp_distance_source_access_list
,
12484 ipv6_bgp_distance_source_access_list_cmd
,
12485 "distance (1-255) X:X::X:X/M WORD",
12486 "Define an administrative distance\n"
12487 "Administrative distance\n"
12488 "IP source prefix\n"
12489 "Access list name\n")
12491 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12492 return CMD_SUCCESS
;
12495 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12496 no_ipv6_bgp_distance_source_access_list_cmd
,
12497 "no distance (1-255) X:X::X:X/M WORD",
12499 "Define an administrative distance\n"
12500 "Administrative distance\n"
12501 "IP source prefix\n"
12502 "Access list name\n")
12504 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12505 return CMD_SUCCESS
;
12508 DEFUN (bgp_damp_set
,
12510 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12511 "BGP Specific commands\n"
12512 "Enable route-flap dampening\n"
12513 "Half-life time for the penalty\n"
12514 "Value to start reusing a route\n"
12515 "Value to start suppressing a route\n"
12516 "Maximum duration to suppress a stable route\n")
12518 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12519 int idx_half_life
= 2;
12521 int idx_suppress
= 4;
12522 int idx_max_suppress
= 5;
12523 int half
= DEFAULT_HALF_LIFE
* 60;
12524 int reuse
= DEFAULT_REUSE
;
12525 int suppress
= DEFAULT_SUPPRESS
;
12526 int max
= 4 * half
;
12529 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12530 reuse
= atoi(argv
[idx_reuse
]->arg
);
12531 suppress
= atoi(argv
[idx_suppress
]->arg
);
12532 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12533 } else if (argc
== 3) {
12534 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12539 * These can't be 0 but our SA doesn't understand the
12540 * way our cli is constructed
12544 if (suppress
< reuse
) {
12546 "Suppress value cannot be less than reuse value \n");
12550 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12551 reuse
, suppress
, max
);
12554 DEFUN (bgp_damp_unset
,
12555 bgp_damp_unset_cmd
,
12556 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12558 "BGP Specific commands\n"
12559 "Enable route-flap dampening\n"
12560 "Half-life time for the penalty\n"
12561 "Value to start reusing a route\n"
12562 "Value to start suppressing a route\n"
12563 "Maximum duration to suppress a stable route\n")
12565 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12566 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12569 /* Display specified route of BGP table. */
12570 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12571 const char *ip_str
, afi_t afi
, safi_t safi
,
12572 struct prefix_rd
*prd
, int prefix_check
)
12575 struct prefix match
;
12576 struct bgp_node
*rn
;
12577 struct bgp_node
*rm
;
12578 struct bgp_path_info
*pi
;
12579 struct bgp_path_info
*pi_temp
;
12581 struct bgp_table
*table
;
12583 /* BGP structure lookup. */
12585 bgp
= bgp_lookup_by_name(view_name
);
12587 vty_out(vty
, "%% Can't find BGP instance %s\n",
12589 return CMD_WARNING
;
12592 bgp
= bgp_get_default();
12594 vty_out(vty
, "%% No BGP process is configured\n");
12595 return CMD_WARNING
;
12599 /* Check IP address argument. */
12600 ret
= str2prefix(ip_str
, &match
);
12602 vty_out(vty
, "%% address is malformed\n");
12603 return CMD_WARNING
;
12606 match
.family
= afi2family(afi
);
12608 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12609 || (safi
== SAFI_EVPN
)) {
12610 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12611 rn
= bgp_route_next(rn
)) {
12612 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12614 table
= bgp_node_get_bgp_table_info(rn
);
12617 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12621 || rm
->p
.prefixlen
== match
.prefixlen
) {
12622 pi
= bgp_node_get_bgp_path_info(rm
);
12624 if (pi
->extra
&& pi
->extra
->damp_info
) {
12625 pi_temp
= pi
->next
;
12626 bgp_damp_info_free(
12627 pi
->extra
->damp_info
,
12635 bgp_unlock_node(rm
);
12638 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12641 || rn
->p
.prefixlen
== match
.prefixlen
) {
12642 pi
= bgp_node_get_bgp_path_info(rn
);
12644 if (pi
->extra
&& pi
->extra
->damp_info
) {
12645 pi_temp
= pi
->next
;
12646 bgp_damp_info_free(
12647 pi
->extra
->damp_info
,
12655 bgp_unlock_node(rn
);
12659 return CMD_SUCCESS
;
12662 DEFUN (clear_ip_bgp_dampening
,
12663 clear_ip_bgp_dampening_cmd
,
12664 "clear ip bgp dampening",
12668 "Clear route flap dampening information\n")
12670 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12671 return CMD_SUCCESS
;
12674 DEFUN (clear_ip_bgp_dampening_prefix
,
12675 clear_ip_bgp_dampening_prefix_cmd
,
12676 "clear ip bgp dampening A.B.C.D/M",
12680 "Clear route flap dampening information\n"
12683 int idx_ipv4_prefixlen
= 4;
12684 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12685 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12688 DEFUN (clear_ip_bgp_dampening_address
,
12689 clear_ip_bgp_dampening_address_cmd
,
12690 "clear ip bgp dampening A.B.C.D",
12694 "Clear route flap dampening information\n"
12695 "Network to clear damping information\n")
12698 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12699 SAFI_UNICAST
, NULL
, 0);
12702 DEFUN (clear_ip_bgp_dampening_address_mask
,
12703 clear_ip_bgp_dampening_address_mask_cmd
,
12704 "clear ip bgp dampening A.B.C.D A.B.C.D",
12708 "Clear route flap dampening information\n"
12709 "Network to clear damping information\n"
12713 int idx_ipv4_2
= 5;
12715 char prefix_str
[BUFSIZ
];
12717 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12720 vty_out(vty
, "%% Inconsistent address and mask\n");
12721 return CMD_WARNING
;
12724 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12728 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12730 struct vty
*vty
= arg
;
12731 struct peer
*peer
= bucket
->data
;
12732 char buf
[SU_ADDRSTRLEN
];
12734 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12735 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12738 DEFUN (show_bgp_peerhash
,
12739 show_bgp_peerhash_cmd
,
12740 "show bgp peerhash",
12743 "Display information about the BGP peerhash\n")
12745 struct list
*instances
= bm
->bgp
;
12746 struct listnode
*node
;
12749 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12750 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12751 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12755 return CMD_SUCCESS
;
12758 /* also used for encap safi */
12759 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12760 afi_t afi
, safi_t safi
)
12762 struct bgp_node
*prn
;
12763 struct bgp_node
*rn
;
12764 struct bgp_table
*table
;
12766 struct prefix_rd
*prd
;
12767 struct bgp_static
*bgp_static
;
12768 mpls_label_t label
;
12769 char buf
[SU_ADDRSTRLEN
];
12770 char rdbuf
[RD_ADDRSTRLEN
];
12772 /* Network configuration. */
12773 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12774 prn
= bgp_route_next(prn
)) {
12775 table
= bgp_node_get_bgp_table_info(prn
);
12779 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12780 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12781 if (bgp_static
== NULL
)
12785 prd
= (struct prefix_rd
*)&prn
->p
;
12787 /* "network" configuration display. */
12788 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12789 label
= decode_label(&bgp_static
->label
);
12791 vty_out(vty
, " network %s/%d rd %s",
12792 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12794 p
->prefixlen
, rdbuf
);
12795 if (safi
== SAFI_MPLS_VPN
)
12796 vty_out(vty
, " label %u", label
);
12798 if (bgp_static
->rmap
.name
)
12799 vty_out(vty
, " route-map %s",
12800 bgp_static
->rmap
.name
);
12802 if (bgp_static
->backdoor
)
12803 vty_out(vty
, " backdoor");
12805 vty_out(vty
, "\n");
12810 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12811 afi_t afi
, safi_t safi
)
12813 struct bgp_node
*prn
;
12814 struct bgp_node
*rn
;
12815 struct bgp_table
*table
;
12817 struct prefix_rd
*prd
;
12818 struct bgp_static
*bgp_static
;
12819 char buf
[PREFIX_STRLEN
* 2];
12820 char buf2
[SU_ADDRSTRLEN
];
12821 char rdbuf
[RD_ADDRSTRLEN
];
12823 /* Network configuration. */
12824 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12825 prn
= bgp_route_next(prn
)) {
12826 table
= bgp_node_get_bgp_table_info(prn
);
12830 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12831 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12832 if (bgp_static
== NULL
)
12835 char *macrouter
= NULL
;
12838 if (bgp_static
->router_mac
)
12839 macrouter
= prefix_mac2str(
12840 bgp_static
->router_mac
, NULL
, 0);
12841 if (bgp_static
->eth_s_id
)
12842 esi
= esi2str(bgp_static
->eth_s_id
);
12844 prd
= (struct prefix_rd
*)&prn
->p
;
12846 /* "network" configuration display. */
12847 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12848 if (p
->u
.prefix_evpn
.route_type
== 5) {
12849 char local_buf
[PREFIX_STRLEN
];
12850 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12851 struct prefix_evpn
*)p
)
12855 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12856 local_buf
, PREFIX_STRLEN
);
12857 sprintf(buf
, "%s/%u", local_buf
,
12858 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12860 prefix2str(p
, buf
, sizeof(buf
));
12863 if (bgp_static
->gatewayIp
.family
== AF_INET
12864 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12865 inet_ntop(bgp_static
->gatewayIp
.family
,
12866 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12869 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12871 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12872 decode_label(&bgp_static
->label
), esi
, buf2
,
12875 XFREE(MTYPE_TMP
, macrouter
);
12876 XFREE(MTYPE_TMP
, esi
);
12881 /* Configuration of static route announcement and aggregate
12883 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12886 struct bgp_node
*rn
;
12888 struct bgp_static
*bgp_static
;
12889 struct bgp_aggregate
*bgp_aggregate
;
12890 char buf
[SU_ADDRSTRLEN
];
12892 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12893 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12897 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12898 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12902 /* Network configuration. */
12903 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12904 rn
= bgp_route_next(rn
)) {
12905 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12906 if (bgp_static
== NULL
)
12911 vty_out(vty
, " network %s/%d",
12912 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12915 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12916 vty_out(vty
, " label-index %u",
12917 bgp_static
->label_index
);
12919 if (bgp_static
->rmap
.name
)
12920 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12922 if (bgp_static
->backdoor
)
12923 vty_out(vty
, " backdoor");
12925 vty_out(vty
, "\n");
12928 /* Aggregate-address configuration. */
12929 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12930 rn
= bgp_route_next(rn
)) {
12931 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12932 if (bgp_aggregate
== NULL
)
12937 vty_out(vty
, " aggregate-address %s/%d",
12938 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12941 if (bgp_aggregate
->as_set
)
12942 vty_out(vty
, " as-set");
12944 if (bgp_aggregate
->summary_only
)
12945 vty_out(vty
, " summary-only");
12947 if (bgp_aggregate
->rmap
.name
)
12948 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12950 vty_out(vty
, "\n");
12954 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12957 struct bgp_node
*rn
;
12958 struct bgp_distance
*bdistance
;
12960 /* Distance configuration. */
12961 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12962 && bgp
->distance_local
[afi
][safi
]
12963 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12964 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12965 || bgp
->distance_local
[afi
][safi
]
12966 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12967 vty_out(vty
, " distance bgp %d %d %d\n",
12968 bgp
->distance_ebgp
[afi
][safi
],
12969 bgp
->distance_ibgp
[afi
][safi
],
12970 bgp
->distance_local
[afi
][safi
]);
12973 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12974 rn
= bgp_route_next(rn
)) {
12975 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12976 if (bdistance
!= NULL
) {
12977 char buf
[PREFIX_STRLEN
];
12979 vty_out(vty
, " distance %d %s %s\n",
12980 bdistance
->distance
,
12981 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12982 bdistance
->access_list
? bdistance
->access_list
12988 /* Allocate routing table structure and install commands. */
12989 void bgp_route_init(void)
12994 /* Init BGP distance table. */
12995 FOREACH_AFI_SAFI (afi
, safi
)
12996 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12998 /* IPv4 BGP commands. */
12999 install_element(BGP_NODE
, &bgp_table_map_cmd
);
13000 install_element(BGP_NODE
, &bgp_network_cmd
);
13001 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
13003 install_element(BGP_NODE
, &aggregate_address_cmd
);
13004 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
13005 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
13006 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
13008 /* IPv4 unicast configuration. */
13009 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
13010 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
13011 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
13013 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
13014 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
13015 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
13016 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
13018 /* IPv4 multicast configuration. */
13019 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
13020 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
13021 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
13022 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
13023 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
13024 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
13025 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13027 /* IPv4 labeled-unicast configuration. */
13028 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13029 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13030 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13031 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13032 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13034 install_element(VIEW_NODE
,
13035 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13036 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13037 install_element(VIEW_NODE
,
13038 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13039 #ifdef KEEP_OLD_VPN_COMMANDS
13040 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13041 #endif /* KEEP_OLD_VPN_COMMANDS */
13042 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13043 install_element(VIEW_NODE
,
13044 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13046 /* BGP dampening clear commands */
13047 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13048 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13050 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13051 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13054 install_element(ENABLE_NODE
,
13055 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13056 #ifdef KEEP_OLD_VPN_COMMANDS
13057 install_element(ENABLE_NODE
,
13058 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13059 #endif /* KEEP_OLD_VPN_COMMANDS */
13061 /* New config IPv6 BGP commands. */
13062 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13063 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13064 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13066 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13067 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13069 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13071 install_element(BGP_NODE
, &bgp_distance_cmd
);
13072 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13073 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13074 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13075 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13076 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13077 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13078 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13079 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13080 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13081 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13082 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13083 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13084 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13085 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13086 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13087 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13088 install_element(BGP_IPV4M_NODE
,
13089 &no_bgp_distance_source_access_list_cmd
);
13090 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13091 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13092 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13093 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13094 install_element(BGP_IPV6_NODE
,
13095 &ipv6_bgp_distance_source_access_list_cmd
);
13096 install_element(BGP_IPV6_NODE
,
13097 &no_ipv6_bgp_distance_source_access_list_cmd
);
13098 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13099 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13100 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13101 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13102 install_element(BGP_IPV6M_NODE
,
13103 &ipv6_bgp_distance_source_access_list_cmd
);
13104 install_element(BGP_IPV6M_NODE
,
13105 &no_ipv6_bgp_distance_source_access_list_cmd
);
13107 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13108 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13109 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13110 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13112 /* IPv4 Multicast Mode */
13113 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13114 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13116 /* Large Communities */
13117 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13118 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13120 /* show bgp ipv4 flowspec detailed */
13121 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13123 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13126 void bgp_route_finish(void)
13131 FOREACH_AFI_SAFI (afi
, safi
) {
13132 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13133 bgp_distance_table
[afi
][safi
] = NULL
;