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"
42 #include "lib_errors.h"
44 #include "bgpd/bgpd.h"
45 #include "bgpd/bgp_table.h"
46 #include "bgpd/bgp_route.h"
47 #include "bgpd/bgp_attr.h"
48 #include "bgpd/bgp_debug.h"
49 #include "bgpd/bgp_errors.h"
50 #include "bgpd/bgp_aspath.h"
51 #include "bgpd/bgp_regex.h"
52 #include "bgpd/bgp_community.h"
53 #include "bgpd/bgp_ecommunity.h"
54 #include "bgpd/bgp_lcommunity.h"
55 #include "bgpd/bgp_clist.h"
56 #include "bgpd/bgp_packet.h"
57 #include "bgpd/bgp_filter.h"
58 #include "bgpd/bgp_fsm.h"
59 #include "bgpd/bgp_mplsvpn.h"
60 #include "bgpd/bgp_nexthop.h"
61 #include "bgpd/bgp_damp.h"
62 #include "bgpd/bgp_advertise.h"
63 #include "bgpd/bgp_zebra.h"
64 #include "bgpd/bgp_vty.h"
65 #include "bgpd/bgp_mpath.h"
66 #include "bgpd/bgp_nht.h"
67 #include "bgpd/bgp_updgrp.h"
68 #include "bgpd/bgp_label.h"
69 #include "bgpd/bgp_addpath.h"
70 #include "bgpd/bgp_mac.h"
73 #include "bgpd/rfapi/rfapi_backend.h"
74 #include "bgpd/rfapi/vnc_import_bgp.h"
75 #include "bgpd/rfapi/vnc_export_bgp.h"
77 #include "bgpd/bgp_encap_types.h"
78 #include "bgpd/bgp_encap_tlv.h"
79 #include "bgpd/bgp_evpn.h"
80 #include "bgpd/bgp_evpn_vty.h"
81 #include "bgpd/bgp_flowspec.h"
82 #include "bgpd/bgp_flowspec_util.h"
83 #include "bgpd/bgp_pbr.h"
85 #ifndef VTYSH_EXTRACT_PL
86 #include "bgpd/bgp_route_clippy.c"
89 /* Extern from bgp_dump.c */
90 extern const char *bgp_origin_str
[];
91 extern const char *bgp_origin_long_str
[];
92 const char *get_afi_safi_str(afi_t afi
,
93 safi_t safi
, bool for_json
);
95 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
96 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
97 static const struct message bgp_pmsi_tnltype_str
[] = {
98 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
99 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
100 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
101 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
102 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
103 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
104 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
105 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
109 #define VRFID_NONE_STR "-"
111 DEFINE_HOOK(bgp_process
,
112 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
113 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
114 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
117 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
118 safi_t safi
, struct prefix
*p
,
119 struct prefix_rd
*prd
)
122 struct bgp_node
*prn
= NULL
;
128 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
129 || (safi
== SAFI_EVPN
)) {
130 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
132 if (!bgp_node_has_bgp_path_info_data(prn
))
133 bgp_node_set_bgp_table_info(
134 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
136 bgp_unlock_node(prn
);
137 table
= bgp_node_get_bgp_table_info(prn
);
140 rn
= bgp_node_get(table
, p
);
142 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
143 || (safi
== SAFI_EVPN
))
149 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
150 safi_t safi
, struct prefix
*p
,
151 struct prefix_rd
*prd
)
154 struct bgp_node
*prn
= NULL
;
159 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
160 || (safi
== SAFI_EVPN
)) {
161 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
165 if (!bgp_node_has_bgp_path_info_data(prn
)) {
166 bgp_unlock_node(prn
);
170 table
= bgp_node_get_bgp_table_info(prn
);
173 rn
= bgp_node_lookup(table
, p
);
178 /* Allocate bgp_path_info_extra */
179 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
181 struct bgp_path_info_extra
*new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
183 sizeof(struct bgp_path_info_extra
));
184 new->label
[0] = MPLS_INVALID_LABEL
;
186 new->bgp_fs_pbr
= NULL
;
187 new->bgp_fs_iprule
= NULL
;
191 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
193 struct bgp_path_info_extra
*e
;
195 if (!extra
|| !*extra
)
200 bgp_damp_info_free(e
->damp_info
, 0, e
->damp_info
->afi
,
205 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
218 bpi
= bgp_path_info_lock(bpi
);
219 refcount
= bpi
->net
->lock
- 1;
220 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
223 bgp_path_info_unlock(bpi
);
225 bgp_path_info_unlock(e
->parent
);
230 bgp_unlock(e
->bgp_orig
);
232 if ((*extra
)->bgp_fs_iprule
)
233 list_delete(&((*extra
)->bgp_fs_iprule
));
234 if ((*extra
)->bgp_fs_pbr
)
235 list_delete(&((*extra
)->bgp_fs_pbr
));
236 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
241 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
242 * allocated if required.
244 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
247 pi
->extra
= bgp_path_info_extra_new();
251 /* Free bgp route information. */
252 static void bgp_path_info_free(struct bgp_path_info
*path
)
254 bgp_attr_unintern(&path
->attr
);
256 bgp_unlink_nexthop(path
);
257 bgp_path_info_extra_free(&path
->extra
);
258 bgp_path_info_mpath_free(&path
->mpath
);
260 bgp_addpath_free_info_data(&path
->tx_addpath
,
261 &path
->net
->tx_addpath
);
263 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
265 XFREE(MTYPE_BGP_ROUTE
, path
);
268 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
274 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
276 assert(path
&& path
->lock
> 0);
279 if (path
->lock
== 0) {
281 zlog_debug ("%s: unlocked and freeing", __func__
);
282 zlog_backtrace (LOG_DEBUG
);
284 bgp_path_info_free(path
);
291 zlog_debug ("%s: unlocked to 1", __func__
);
292 zlog_backtrace (LOG_DEBUG
);
299 /* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
300 static int bgp_node_set_defer_flag(struct bgp_node
*rn
, bool delete)
303 struct bgp_path_info
*old_pi
, *nextpi
;
305 struct bgp
*bgp
= NULL
;
306 struct bgp_table
*table
= NULL
;
309 char buf
[PREFIX2STR_BUFFER
];
311 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
312 * then the route selection is deferred
314 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
) && (!delete))
317 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
)) {
318 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
319 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
320 zlog_debug("Route %s is in workqueue and being processed, not deferred.",
326 table
= bgp_node_table(rn
);
333 for (old_pi
= bgp_node_get_bgp_path_info(rn
);
334 (old_pi
!= NULL
) && (nextpi
= old_pi
->next
, 1); old_pi
= nextpi
) {
335 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_SELECTED
))
338 /* Route selection is deferred if there is a stale path which
339 * which indicates peer is in restart mode
341 if (CHECK_FLAG(old_pi
->flags
, BGP_PATH_STALE
) &&
342 (old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
345 /* If the peer is graceful restart capable and peer is
346 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
349 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer
) &&
350 BGP_PEER_RESTARTING_MODE(peer
) &&
351 (old_pi
&& old_pi
->sub_type
== BGP_ROUTE_NORMAL
)) {
359 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
362 if (set_flag
&& table
) {
363 if (bgp
&& (bgp
->gr_info
[afi
][safi
].t_select_deferral
)) {
364 SET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
365 prefix2str(&rn
->p
, buf
, PREFIX2STR_BUFFER
);
366 if (rn
->rt_node
== NULL
)
367 rn
->rt_node
= listnode_add(
368 bgp
->gr_info
[afi
][safi
].route_list
, rn
);
369 if (BGP_DEBUG(update
, UPDATE_OUT
))
370 zlog_debug("DEFER route %s, rn %p, node %p",
371 buf
, rn
, rn
->rt_node
);
378 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
380 struct bgp_path_info
*top
;
382 top
= bgp_node_get_bgp_path_info(rn
);
388 bgp_node_set_bgp_path_info(rn
, pi
);
390 bgp_path_info_lock(pi
);
392 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
393 bgp_node_set_defer_flag(rn
, false);
396 /* Do the actual removal of info from RIB, for use by bgp_process
397 completion callback *only* */
398 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
401 pi
->next
->prev
= pi
->prev
;
403 pi
->prev
->next
= pi
->next
;
405 bgp_node_set_bgp_path_info(rn
, pi
->next
);
407 bgp_path_info_mpath_dequeue(pi
);
408 bgp_path_info_unlock(pi
);
412 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
414 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
415 /* set of previous already took care of pcount */
416 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
419 /* undo the effects of a previous call to bgp_path_info_delete; typically
420 called when a route is deleted and then quickly re-added before the
421 deletion has been processed */
422 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
424 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
425 /* unset of previous already took care of pcount */
426 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
429 /* Adjust pcount as required */
430 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
432 struct bgp_table
*table
;
434 assert(rn
&& bgp_node_table(rn
));
435 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
437 table
= bgp_node_table(rn
);
439 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
442 if (!BGP_PATH_COUNTABLE(pi
)
443 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
445 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
447 /* slight hack, but more robust against errors. */
448 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
449 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
451 flog_err(EC_LIB_DEVELOPMENT
,
452 "Asked to decrement 0 prefix count for peer");
453 } else if (BGP_PATH_COUNTABLE(pi
)
454 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
455 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
456 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
460 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
461 struct bgp_path_info
*pi2
)
463 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
466 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
467 * This is here primarily to keep prefix-count in check.
469 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
472 SET_FLAG(pi
->flags
, flag
);
474 /* early bath if we know it's not a flag that changes countability state
476 if (!CHECK_FLAG(flag
,
477 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
480 bgp_pcount_adjust(rn
, pi
);
483 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
486 UNSET_FLAG(pi
->flags
, flag
);
488 /* early bath if we know it's not a flag that changes countability state
490 if (!CHECK_FLAG(flag
,
491 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
494 bgp_pcount_adjust(rn
, pi
);
497 /* Get MED value. If MED value is missing and "bgp bestpath
498 missing-as-worst" is specified, treat it as the worst value. */
499 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
501 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
504 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
511 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
513 if (pi
->addpath_rx_id
)
514 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
517 sprintf(buf
, "path %s", pi
->peer
->host
);
520 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
522 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
523 struct bgp_path_info
*exist
, int *paths_eq
,
524 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
525 char *pfx_buf
, afi_t afi
, safi_t safi
,
526 enum bgp_path_selection_reason
*reason
)
528 struct attr
*newattr
, *existattr
;
529 bgp_peer_sort_t new_sort
;
530 bgp_peer_sort_t exist_sort
;
536 uint32_t exist_weight
;
537 uint32_t newm
, existm
;
538 struct in_addr new_id
;
539 struct in_addr exist_id
;
542 int internal_as_route
;
545 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
546 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
548 uint32_t exist_mm_seq
;
555 *reason
= bgp_path_selection_none
;
557 zlog_debug("%s: new is NULL", pfx_buf
);
562 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
565 *reason
= bgp_path_selection_first
;
567 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
573 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
574 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
575 pfx_buf
, new_buf
, new->flags
, exist_buf
,
580 existattr
= exist
->attr
;
582 /* For EVPN routes, we cannot just go by local vs remote, we have to
583 * look at the MAC mobility sequence number, if present.
585 if (safi
== SAFI_EVPN
) {
586 /* This is an error condition described in RFC 7432 Section
588 * states that in this scenario "the PE MUST alert the operator"
590 * does not state what other action to take. In order to provide
592 * consistency in this scenario we are going to prefer the path
596 if (newattr
->sticky
!= existattr
->sticky
) {
598 prefix2str(&new->net
->p
, pfx_buf
,
600 * PREFIX2STR_BUFFER
);
601 bgp_path_info_path_with_addpath_rx_str(new,
603 bgp_path_info_path_with_addpath_rx_str(
607 if (newattr
->sticky
&& !existattr
->sticky
) {
608 *reason
= bgp_path_selection_evpn_sticky_mac
;
611 "%s: %s wins over %s due to sticky MAC flag",
612 pfx_buf
, new_buf
, exist_buf
);
616 if (!newattr
->sticky
&& existattr
->sticky
) {
617 *reason
= bgp_path_selection_evpn_sticky_mac
;
620 "%s: %s loses to %s due to sticky MAC flag",
621 pfx_buf
, new_buf
, exist_buf
);
626 new_mm_seq
= mac_mobility_seqnum(newattr
);
627 exist_mm_seq
= mac_mobility_seqnum(existattr
);
629 if (new_mm_seq
> exist_mm_seq
) {
630 *reason
= bgp_path_selection_evpn_seq
;
633 "%s: %s wins over %s due to MM seq %u > %u",
634 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
639 if (new_mm_seq
< exist_mm_seq
) {
640 *reason
= bgp_path_selection_evpn_seq
;
643 "%s: %s loses to %s due to MM seq %u < %u",
644 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
650 * if sequence numbers are the same path with the lowest IP
653 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
655 *reason
= bgp_path_selection_evpn_lower_ip
;
658 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
659 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
660 inet_ntoa(new->attr
->nexthop
));
664 *reason
= bgp_path_selection_evpn_lower_ip
;
667 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
668 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
669 inet_ntoa(new->attr
->nexthop
));
674 /* 1. Weight check. */
675 new_weight
= newattr
->weight
;
676 exist_weight
= existattr
->weight
;
678 if (new_weight
> exist_weight
) {
679 *reason
= bgp_path_selection_weight
;
681 zlog_debug("%s: %s wins over %s due to weight %d > %d",
682 pfx_buf
, new_buf
, exist_buf
, new_weight
,
687 if (new_weight
< exist_weight
) {
688 *reason
= bgp_path_selection_weight
;
690 zlog_debug("%s: %s loses to %s due to weight %d < %d",
691 pfx_buf
, new_buf
, exist_buf
, new_weight
,
696 /* 2. Local preference check. */
697 new_pref
= exist_pref
= bgp
->default_local_pref
;
699 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
700 new_pref
= newattr
->local_pref
;
701 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
702 exist_pref
= existattr
->local_pref
;
704 if (new_pref
> exist_pref
) {
705 *reason
= bgp_path_selection_local_pref
;
708 "%s: %s wins over %s due to localpref %d > %d",
709 pfx_buf
, new_buf
, exist_buf
, new_pref
,
714 if (new_pref
< exist_pref
) {
715 *reason
= bgp_path_selection_local_pref
;
718 "%s: %s loses to %s due to localpref %d < %d",
719 pfx_buf
, new_buf
, exist_buf
, new_pref
,
724 /* 3. Local route check. We prefer:
726 * - BGP_ROUTE_AGGREGATE
727 * - BGP_ROUTE_REDISTRIBUTE
729 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
730 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
731 *reason
= bgp_path_selection_local_route
;
734 "%s: %s wins over %s due to preferred BGP_ROUTE type",
735 pfx_buf
, new_buf
, exist_buf
);
739 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
740 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
741 *reason
= bgp_path_selection_local_route
;
744 "%s: %s loses to %s due to preferred BGP_ROUTE type",
745 pfx_buf
, new_buf
, exist_buf
);
749 /* 4. AS path length check. */
750 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
751 int exist_hops
= aspath_count_hops(existattr
->aspath
);
752 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
754 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
757 aspath_hops
= aspath_count_hops(newattr
->aspath
);
758 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
760 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
761 *reason
= bgp_path_selection_confed_as_path
;
764 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
765 pfx_buf
, new_buf
, exist_buf
,
767 (exist_hops
+ exist_confeds
));
771 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
772 *reason
= bgp_path_selection_confed_as_path
;
775 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
776 pfx_buf
, new_buf
, exist_buf
,
778 (exist_hops
+ exist_confeds
));
782 int newhops
= aspath_count_hops(newattr
->aspath
);
784 if (newhops
< exist_hops
) {
785 *reason
= bgp_path_selection_as_path
;
788 "%s: %s wins over %s due to aspath hopcount %d < %d",
789 pfx_buf
, new_buf
, exist_buf
,
790 newhops
, exist_hops
);
794 if (newhops
> exist_hops
) {
795 *reason
= bgp_path_selection_as_path
;
798 "%s: %s loses to %s due to aspath hopcount %d > %d",
799 pfx_buf
, new_buf
, exist_buf
,
800 newhops
, exist_hops
);
806 /* 5. Origin check. */
807 if (newattr
->origin
< existattr
->origin
) {
808 *reason
= bgp_path_selection_origin
;
810 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
811 pfx_buf
, new_buf
, exist_buf
,
812 bgp_origin_long_str
[newattr
->origin
],
813 bgp_origin_long_str
[existattr
->origin
]);
817 if (newattr
->origin
> existattr
->origin
) {
818 *reason
= bgp_path_selection_origin
;
820 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
821 pfx_buf
, new_buf
, exist_buf
,
822 bgp_origin_long_str
[newattr
->origin
],
823 bgp_origin_long_str
[existattr
->origin
]);
828 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
829 && aspath_count_hops(existattr
->aspath
) == 0);
830 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
831 && aspath_count_confeds(existattr
->aspath
) > 0
832 && aspath_count_hops(newattr
->aspath
) == 0
833 && aspath_count_hops(existattr
->aspath
) == 0);
835 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
836 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
837 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
838 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
839 || internal_as_route
) {
840 new_med
= bgp_med_value(new->attr
, bgp
);
841 exist_med
= bgp_med_value(exist
->attr
, bgp
);
843 if (new_med
< exist_med
) {
844 *reason
= bgp_path_selection_med
;
847 "%s: %s wins over %s due to MED %d < %d",
848 pfx_buf
, new_buf
, exist_buf
, new_med
,
853 if (new_med
> exist_med
) {
854 *reason
= bgp_path_selection_med
;
857 "%s: %s loses to %s due to MED %d > %d",
858 pfx_buf
, new_buf
, exist_buf
, new_med
,
864 /* 7. Peer type check. */
865 new_sort
= new->peer
->sort
;
866 exist_sort
= exist
->peer
->sort
;
868 if (new_sort
== BGP_PEER_EBGP
869 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
870 *reason
= bgp_path_selection_peer
;
873 "%s: %s wins over %s due to eBGP peer > iBGP peer",
874 pfx_buf
, new_buf
, exist_buf
);
878 if (exist_sort
== BGP_PEER_EBGP
879 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
880 *reason
= bgp_path_selection_peer
;
883 "%s: %s loses to %s due to iBGP peer < eBGP peer",
884 pfx_buf
, new_buf
, exist_buf
);
888 /* 8. IGP metric check. */
892 newm
= new->extra
->igpmetric
;
894 existm
= exist
->extra
->igpmetric
;
899 "%s: %s wins over %s due to IGP metric %d < %d",
900 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
907 "%s: %s loses to %s due to IGP metric %d > %d",
908 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
912 /* 9. Same IGP metric. Compare the cluster list length as
913 representative of IGP hops metric. Rewrite the metric value
914 pair (newm, existm) with the cluster list length. Prefer the
915 path with smaller cluster list length. */
916 if (newm
== existm
) {
917 if (peer_sort(new->peer
) == BGP_PEER_IBGP
918 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
919 && (mpath_cfg
== NULL
921 mpath_cfg
->ibgp_flags
,
922 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
923 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
924 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
929 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
930 pfx_buf
, new_buf
, exist_buf
,
938 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
939 pfx_buf
, new_buf
, exist_buf
,
946 /* 10. confed-external vs. confed-internal */
947 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
948 if (new_sort
== BGP_PEER_CONFED
949 && exist_sort
== BGP_PEER_IBGP
) {
950 *reason
= bgp_path_selection_confed
;
953 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
954 pfx_buf
, new_buf
, exist_buf
);
958 if (exist_sort
== BGP_PEER_CONFED
959 && new_sort
== BGP_PEER_IBGP
) {
960 *reason
= bgp_path_selection_confed
;
963 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
964 pfx_buf
, new_buf
, exist_buf
);
969 /* 11. Maximum path check. */
970 if (newm
== existm
) {
971 /* If one path has a label but the other does not, do not treat
972 * them as equals for multipath
974 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
976 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
979 "%s: %s and %s cannot be multipath, one has a label while the other does not",
980 pfx_buf
, new_buf
, exist_buf
);
981 } else if (bgp_flag_check(bgp
,
982 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
985 * For the two paths, all comparison steps till IGP
987 * have succeeded - including AS_PATH hop count. Since
989 * bestpath as-path multipath-relax' knob is on, we
991 * an exact match of AS_PATH. Thus, mark the paths are
993 * That will trigger both these paths to get into the
1001 "%s: %s and %s are equal via multipath-relax",
1002 pfx_buf
, new_buf
, exist_buf
);
1003 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
1004 if (aspath_cmp(new->attr
->aspath
,
1005 exist
->attr
->aspath
)) {
1010 "%s: %s and %s are equal via matching aspaths",
1011 pfx_buf
, new_buf
, exist_buf
);
1013 } else if (new->peer
->as
== exist
->peer
->as
) {
1018 "%s: %s and %s are equal via same remote-as",
1019 pfx_buf
, new_buf
, exist_buf
);
1023 * TODO: If unequal cost ibgp multipath is enabled we can
1024 * mark the paths as equal here instead of returning
1029 "%s: %s wins over %s after IGP metric comparison",
1030 pfx_buf
, new_buf
, exist_buf
);
1033 "%s: %s loses to %s after IGP metric comparison",
1034 pfx_buf
, new_buf
, exist_buf
);
1036 *reason
= bgp_path_selection_igp_metric
;
1040 /* 12. If both paths are external, prefer the path that was received
1041 first (the oldest one). This step minimizes route-flap, since a
1042 newer path won't displace an older one, even if it was the
1043 preferred route based on the additional decision criteria below. */
1044 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
1045 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
1046 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
1047 *reason
= bgp_path_selection_older
;
1050 "%s: %s wins over %s due to oldest external",
1051 pfx_buf
, new_buf
, exist_buf
);
1055 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
1056 *reason
= bgp_path_selection_older
;
1059 "%s: %s loses to %s due to oldest external",
1060 pfx_buf
, new_buf
, exist_buf
);
1065 /* 13. Router-ID comparision. */
1066 /* If one of the paths is "stale", the corresponding peer router-id will
1067 * be 0 and would always win over the other path. If originator id is
1068 * used for the comparision, it will decide which path is better.
1070 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1071 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
1073 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
1074 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
1075 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
1077 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
1079 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
1080 *reason
= bgp_path_selection_router_id
;
1083 "%s: %s wins over %s due to Router-ID comparison",
1084 pfx_buf
, new_buf
, exist_buf
);
1088 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1089 *reason
= bgp_path_selection_router_id
;
1092 "%s: %s loses to %s due to Router-ID comparison",
1093 pfx_buf
, new_buf
, exist_buf
);
1097 /* 14. Cluster length comparision. */
1098 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1099 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1101 if (new_cluster
< exist_cluster
) {
1102 *reason
= bgp_path_selection_cluster_length
;
1105 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1106 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1111 if (new_cluster
> exist_cluster
) {
1112 *reason
= bgp_path_selection_cluster_length
;
1115 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1116 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1121 /* 15. Neighbor address comparision. */
1122 /* Do this only if neither path is "stale" as stale paths do not have
1123 * valid peer information (as the connection may or may not be up).
1125 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1126 *reason
= bgp_path_selection_stale
;
1129 "%s: %s wins over %s due to latter path being STALE",
1130 pfx_buf
, new_buf
, exist_buf
);
1134 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1135 *reason
= bgp_path_selection_stale
;
1138 "%s: %s loses to %s due to former path being STALE",
1139 pfx_buf
, new_buf
, exist_buf
);
1143 /* locally configured routes to advertise do not have su_remote */
1144 if (new->peer
->su_remote
== NULL
) {
1145 *reason
= bgp_path_selection_local_configured
;
1148 if (exist
->peer
->su_remote
== NULL
) {
1149 *reason
= bgp_path_selection_local_configured
;
1153 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1156 *reason
= bgp_path_selection_neighbor_ip
;
1159 "%s: %s loses to %s due to Neighor IP comparison",
1160 pfx_buf
, new_buf
, exist_buf
);
1165 *reason
= bgp_path_selection_neighbor_ip
;
1168 "%s: %s wins over %s due to Neighor IP comparison",
1169 pfx_buf
, new_buf
, exist_buf
);
1173 *reason
= bgp_path_selection_default
;
1175 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1176 pfx_buf
, new_buf
, exist_buf
);
1181 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1182 * is preferred, or 0 if they are the same (usually will only occur if
1183 * multipath is enabled
1184 * This version is compatible with */
1185 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1186 struct bgp_path_info
*exist
, char *pfx_buf
,
1187 afi_t afi
, safi_t safi
,
1188 enum bgp_path_selection_reason
*reason
)
1192 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1206 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1207 struct attr
*attr
, afi_t afi
,
1210 struct bgp_filter
*filter
;
1212 filter
= &peer
->filter
[afi
][safi
];
1214 #define FILTER_EXIST_WARN(F, f, filter) \
1215 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1216 zlog_debug("%s: Could not find configured input %s-list %s!", \
1217 peer->host, #f, F##_IN_NAME(filter));
1219 if (DISTRIBUTE_IN_NAME(filter
)) {
1220 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1222 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1226 if (PREFIX_LIST_IN_NAME(filter
)) {
1227 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1229 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1233 if (FILTER_LIST_IN_NAME(filter
)) {
1234 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1236 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1241 return FILTER_PERMIT
;
1242 #undef FILTER_EXIST_WARN
1245 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1246 struct attr
*attr
, afi_t afi
,
1249 struct bgp_filter
*filter
;
1251 filter
= &peer
->filter
[afi
][safi
];
1253 #define FILTER_EXIST_WARN(F, f, filter) \
1254 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1255 zlog_debug("%s: Could not find configured output %s-list %s!", \
1256 peer->host, #f, F##_OUT_NAME(filter));
1258 if (DISTRIBUTE_OUT_NAME(filter
)) {
1259 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1261 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1265 if (PREFIX_LIST_OUT_NAME(filter
)) {
1266 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1268 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1273 if (FILTER_LIST_OUT_NAME(filter
)) {
1274 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1276 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1281 return FILTER_PERMIT
;
1282 #undef FILTER_EXIST_WARN
1285 /* If community attribute includes no_export then return 1. */
1286 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1288 if (attr
->community
) {
1289 /* NO_ADVERTISE check. */
1290 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1293 /* NO_EXPORT check. */
1294 if (peer
->sort
== BGP_PEER_EBGP
1295 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1298 /* NO_EXPORT_SUBCONFED check. */
1299 if (peer
->sort
== BGP_PEER_EBGP
1300 || peer
->sort
== BGP_PEER_CONFED
)
1301 if (community_include(attr
->community
,
1302 COMMUNITY_NO_EXPORT_SUBCONFED
))
1308 /* Route reflection loop check. */
1309 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1311 struct in_addr cluster_id
;
1313 if (attr
->cluster
) {
1314 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1315 cluster_id
= peer
->bgp
->cluster_id
;
1317 cluster_id
= peer
->bgp
->router_id
;
1319 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1325 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1326 struct attr
*attr
, afi_t afi
, safi_t safi
,
1327 const char *rmap_name
, mpls_label_t
*label
,
1328 uint32_t num_labels
, struct bgp_node
*rn
)
1330 struct bgp_filter
*filter
;
1331 struct bgp_path_info rmap_path
= { 0 };
1332 struct bgp_path_info_extra extra
= { 0 };
1333 route_map_result_t ret
;
1334 struct route_map
*rmap
= NULL
;
1336 filter
= &peer
->filter
[afi
][safi
];
1338 /* Apply default weight value. */
1339 if (peer
->weight
[afi
][safi
])
1340 attr
->weight
= peer
->weight
[afi
][safi
];
1343 rmap
= route_map_lookup_by_name(rmap_name
);
1348 if (ROUTE_MAP_IN_NAME(filter
)) {
1349 rmap
= ROUTE_MAP_IN(filter
);
1356 /* Route map apply. */
1358 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1359 /* Duplicate current value to new strucutre for modification. */
1360 rmap_path
.peer
= peer
;
1361 rmap_path
.attr
= attr
;
1362 rmap_path
.extra
= &extra
;
1365 extra
.num_labels
= num_labels
;
1366 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1367 memcpy(extra
.label
, label
,
1368 num_labels
* sizeof(mpls_label_t
));
1370 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1372 /* Apply BGP route map to the attribute. */
1373 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1375 peer
->rmap_type
= 0;
1377 if (ret
== RMAP_DENYMATCH
)
1383 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1384 struct attr
*attr
, afi_t afi
, safi_t safi
,
1385 const char *rmap_name
)
1387 struct bgp_path_info rmap_path
;
1388 route_map_result_t ret
;
1389 struct route_map
*rmap
= NULL
;
1393 * So if we get to this point and have no rmap_name
1394 * we want to just show the output as it currently
1400 /* Apply default weight value. */
1401 if (peer
->weight
[afi
][safi
])
1402 attr
->weight
= peer
->weight
[afi
][safi
];
1404 rmap
= route_map_lookup_by_name(rmap_name
);
1407 * If we have a route map name and we do not find
1408 * the routemap that means we have an implicit
1414 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1415 /* Route map apply. */
1416 /* Duplicate current value to new strucutre for modification. */
1417 rmap_path
.peer
= peer
;
1418 rmap_path
.attr
= attr
;
1420 rmap_type
= peer
->rmap_type
;
1421 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1423 /* Apply BGP route map to the attribute. */
1424 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1426 peer
->rmap_type
= rmap_type
;
1428 if (ret
== RMAP_DENYMATCH
)
1430 * caller has multiple error paths with bgp_attr_flush()
1437 /* If this is an EBGP peer with remove-private-AS */
1438 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1439 struct peer
*peer
, struct attr
*attr
)
1441 if (peer
->sort
== BGP_PEER_EBGP
1442 && (peer_af_flag_check(peer
, afi
, safi
,
1443 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1444 || peer_af_flag_check(peer
, afi
, safi
,
1445 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1446 || peer_af_flag_check(peer
, afi
, safi
,
1447 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1448 || peer_af_flag_check(peer
, afi
, safi
,
1449 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1450 // Take action on the entire aspath
1451 if (peer_af_flag_check(peer
, afi
, safi
,
1452 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1453 || peer_af_flag_check(peer
, afi
, safi
,
1454 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1455 if (peer_af_flag_check(
1457 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1458 attr
->aspath
= aspath_replace_private_asns(
1459 attr
->aspath
, bgp
->as
, peer
->as
);
1461 // The entire aspath consists of private ASNs so create
1463 else if (aspath_private_as_check(attr
->aspath
))
1464 attr
->aspath
= aspath_empty_get();
1466 // There are some public and some private ASNs, remove
1469 attr
->aspath
= aspath_remove_private_asns(
1470 attr
->aspath
, peer
->as
);
1473 // 'all' was not specified so the entire aspath must be private
1475 // for us to do anything
1476 else if (aspath_private_as_check(attr
->aspath
)) {
1477 if (peer_af_flag_check(
1479 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1480 attr
->aspath
= aspath_replace_private_asns(
1481 attr
->aspath
, bgp
->as
, peer
->as
);
1483 attr
->aspath
= aspath_empty_get();
1488 /* If this is an EBGP peer with as-override */
1489 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1490 struct peer
*peer
, struct attr
*attr
)
1492 if (peer
->sort
== BGP_PEER_EBGP
1493 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1494 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1495 attr
->aspath
= aspath_replace_specific_asn(
1496 attr
->aspath
, peer
->as
, bgp
->as
);
1500 void bgp_attr_add_gshut_community(struct attr
*attr
)
1502 struct community
*old
;
1503 struct community
*new;
1504 struct community
*merge
;
1505 struct community
*gshut
;
1507 old
= attr
->community
;
1508 gshut
= community_str2com("graceful-shutdown");
1513 merge
= community_merge(community_dup(old
), gshut
);
1515 if (old
->refcnt
== 0)
1516 community_free(&old
);
1518 new = community_uniq_sort(merge
);
1519 community_free(&merge
);
1521 new = community_dup(gshut
);
1524 community_free(&gshut
);
1525 attr
->community
= new;
1526 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1528 /* When we add the graceful-shutdown community we must also
1529 * lower the local-preference */
1530 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1531 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1535 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1537 if (family
== AF_INET
) {
1538 attr
->nexthop
.s_addr
= 0;
1539 attr
->mp_nexthop_global_in
.s_addr
= 0;
1541 if (family
== AF_INET6
)
1542 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1543 if (family
== AF_EVPN
)
1544 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1547 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1548 struct update_subgroup
*subgrp
, struct prefix
*p
,
1551 struct bgp_filter
*filter
;
1554 struct peer
*onlypeer
;
1556 struct attr
*piattr
;
1557 char buf
[PREFIX_STRLEN
];
1558 route_map_result_t ret
;
1563 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1565 if (DISABLE_BGP_ANNOUNCE
)
1568 afi
= SUBGRP_AFI(subgrp
);
1569 safi
= SUBGRP_SAFI(subgrp
);
1570 peer
= SUBGRP_PEER(subgrp
);
1572 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1573 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1576 filter
= &peer
->filter
[afi
][safi
];
1577 bgp
= SUBGRP_INST(subgrp
);
1578 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1582 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1583 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1584 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1587 * direct and direct_ext type routes originate internally even
1588 * though they can have peer pointers that reference other
1591 prefix2str(p
, buf
, PREFIX_STRLEN
);
1592 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1598 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1599 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1600 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1601 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1603 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1608 /* With addpath we may be asked to TX all kinds of paths so make sure
1610 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1611 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1612 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1616 /* If this is not the bestpath then check to see if there is an enabled
1618 * feature that requires us to advertise it */
1619 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1620 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1625 /* Aggregate-address suppress check. */
1626 if (pi
->extra
&& pi
->extra
->suppress
)
1627 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1632 * If we are doing VRF 2 VRF leaking via the import
1633 * statement, we want to prevent the route going
1634 * off box as that the RT and RD created are localy
1635 * significant and globaly useless.
1637 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1638 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1641 /* If it's labeled safi, make sure the route has a valid label. */
1642 if (safi
== SAFI_LABELED_UNICAST
) {
1643 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1644 if (!bgp_is_valid_label(&label
)) {
1645 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1646 zlog_debug("u%" PRIu64
":s%" PRIu64
1647 " %s/%d is filtered - no label (%p)",
1648 subgrp
->update_group
->id
, subgrp
->id
,
1649 inet_ntop(p
->family
, &p
->u
.prefix
,
1650 buf
, SU_ADDRSTRLEN
),
1651 p
->prefixlen
, &label
);
1656 /* Do not send back route to sender. */
1657 if (onlypeer
&& from
== onlypeer
) {
1661 /* Do not send the default route in the BGP table if the neighbor is
1662 * configured for default-originate */
1663 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1664 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1665 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1667 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1671 /* Transparency check. */
1672 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1673 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1678 /* If community is not disabled check the no-export and local. */
1679 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1680 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1682 "subgrpannouncecheck: community filter check fail");
1686 /* If the attribute has originator-id and it is same as remote
1688 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1689 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1690 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1692 "%s [Update:SEND] %s originator-id is same as "
1695 prefix2str(p
, buf
, sizeof(buf
)));
1699 /* ORF prefix-list filter check */
1700 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1701 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1702 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1703 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1704 if (peer
->orf_plist
[afi
][safi
]) {
1705 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1707 if (bgp_debug_update(NULL
, p
,
1708 subgrp
->update_group
, 0))
1710 "%s [Update:SEND] %s is filtered via ORF",
1718 /* Output filter check. */
1719 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1720 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1721 zlog_debug("%s [Update:SEND] %s is filtered",
1722 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1726 /* AS path loop check. */
1727 if (onlypeer
&& onlypeer
->as_path_loop_detection
1728 && aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1729 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1731 "%s [Update:SEND] suppress announcement to peer AS %u "
1732 "that is part of AS path.",
1733 onlypeer
->host
, onlypeer
->as
);
1737 /* If we're a CONFED we need to loop check the CONFED ID too */
1738 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1739 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1740 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1742 "%s [Update:SEND] suppress announcement to peer AS %u"
1744 peer
->host
, bgp
->confed_id
);
1749 /* Route-Reflect check. */
1750 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1755 /* IBGP reflection check. */
1756 if (reflect
&& !samepeer_safe
) {
1757 /* A route from a Client peer. */
1758 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1759 PEER_FLAG_REFLECTOR_CLIENT
)) {
1760 /* Reflect to all the Non-Client peers and also to the
1761 Client peers other than the originator. Originator
1763 is already done. So there is noting to do. */
1764 /* no bgp client-to-client reflection check. */
1765 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1766 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1767 PEER_FLAG_REFLECTOR_CLIENT
))
1770 /* A route from a Non-client peer. Reflect to all other
1772 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1773 PEER_FLAG_REFLECTOR_CLIENT
))
1778 /* For modify attribute, copy it to temporary structure. */
1781 /* If local-preference is not set. */
1782 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1783 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1784 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1785 attr
->local_pref
= bgp
->default_local_pref
;
1788 /* If originator-id is not set and the route is to be reflected,
1789 set the originator id */
1791 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1792 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1793 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1796 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1798 if (peer
->sort
== BGP_PEER_EBGP
1799 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1800 if (from
!= bgp
->peer_self
&& !transparent
1801 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1802 PEER_FLAG_MED_UNCHANGED
))
1804 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1807 /* Since the nexthop attribute can vary per peer, it is not explicitly
1809 * in announce check, only certain flags and length (or number of
1811 * -- for IPv6/MP_REACH) are set here in order to guide the update
1813 * code in setting the nexthop(s) on a per peer basis in
1815 * Typically, the source nexthop in the attribute is preserved but in
1817 * scenarios where we know it will always be overwritten, we reset the
1818 * nexthop to "0" in an attempt to achieve better Update packing. An
1819 * example of this is when a prefix from each of 2 IBGP peers needs to
1821 * announced to an EBGP peer (and they have the same attributes barring
1825 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1827 #define NEXTHOP_IS_V6 \
1828 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1829 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1830 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1831 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1833 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1835 * the peer (group) is configured to receive link-local nexthop
1837 * and it is available in the prefix OR we're not reflecting the route,
1838 * link-local nexthop address is valid and
1839 * the peer (group) to whom we're going to announce is on a shared
1841 * and this is either a self-originated route or the peer is EBGP.
1842 * By checking if nexthop LL address is valid we are sure that
1843 * we do not announce LL address as `::`.
1845 if (NEXTHOP_IS_V6
) {
1846 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1847 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1848 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1849 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1851 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1852 && peer
->shared_network
1853 && (from
== bgp
->peer_self
1854 || peer
->sort
== BGP_PEER_EBGP
))) {
1855 attr
->mp_nexthop_len
=
1856 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1859 /* Clear off link-local nexthop in source, whenever it is not
1861 * ensure more prefixes share the same attribute for
1864 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1865 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1866 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1869 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1870 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1872 /* Route map & unsuppress-map apply. */
1873 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1874 struct bgp_path_info rmap_path
= {0};
1875 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1876 struct attr dummy_attr
= {0};
1878 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1879 rmap_path
.peer
= peer
;
1880 rmap_path
.attr
= attr
;
1884 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1885 sizeof(struct bgp_path_info_extra
));
1886 rmap_path
.extra
= &dummy_rmap_path_extra
;
1889 /* don't confuse inbound and outbound setting */
1890 RESET_FLAG(attr
->rmap_change_flags
);
1893 * The route reflector is not allowed to modify the attributes
1894 * of the reflected IBGP routes unless explicitly allowed.
1896 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1897 && !bgp_flag_check(bgp
,
1898 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1900 rmap_path
.attr
= &dummy_attr
;
1903 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1905 if (pi
->extra
&& pi
->extra
->suppress
)
1906 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1907 RMAP_BGP
, &rmap_path
);
1909 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1910 RMAP_BGP
, &rmap_path
);
1912 peer
->rmap_type
= 0;
1914 if (ret
== RMAP_DENYMATCH
) {
1915 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1916 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1917 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1919 bgp_attr_flush(attr
);
1924 /* RFC 8212 to prevent route leaks.
1925 * This specification intends to improve this situation by requiring the
1926 * explicit configuration of both BGP Import and Export Policies for any
1927 * External BGP (EBGP) session such as customers, peers, or
1928 * confederation boundaries for all enabled address families. Through
1929 * codification of the aforementioned requirement, operators will
1930 * benefit from consistent behavior across different BGP
1933 if (peer
->bgp
->ebgp_requires_policy
1934 == DEFAULT_EBGP_POLICY_ENABLED
)
1935 if (!bgp_outbound_policy_exists(peer
, filter
))
1938 /* draft-ietf-idr-deprecate-as-set-confed-set
1939 * Filter routes having AS_SET or AS_CONFED_SET in the path.
1940 * Eventually, This document (if approved) updates RFC 4271
1941 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
1942 * and obsoletes RFC 6472.
1944 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
1945 if (aspath_check_as_sets(attr
->aspath
))
1948 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1949 if (peer
->sort
== BGP_PEER_IBGP
1950 || peer
->sort
== BGP_PEER_CONFED
) {
1951 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1952 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1954 bgp_attr_add_gshut_community(attr
);
1958 /* After route-map has been applied, we check to see if the nexthop to
1959 * be carried in the attribute (that is used for the announcement) can
1960 * be cleared off or not. We do this in all cases where we would be
1961 * setting the nexthop to "ourselves". For IPv6, we only need to
1963 * the global nexthop here; the link-local nexthop would have been
1965 * already, and if not, it is required by the update formation code.
1966 * Also see earlier comments in this function.
1969 * If route-map has performed some operation on the nexthop or the peer
1970 * configuration says to pass it unchanged, we cannot reset the nexthop
1971 * here, so only attempt to do it if these aren't true. Note that the
1972 * route-map handler itself might have cleared the nexthop, if for
1974 * it is configured as 'peer-address'.
1976 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1977 piattr
->rmap_change_flags
)
1979 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1980 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1981 /* We can reset the nexthop, if setting (or forcing) it to
1983 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1984 PEER_FLAG_NEXTHOP_SELF
)
1985 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1986 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1988 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1989 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1990 subgroup_announce_reset_nhop(
1991 (peer_cap_enhe(peer
, afi
, safi
)
1995 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1996 /* Can also reset the nexthop if announcing to EBGP, but
1998 * no peer in the subgroup is on a shared subnet.
1999 * Note: 3rd party nexthop currently implemented for
2002 if ((p
->family
== AF_INET
) &&
2003 (!bgp_subgrp_multiaccess_check_v4(
2006 subgroup_announce_reset_nhop(
2007 (peer_cap_enhe(peer
, afi
, safi
)
2012 if ((p
->family
== AF_INET6
) &&
2013 (!bgp_subgrp_multiaccess_check_v6(
2014 piattr
->mp_nexthop_global
,
2016 subgroup_announce_reset_nhop(
2017 (peer_cap_enhe(peer
, afi
, safi
)
2024 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
2026 * This flag is used for leaked vpn-vrf routes
2028 int family
= p
->family
;
2030 if (peer_cap_enhe(peer
, afi
, safi
))
2033 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
2035 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
2036 __func__
, family2str(family
));
2037 subgroup_announce_reset_nhop(family
, attr
);
2041 /* If IPv6/MP and nexthop does not have any override and happens
2043 * be a link-local address, reset it so that we don't pass along
2045 * source's link-local IPv6 address to recipients who may not be
2047 * the same interface.
2049 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
2050 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
2051 subgroup_announce_reset_nhop(AF_INET6
, attr
);
2057 static int bgp_route_select_timer_expire(struct thread
*thread
)
2059 struct afi_safi_info
*info
;
2064 info
= THREAD_ARG(thread
);
2069 if (BGP_DEBUG(update
, UPDATE_OUT
))
2070 zlog_debug("afi %d, safi %d : route select timer expired",
2073 bgp
->gr_info
[afi
][safi
].t_route_select
= NULL
;
2075 XFREE(MTYPE_TMP
, info
);
2077 /* Best path selection */
2078 return bgp_best_path_select_defer(bgp
, afi
, safi
);
2081 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
2082 struct bgp_maxpaths_cfg
*mpath_cfg
,
2083 struct bgp_path_info_pair
*result
, afi_t afi
,
2086 struct bgp_path_info
*new_select
;
2087 struct bgp_path_info
*old_select
;
2088 struct bgp_path_info
*pi
;
2089 struct bgp_path_info
*pi1
;
2090 struct bgp_path_info
*pi2
;
2091 struct bgp_path_info
*nextpi
= NULL
;
2092 int paths_eq
, do_mpath
, debug
;
2093 struct list mp_list
;
2094 char pfx_buf
[PREFIX2STR_BUFFER
];
2095 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
2097 bgp_mp_list_init(&mp_list
);
2099 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
2101 debug
= bgp_debug_bestpath(&rn
->p
);
2104 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2106 /* bgp deterministic-med */
2108 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
2110 /* Clear BGP_PATH_DMED_SELECTED for all paths */
2111 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2113 bgp_path_info_unset_flag(rn
, pi1
,
2114 BGP_PATH_DMED_SELECTED
);
2116 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
2118 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2120 if (BGP_PATH_HOLDDOWN(pi1
))
2122 if (pi1
->peer
!= bgp
->peer_self
)
2123 if (pi1
->peer
->status
!= Established
)
2128 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2129 if (CHECK_FLAG(pi2
->flags
,
2130 BGP_PATH_DMED_CHECK
))
2132 if (BGP_PATH_HOLDDOWN(pi2
))
2134 if (pi2
->peer
!= bgp
->peer_self
2137 PEER_STATUS_NSF_WAIT
))
2138 if (pi2
->peer
->status
2142 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2144 && !aspath_cmp_left_confed(
2149 if (bgp_path_info_cmp(
2150 bgp
, pi2
, new_select
,
2151 &paths_eq
, mpath_cfg
, debug
,
2154 bgp_path_info_unset_flag(
2156 BGP_PATH_DMED_SELECTED
);
2160 bgp_path_info_set_flag(
2161 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2164 bgp_path_info_set_flag(rn
, new_select
,
2165 BGP_PATH_DMED_CHECK
);
2166 bgp_path_info_set_flag(rn
, new_select
,
2167 BGP_PATH_DMED_SELECTED
);
2170 bgp_path_info_path_with_addpath_rx_str(
2171 new_select
, path_buf
);
2172 zlog_debug("%s: %s is the bestpath from AS %u",
2174 aspath_get_first_as(
2175 new_select
->attr
->aspath
));
2180 /* Check old selected route and new selected route. */
2183 for (pi
= bgp_node_get_bgp_path_info(rn
);
2184 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2185 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2188 if (BGP_PATH_HOLDDOWN(pi
)) {
2189 /* reap REMOVED routes, if needs be
2190 * selected route must stay for a while longer though
2192 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2193 && (pi
!= old_select
))
2194 bgp_path_info_reap(rn
, pi
);
2197 zlog_debug("%s: pi %p in holddown", __func__
,
2203 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2204 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2205 if (pi
->peer
->status
!= Established
) {
2209 "%s: pi %p non self peer %s not estab state",
2210 __func__
, pi
, pi
->peer
->host
);
2215 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2216 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2217 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2219 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2223 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2225 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2226 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2231 /* Now that we know which path is the bestpath see if any of the other
2233 * qualify as multipaths
2237 bgp_path_info_path_with_addpath_rx_str(new_select
,
2240 sprintf(path_buf
, "NONE");
2242 "%s: After path selection, newbest is %s oldbest was %s",
2244 old_select
? old_select
->peer
->host
: "NONE");
2247 if (do_mpath
&& new_select
) {
2248 for (pi
= bgp_node_get_bgp_path_info(rn
);
2249 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2252 bgp_path_info_path_with_addpath_rx_str(
2255 if (pi
== new_select
) {
2258 "%s: %s is the bestpath, add to the multipath list",
2260 bgp_mp_list_add(&mp_list
, pi
);
2264 if (BGP_PATH_HOLDDOWN(pi
))
2267 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2268 && !CHECK_FLAG(pi
->peer
->sflags
,
2269 PEER_STATUS_NSF_WAIT
))
2270 if (pi
->peer
->status
!= Established
)
2273 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2276 "%s: %s has the same nexthop as the bestpath, skip it",
2281 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2282 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2288 "%s: %s is equivalent to the bestpath, add to the multipath list",
2290 bgp_mp_list_add(&mp_list
, pi
);
2295 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2297 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2298 bgp_mp_list_clear(&mp_list
);
2300 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2302 result
->old
= old_select
;
2303 result
->new = new_select
;
2309 * A new route/change in bestpath of an existing route. Evaluate the path
2310 * for advertisement to the subgroup.
2312 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2313 struct bgp_path_info
*selected
,
2314 struct bgp_node
*rn
,
2315 uint32_t addpath_tx_id
)
2318 struct peer
*onlypeer
;
2324 afi
= SUBGRP_AFI(subgrp
);
2325 safi
= SUBGRP_SAFI(subgrp
);
2326 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2329 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2330 char buf_prefix
[PREFIX_STRLEN
];
2331 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2332 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2336 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2337 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2338 PEER_STATUS_ORF_WAIT_REFRESH
))
2341 memset(&attr
, 0, sizeof(struct attr
));
2342 /* It's initialized in bgp_announce_check() */
2344 /* Announcement to the subgroup. If the route is filtered withdraw it.
2347 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2348 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2350 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2354 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2356 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2363 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2364 * This is called at the end of route processing.
2366 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2368 struct bgp_path_info
*pi
;
2370 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2371 if (BGP_PATH_HOLDDOWN(pi
))
2373 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2374 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2379 * Has the route changed from the RIB's perspective? This is invoked only
2380 * if the route selection returns the same best route as earlier - to
2381 * determine if we need to update zebra or not.
2383 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2384 struct bgp_path_info
*selected
)
2386 struct bgp_path_info
*mpinfo
;
2388 /* If this is multipath, check all selected paths for any nexthop
2389 * change or attribute change. Some attribute changes (e.g., community)
2390 * aren't of relevance to the RIB, but we'll update zebra to ensure
2391 * we handle the case of BGP nexthop change. This is the behavior
2392 * when the best path has an attribute change anyway.
2394 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2395 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2399 * If this is multipath, check all selected paths for any nexthop change
2401 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2402 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2403 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2404 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2408 /* Nothing has changed from the RIB's perspective. */
2412 struct bgp_process_queue
{
2414 STAILQ_HEAD(, bgp_node
) pqueue
;
2415 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2417 unsigned int queued
;
2421 * old_select = The old best path
2422 * new_select = the new best path
2424 * if (!old_select && new_select)
2425 * We are sending new information on.
2427 * if (old_select && new_select) {
2428 * if (new_select != old_select)
2429 * We have a new best path send a change
2431 * We've received a update with new attributes that needs
2435 * if (old_select && !new_select)
2436 * We have no eligible route that we can announce or the rn
2439 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2440 afi_t afi
, safi_t safi
)
2442 struct bgp_path_info
*new_select
;
2443 struct bgp_path_info
*old_select
;
2444 struct bgp_path_info_pair old_and_new
;
2445 char pfx_buf
[PREFIX2STR_BUFFER
];
2448 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2450 debug
= bgp_debug_bestpath(&rn
->p
);
2452 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2454 "%s: bgp delete in progress, ignoring event, p=%s",
2459 /* Is it end of initial update? (after startup) */
2461 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2462 sizeof(bgp
->update_delay_zebra_resume_time
));
2464 bgp
->main_zebra_update_hold
= 0;
2465 FOREACH_AFI_SAFI (afi
, safi
) {
2466 if (bgp_fibupd_safi(safi
))
2467 bgp_zebra_announce_table(bgp
, afi
, safi
);
2469 bgp
->main_peers_update_hold
= 0;
2471 bgp_start_routeadv(bgp
);
2475 struct prefix
*p
= &rn
->p
;
2477 debug
= bgp_debug_bestpath(&rn
->p
);
2479 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2480 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2481 afi2str(afi
), safi2str(safi
));
2484 /* The best path calculation for the route is deferred if
2485 * BGP_NODE_SELECT_DEFER is set
2487 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2488 if (BGP_DEBUG(update
, UPDATE_OUT
))
2489 zlog_debug("SELECT_DEFER falg set for route %p", rn
);
2493 /* Best path selection. */
2494 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2496 old_select
= old_and_new
.old
;
2497 new_select
= old_and_new
.new;
2499 /* Do we need to allocate or free labels?
2500 * Right now, since we only deal with per-prefix labels, it is not
2501 * necessary to do this upon changes to best path. Exceptions:
2502 * - label index has changed -> recalculate resulting label
2503 * - path_info sub_type changed -> switch to/from implicit-null
2504 * - no valid label (due to removed static label binding) -> get new one
2506 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2509 || bgp_label_index_differs(new_select
, old_select
)
2510 || new_select
->sub_type
!= old_select
->sub_type
2511 || !bgp_is_valid_label(&rn
->local_label
)) {
2512 /* Enforced penultimate hop popping:
2513 * implicit-null for local routes, aggregate
2514 * and redistributed routes
2516 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2517 || new_select
->sub_type
2518 == BGP_ROUTE_AGGREGATE
2519 || new_select
->sub_type
2520 == BGP_ROUTE_REDISTRIBUTE
) {
2523 BGP_NODE_REGISTERED_FOR_LABEL
))
2524 bgp_unregister_for_label(rn
);
2525 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2527 bgp_set_valid_label(&rn
->local_label
);
2529 bgp_register_for_label(rn
, new_select
);
2531 } else if (CHECK_FLAG(rn
->flags
,
2532 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2533 bgp_unregister_for_label(rn
);
2535 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2536 bgp_unregister_for_label(rn
);
2540 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2542 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2543 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2544 old_select
, new_select
);
2547 /* If best route remains the same and this is not due to user-initiated
2548 * clear, see exactly what needs to be done.
2550 if (old_select
&& old_select
== new_select
2551 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2552 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2553 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2554 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2556 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2557 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2559 if (bgp_fibupd_safi(safi
)
2560 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2562 if (new_select
->type
== ZEBRA_ROUTE_BGP
2563 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2564 || new_select
->sub_type
2565 == BGP_ROUTE_IMPORTED
))
2567 bgp_zebra_announce(rn
, p
, old_select
,
2571 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2572 bgp_zebra_clear_route_change_flags(rn
);
2574 /* If there is a change of interest to peers, reannounce the
2576 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2577 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2578 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2580 /* unicast routes must also be annouced to
2581 * labeled-unicast update-groups */
2582 if (safi
== SAFI_UNICAST
)
2583 group_announce_route(bgp
, afi
,
2584 SAFI_LABELED_UNICAST
, rn
,
2587 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2588 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2591 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2595 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2597 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2599 /* bestpath has changed; bump version */
2600 if (old_select
|| new_select
) {
2601 bgp_bump_version(rn
);
2603 if (!bgp
->t_rmap_def_originate_eval
) {
2607 update_group_refresh_default_originate_route_map
,
2608 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2609 &bgp
->t_rmap_def_originate_eval
);
2614 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2617 zlog_debug("%s: setting SELECTED flag", __func__
);
2618 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2619 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2620 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2624 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2625 if (old_select
!= new_select
) {
2627 vnc_import_bgp_exterior_del_route(bgp
, p
,
2629 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2632 vnc_import_bgp_exterior_add_route(bgp
, p
,
2634 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2640 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2642 /* unicast routes must also be annouced to labeled-unicast update-groups
2644 if (safi
== SAFI_UNICAST
)
2645 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2649 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2650 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2651 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2652 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2653 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2654 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2656 /* if this is an evpn imported type-5 prefix,
2657 * we need to withdraw the route first to clear
2658 * the nh neigh and the RMAC entry.
2661 is_route_parent_evpn(old_select
))
2662 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2664 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2666 /* Withdraw the route from the kernel. */
2667 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2668 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2669 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2670 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2672 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2676 /* advertise/withdraw type-5 routes */
2677 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2678 if (advertise_type5_routes(bgp
, afi
) &&
2680 is_route_injectable_into_evpn(new_select
)) {
2682 /* apply the route-map */
2683 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2684 route_map_result_t ret
;
2686 ret
= route_map_apply(
2687 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2688 &rn
->p
, RMAP_BGP
, new_select
);
2689 if (ret
== RMAP_PERMITMATCH
)
2690 bgp_evpn_advertise_type5_route(
2691 bgp
, &rn
->p
, new_select
->attr
,
2694 bgp_evpn_withdraw_type5_route(
2695 bgp
, &rn
->p
, afi
, safi
);
2697 bgp_evpn_advertise_type5_route(bgp
,
2703 } else if (advertise_type5_routes(bgp
, afi
) &&
2705 is_route_injectable_into_evpn(old_select
))
2706 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2709 /* Clear any route change flags. */
2710 bgp_zebra_clear_route_change_flags(rn
);
2712 /* Reap old select bgp_path_info, if it has been removed */
2713 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2714 bgp_path_info_reap(rn
, old_select
);
2716 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2720 /* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2721 int bgp_best_path_select_defer(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
2723 struct bgp_node
*rn
;
2725 struct afi_safi_info
*thread_info
;
2726 struct listnode
*node
= NULL
, *nnode
= NULL
;
2728 if (bgp
->gr_info
[afi
][safi
].t_route_select
)
2729 BGP_TIMER_OFF(bgp
->gr_info
[afi
][safi
].t_route_select
);
2731 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2732 zlog_debug("%s: processing route for %s : cnt %d",
2733 __func__
, get_afi_safi_str(afi
, safi
, false),
2734 listcount(bgp
->gr_info
[afi
][safi
].route_list
));
2737 /* Process the route list */
2738 node
= listhead(bgp
->gr_info
[afi
][safi
].route_list
);
2740 rn
= listgetdata(node
);
2742 list_delete_node(bgp
->gr_info
[afi
][safi
].route_list
, node
);
2745 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2746 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
2747 bgp_process_main_one(bgp
, rn
, afi
, safi
);
2749 if (cnt
>= BGP_MAX_BEST_ROUTE_SELECT
)
2755 /* Send EOR message when all routes are processed */
2756 if (list_isempty(bgp
->gr_info
[afi
][safi
].route_list
)) {
2757 bgp_send_delayed_eor(bgp
);
2758 /* Send route processing complete message to RIB */
2759 bgp_zebra_update(afi
, safi
, bgp
->vrf_id
,
2760 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE
);
2764 thread_info
= XMALLOC(MTYPE_TMP
, sizeof(struct afi_safi_info
));
2766 thread_info
->afi
= afi
;
2767 thread_info
->safi
= safi
;
2768 thread_info
->bgp
= bgp
;
2770 /* If there are more routes to be processed, start the
2773 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2774 BGP_ROUTE_SELECT_DELAY
,
2775 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2779 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2781 struct bgp_process_queue
*pqnode
= data
;
2782 struct bgp
*bgp
= pqnode
->bgp
;
2783 struct bgp_table
*table
;
2784 struct bgp_node
*rn
;
2787 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2788 bgp_process_main_one(bgp
, NULL
, 0, 0);
2789 /* should always have dedicated wq call */
2790 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2794 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2795 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2796 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2797 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2798 table
= bgp_node_table(rn
);
2799 /* note, new RNs may be added as part of processing */
2800 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2802 bgp_unlock_node(rn
);
2803 bgp_table_unlock(table
);
2809 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2811 struct bgp_process_queue
*pqnode
= data
;
2813 bgp_unlock(pqnode
->bgp
);
2815 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2818 void bgp_process_queue_init(void)
2820 if (!bm
->process_main_queue
)
2821 bm
->process_main_queue
=
2822 work_queue_new(bm
->master
, "process_main_queue");
2824 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2825 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2826 bm
->process_main_queue
->spec
.max_retries
= 0;
2827 bm
->process_main_queue
->spec
.hold
= 50;
2828 /* Use a higher yield value of 50ms for main queue processing */
2829 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2832 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2834 struct bgp_process_queue
*pqnode
;
2836 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2837 sizeof(struct bgp_process_queue
));
2839 /* unlocked in bgp_processq_del */
2840 pqnode
->bgp
= bgp_lock(bgp
);
2841 STAILQ_INIT(&pqnode
->pqueue
);
2846 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2848 #define ARBITRARY_PROCESS_QLEN 10000
2849 struct work_queue
*wq
= bm
->process_main_queue
;
2850 struct bgp_process_queue
*pqnode
;
2851 int pqnode_reuse
= 0;
2853 /* already scheduled for processing? */
2854 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2857 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2860 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2861 if (BGP_DEBUG(update
, UPDATE_OUT
))
2862 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2870 /* Add route nodes to an existing work queue item until reaching the
2871 limit only if is from the same BGP view and it's not an EOIU marker
2873 if (work_queue_item_count(wq
)) {
2874 struct work_queue_item
*item
= work_queue_last_item(wq
);
2875 pqnode
= item
->data
;
2877 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2878 || pqnode
->bgp
!= bgp
2879 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2880 pqnode
= bgp_processq_alloc(bgp
);
2884 pqnode
= bgp_processq_alloc(bgp
);
2885 /* all unlocked in bgp_process_wq */
2886 bgp_table_lock(bgp_node_table(rn
));
2888 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2891 /* can't be enqueued twice */
2892 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2893 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2897 work_queue_add(wq
, pqnode
);
2902 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2904 struct bgp_process_queue
*pqnode
;
2906 if (bm
->process_main_queue
== NULL
)
2909 pqnode
= bgp_processq_alloc(bgp
);
2911 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2912 work_queue_add(bm
->process_main_queue
, pqnode
);
2915 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2919 peer
= THREAD_ARG(thread
);
2920 peer
->t_pmax_restart
= NULL
;
2922 if (bgp_debug_neighbor_events(peer
))
2924 "%s Maximum-prefix restart timer expired, restore peering",
2927 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2928 zlog_debug("%s: %s peer_clear failed",
2929 __PRETTY_FUNCTION__
, peer
->host
);
2934 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2938 iana_safi_t pkt_safi
;
2940 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2943 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2944 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2945 PEER_STATUS_PREFIX_LIMIT
)
2950 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2951 " exceed, limit %" PRIu32
,
2952 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2953 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2954 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2956 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2957 PEER_FLAG_MAX_PREFIX_WARNING
))
2960 /* Convert AFI, SAFI to values for packet. */
2961 pkt_afi
= afi_int2iana(afi
);
2962 pkt_safi
= safi_int2iana(safi
);
2966 ndata
[0] = (pkt_afi
>> 8);
2968 ndata
[2] = pkt_safi
;
2969 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2970 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2971 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2972 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2974 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2975 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2976 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2980 /* Dynamic peers will just close their connection. */
2981 if (peer_dynamic_neighbor(peer
))
2984 /* restart timer start */
2985 if (peer
->pmax_restart
[afi
][safi
]) {
2986 peer
->v_pmax_restart
=
2987 peer
->pmax_restart
[afi
][safi
] * 60;
2989 if (bgp_debug_neighbor_events(peer
))
2991 "%s Maximum-prefix restart timer started for %d secs",
2992 peer
->host
, peer
->v_pmax_restart
);
2994 BGP_TIMER_ON(peer
->t_pmax_restart
,
2995 bgp_maximum_prefix_restart_timer
,
2996 peer
->v_pmax_restart
);
3001 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3002 PEER_STATUS_PREFIX_LIMIT
);
3004 if (peer
->pcount
[afi
][safi
]
3005 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3006 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3007 PEER_STATUS_PREFIX_THRESHOLD
)
3012 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3014 get_afi_safi_str(afi
, safi
, false), peer
->host
,
3015 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
3016 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3017 PEER_STATUS_PREFIX_THRESHOLD
);
3019 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3020 PEER_STATUS_PREFIX_THRESHOLD
);
3024 /* Unconditionally remove the route from the RIB, without taking
3025 * damping into consideration (eg, because the session went down)
3027 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3028 struct peer
*peer
, afi_t afi
, safi_t safi
)
3031 struct bgp
*bgp
= NULL
;
3032 bool delete_route
= false;
3034 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
3036 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3037 bgp_path_info_delete(rn
, pi
); /* keep historical info */
3039 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3042 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3043 delete_route
= true;
3045 if (bgp_node_set_defer_flag(rn
, true) < 0)
3046 delete_route
= true;
3048 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
3049 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
3050 bgp
= pi
->peer
->bgp
;
3051 if ((rn
->rt_node
) &&
3052 (bgp
->gr_info
[afi
][safi
]
3055 bgp
->gr_info
[afi
][safi
]
3064 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
3065 bgp_process(peer
->bgp
, rn
, afi
, safi
);
3068 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3069 struct peer
*peer
, afi_t afi
, safi_t safi
,
3070 struct prefix_rd
*prd
)
3072 /* apply dampening, if result is suppressed, we'll be retaining
3073 * the bgp_path_info in the RIB for historical reference.
3075 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3076 && peer
->sort
== BGP_PEER_EBGP
)
3077 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
3078 == BGP_DAMP_SUPPRESSED
) {
3079 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
3085 if (safi
== SAFI_MPLS_VPN
) {
3086 struct bgp_node
*prn
= NULL
;
3087 struct bgp_table
*table
= NULL
;
3089 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3090 (struct prefix
*)prd
);
3091 if (bgp_node_has_bgp_path_info_data(prn
)) {
3092 table
= bgp_node_get_bgp_table_info(prn
);
3094 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3095 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
3097 bgp_unlock_node(prn
);
3099 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3100 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3102 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
3103 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
3109 /* If this is an EVPN route, process for un-import. */
3110 if (safi
== SAFI_EVPN
)
3111 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
3113 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3116 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3117 struct peer
*peer
, struct attr
*attr
,
3118 struct bgp_node
*rn
)
3120 struct bgp_path_info
*new;
3122 /* Make new BGP info. */
3123 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3125 new->instance
= instance
;
3126 new->sub_type
= sub_type
;
3129 new->uptime
= bgp_clock();
3134 static void overlay_index_update(struct attr
*attr
,
3135 struct eth_segment_id
*eth_s_id
,
3136 union gw_addr
*gw_ip
)
3141 if (eth_s_id
== NULL
) {
3142 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
3143 sizeof(struct eth_segment_id
));
3145 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
3146 sizeof(struct eth_segment_id
));
3148 if (gw_ip
== NULL
) {
3149 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3151 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3152 sizeof(union gw_addr
));
3156 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3157 struct eth_segment_id
*eth_s_id
,
3158 union gw_addr
*gw_ip
)
3160 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
3161 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3163 struct eth_segment_id esi
;
3167 if (afi
!= AFI_L2VPN
)
3170 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
3171 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3173 if (gw_ip
== NULL
) {
3174 memset(&temp
, 0, sizeof(temp
));
3175 path_gw_ip_remote
= &temp
.ip
;
3177 path_gw_ip_remote
= gw_ip
;
3179 if (eth_s_id
== NULL
) {
3180 memset(&temp
, 0, sizeof(temp
));
3181 path_eth_s_id_remote
= &temp
.esi
;
3183 path_eth_s_id_remote
= eth_s_id
;
3185 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
3188 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
3189 sizeof(struct eth_segment_id
));
3192 /* Check if received nexthop is valid or not. */
3193 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3194 uint8_t type
, uint8_t stype
,
3195 struct attr
*attr
, struct bgp_node
*rn
)
3199 /* Only validated for unicast and multicast currently. */
3200 /* Also valid for EVPN where the nexthop is an IP address. */
3201 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3204 /* If NEXT_HOP is present, validate it. */
3205 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3206 if (attr
->nexthop
.s_addr
== 0
3207 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3208 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3213 /* If MP_NEXTHOP is present, validate it. */
3214 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3215 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3216 * it is not an IPv6 link-local address.
3218 if (attr
->mp_nexthop_len
) {
3219 switch (attr
->mp_nexthop_len
) {
3220 case BGP_ATTR_NHLEN_IPV4
:
3221 case BGP_ATTR_NHLEN_VPNV4
:
3222 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3223 || IPV4_CLASS_DE(ntohl(
3224 attr
->mp_nexthop_global_in
.s_addr
))
3225 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3229 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3230 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3231 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3232 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3233 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3234 || IN6_IS_ADDR_MULTICAST(
3235 &attr
->mp_nexthop_global
)
3236 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3249 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3250 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3251 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3252 uint32_t num_labels
, int soft_reconfig
,
3253 struct bgp_route_evpn
*evpn
)
3256 int aspath_loop_count
= 0;
3257 struct bgp_node
*rn
;
3259 struct attr new_attr
;
3260 struct attr
*attr_new
;
3261 struct bgp_path_info
*pi
;
3262 struct bgp_path_info
*new;
3263 struct bgp_path_info_extra
*extra
;
3265 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3267 int do_loop_check
= 1;
3268 int has_valid_label
= 0;
3270 uint8_t pi_type
= 0;
3271 uint8_t pi_sub_type
= 0;
3274 int vnc_implicit_withdraw
= 0;
3278 memset(&new_attr
, 0, sizeof(struct attr
));
3279 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3280 new_attr
.label
= MPLS_INVALID_LABEL
;
3283 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3284 /* TODO: Check to see if we can get rid of "is_valid_label" */
3285 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3286 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3288 has_valid_label
= bgp_is_valid_label(label
);
3290 /* When peer's soft reconfiguration enabled. Record input packet in
3293 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3294 && peer
!= bgp
->peer_self
)
3295 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3297 /* Check previously received route. */
3298 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3299 if (pi
->peer
== peer
&& pi
->type
== type
3300 && pi
->sub_type
== sub_type
3301 && pi
->addpath_rx_id
== addpath_id
)
3304 /* AS path local-as loop check. */
3305 if (peer
->change_local_as
) {
3306 if (peer
->allowas_in
[afi
][safi
])
3307 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3308 else if (!CHECK_FLAG(peer
->flags
,
3309 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3310 aspath_loop_count
= 1;
3312 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3313 > aspath_loop_count
) {
3314 peer
->stat_pfx_aspath_loop
++;
3315 reason
= "as-path contains our own AS;";
3320 /* If the peer is configured for "allowas-in origin" and the last ASN in
3322 * as-path is our ASN then we do not need to call aspath_loop_check
3324 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3325 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3328 /* AS path loop check. */
3329 if (do_loop_check
) {
3330 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3331 > peer
->allowas_in
[afi
][safi
]
3332 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3333 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3334 > peer
->allowas_in
[afi
][safi
])) {
3335 peer
->stat_pfx_aspath_loop
++;
3336 reason
= "as-path contains our own AS;";
3341 /* Route reflector originator ID check. */
3342 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3343 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3344 peer
->stat_pfx_originator_loop
++;
3345 reason
= "originator is us;";
3349 /* Route reflector cluster ID check. */
3350 if (bgp_cluster_filter(peer
, attr
)) {
3351 peer
->stat_pfx_cluster_loop
++;
3352 reason
= "reflected from the same cluster;";
3356 /* Apply incoming filter. */
3357 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3358 peer
->stat_pfx_filter
++;
3363 /* RFC 8212 to prevent route leaks.
3364 * This specification intends to improve this situation by requiring the
3365 * explicit configuration of both BGP Import and Export Policies for any
3366 * External BGP (EBGP) session such as customers, peers, or
3367 * confederation boundaries for all enabled address families. Through
3368 * codification of the aforementioned requirement, operators will
3369 * benefit from consistent behavior across different BGP
3372 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3373 if (!bgp_inbound_policy_exists(peer
,
3374 &peer
->filter
[afi
][safi
])) {
3375 reason
= "inbound policy missing";
3379 /* draft-ietf-idr-deprecate-as-set-confed-set
3380 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3381 * Eventually, This document (if approved) updates RFC 4271
3382 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3383 * and obsoletes RFC 6472.
3385 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3386 if (aspath_check_as_sets(attr
->aspath
)) {
3388 "as-path contains AS_SET or AS_CONFED_SET type;";
3394 /* Apply incoming route-map.
3395 * NB: new_attr may now contain newly allocated values from route-map
3397 * commands, so we need bgp_attr_flush in the error paths, until we
3399 * the attr (which takes over the memory references) */
3400 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3401 label
, num_labels
, rn
) == RMAP_DENY
) {
3402 peer
->stat_pfx_filter
++;
3403 reason
= "route-map;";
3404 bgp_attr_flush(&new_attr
);
3408 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3409 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3410 /* remove from RIB previous entry */
3411 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3414 if (peer
->sort
== BGP_PEER_EBGP
) {
3416 /* If we receive the graceful-shutdown community from an eBGP
3417 * peer we must lower local-preference */
3418 if (new_attr
.community
3419 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3420 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3421 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3423 /* If graceful-shutdown is configured then add the GSHUT
3424 * community to all paths received from eBGP peers */
3425 } else if (bgp_flag_check(peer
->bgp
,
3426 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3427 bgp_attr_add_gshut_community(&new_attr
);
3433 pi_sub_type
= pi
->sub_type
;
3436 /* next hop check. */
3437 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3438 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3439 pi_sub_type
, &new_attr
, rn
)) {
3440 peer
->stat_pfx_nh_invalid
++;
3441 reason
= "martian or self next-hop;";
3442 bgp_attr_flush(&new_attr
);
3446 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3447 peer
->stat_pfx_nh_invalid
++;
3448 reason
= "self mac;";
3452 attr_new
= bgp_attr_intern(&new_attr
);
3454 /* If the update is implicit withdraw. */
3456 pi
->uptime
= bgp_clock();
3457 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3459 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3461 /* Same attribute comes in. */
3462 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3463 && attrhash_cmp(pi
->attr
, attr_new
)
3464 && (!has_valid_label
3465 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3466 num_labels
* sizeof(mpls_label_t
))
3468 && (overlay_index_equal(
3469 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3470 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3471 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3472 BGP_CONFIG_DAMPENING
)
3473 && peer
->sort
== BGP_PEER_EBGP
3474 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3475 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3476 bgp_debug_rdpfxpath2str(
3477 afi
, safi
, prd
, p
, label
,
3478 num_labels
, addpath_id
? 1 : 0,
3479 addpath_id
, pfx_buf
,
3481 zlog_debug("%s rcvd %s", peer
->host
,
3485 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3486 != BGP_DAMP_SUPPRESSED
) {
3487 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3489 bgp_process(bgp
, rn
, afi
, safi
);
3491 } else /* Duplicate - odd */
3493 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3494 if (!peer
->rcvd_attr_printed
) {
3496 "%s rcvd UPDATE w/ attr: %s",
3498 peer
->rcvd_attr_str
);
3499 peer
->rcvd_attr_printed
= 1;
3502 bgp_debug_rdpfxpath2str(
3503 afi
, safi
, prd
, p
, label
,
3504 num_labels
, addpath_id
? 1 : 0,
3505 addpath_id
, pfx_buf
,
3508 "%s rcvd %s...duplicate ignored",
3509 peer
->host
, pfx_buf
);
3512 /* graceful restart STALE flag unset. */
3513 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3514 bgp_path_info_unset_flag(
3515 rn
, pi
, BGP_PATH_STALE
);
3516 bgp_node_set_defer_flag(rn
, false);
3517 bgp_process(bgp
, rn
, afi
, safi
);
3521 bgp_unlock_node(rn
);
3522 bgp_attr_unintern(&attr_new
);
3527 /* Withdraw/Announce before we fully processed the withdraw */
3528 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3529 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3530 bgp_debug_rdpfxpath2str(
3531 afi
, safi
, prd
, p
, label
, num_labels
,
3532 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3535 "%s rcvd %s, flapped quicker than processing",
3536 peer
->host
, pfx_buf
);
3539 bgp_path_info_restore(rn
, pi
);
3542 /* Received Logging. */
3543 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3544 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3545 num_labels
, addpath_id
? 1 : 0,
3546 addpath_id
, pfx_buf
,
3548 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3551 /* graceful restart STALE flag unset. */
3552 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3553 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3554 bgp_node_set_defer_flag(rn
, false);
3557 /* The attribute is changed. */
3558 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3560 /* implicit withdraw, decrement aggregate and pcount here.
3561 * only if update is accepted, they'll increment below.
3563 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3565 /* Update bgp route dampening information. */
3566 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3567 && peer
->sort
== BGP_PEER_EBGP
) {
3568 /* This is implicit withdraw so we should update
3571 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3572 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3575 if (safi
== SAFI_MPLS_VPN
) {
3576 struct bgp_node
*prn
= NULL
;
3577 struct bgp_table
*table
= NULL
;
3579 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3580 (struct prefix
*)prd
);
3581 if (bgp_node_has_bgp_path_info_data(prn
)) {
3582 table
= bgp_node_get_bgp_table_info(prn
);
3584 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3585 bgp
, prd
, table
, p
, pi
);
3587 bgp_unlock_node(prn
);
3589 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3590 && (safi
== SAFI_UNICAST
)) {
3591 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3593 * Implicit withdraw case.
3595 ++vnc_implicit_withdraw
;
3596 vnc_import_bgp_del_route(bgp
, p
, pi
);
3597 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3602 /* Special handling for EVPN update of an existing route. If the
3603 * extended community attribute has changed, we need to
3605 * the route using its existing extended community. It will be
3606 * subsequently processed for import with the new extended
3609 if (safi
== SAFI_EVPN
&& !same_attr
) {
3611 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3613 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3616 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3617 attr_new
->ecommunity
);
3619 if (bgp_debug_update(peer
, p
, NULL
, 1))
3621 "Change in EXT-COMM, existing %s new %s",
3623 pi
->attr
->ecommunity
),
3625 attr_new
->ecommunity
));
3626 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3632 /* Update to new attribute. */
3633 bgp_attr_unintern(&pi
->attr
);
3634 pi
->attr
= attr_new
;
3636 /* Update MPLS label */
3637 if (has_valid_label
) {
3638 extra
= bgp_path_info_extra_get(pi
);
3639 if (extra
->label
!= label
) {
3640 memcpy(&extra
->label
, label
,
3641 num_labels
* sizeof(mpls_label_t
));
3642 extra
->num_labels
= num_labels
;
3644 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3645 bgp_set_valid_label(&extra
->label
[0]);
3649 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3650 && (safi
== SAFI_UNICAST
)) {
3651 if (vnc_implicit_withdraw
) {
3653 * Add back the route with its new attributes
3655 * The route is still selected, until the route
3657 * queued by bgp_process actually runs. We have
3659 * update to the VNC side immediately to avoid
3661 * configuration changes (e.g., route-map
3663 * trigger re-importation of the entire RIB.
3665 vnc_import_bgp_add_route(bgp
, p
, pi
);
3666 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3670 /* Update Overlay Index */
3671 if (afi
== AFI_L2VPN
) {
3672 overlay_index_update(
3673 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3674 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3677 /* Update bgp route dampening information. */
3678 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3679 && peer
->sort
== BGP_PEER_EBGP
) {
3680 /* Now we do normal update dampening. */
3681 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3682 if (ret
== BGP_DAMP_SUPPRESSED
) {
3683 bgp_unlock_node(rn
);
3688 /* Nexthop reachability check - for unicast and
3689 * labeled-unicast.. */
3690 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3691 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3692 || (safi
== SAFI_EVPN
&&
3693 bgp_evpn_is_prefix_nht_supported(p
))) {
3694 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3695 && peer
->ttl
== BGP_DEFAULT_TTL
3696 && !CHECK_FLAG(peer
->flags
,
3697 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3699 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3704 struct bgp
*bgp_nexthop
= bgp
;
3706 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3707 bgp_nexthop
= pi
->extra
->bgp_orig
;
3709 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3711 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3712 pi
, NULL
, connected
)
3713 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3714 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3716 if (BGP_DEBUG(nht
, NHT
)) {
3717 char buf1
[INET6_ADDRSTRLEN
];
3719 (const void *)&attr_new
3721 buf1
, INET6_ADDRSTRLEN
);
3722 zlog_debug("%s(%s): NH unresolved",
3723 __FUNCTION__
, buf1
);
3725 bgp_path_info_unset_flag(rn
, pi
,
3729 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3732 if (safi
== SAFI_MPLS_VPN
) {
3733 struct bgp_node
*prn
= NULL
;
3734 struct bgp_table
*table
= NULL
;
3736 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3737 (struct prefix
*)prd
);
3738 if (bgp_node_has_bgp_path_info_data(prn
)) {
3739 table
= bgp_node_get_bgp_table_info(prn
);
3741 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3742 bgp
, prd
, table
, p
, pi
);
3744 bgp_unlock_node(prn
);
3748 /* If this is an EVPN route and some attribute has changed,
3750 * route for import. If the extended community has changed, we
3752 * have done the un-import earlier and the import would result
3754 * route getting injected into appropriate L2 VNIs. If it is
3756 * some other attribute change, the import will result in
3758 * the attributes for the route in the VNI(s).
3760 if (safi
== SAFI_EVPN
&& !same_attr
&&
3761 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3762 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3764 /* Process change. */
3765 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3767 bgp_process(bgp
, rn
, afi
, safi
);
3768 bgp_unlock_node(rn
);
3770 if (SAFI_UNICAST
== safi
3771 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3772 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3774 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3776 if ((SAFI_MPLS_VPN
== safi
)
3777 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3779 vpn_leak_to_vrf_update(bgp
, pi
);
3783 if (SAFI_MPLS_VPN
== safi
) {
3784 mpls_label_t label_decoded
= decode_label(label
);
3786 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3787 type
, sub_type
, &label_decoded
);
3789 if (SAFI_ENCAP
== safi
) {
3790 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3791 type
, sub_type
, NULL
);
3796 } // End of implicit withdraw
3798 /* Received Logging. */
3799 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3800 if (!peer
->rcvd_attr_printed
) {
3801 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3802 peer
->rcvd_attr_str
);
3803 peer
->rcvd_attr_printed
= 1;
3806 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3807 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3809 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3812 /* Make new BGP info. */
3813 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3815 /* Update MPLS label */
3816 if (has_valid_label
) {
3817 extra
= bgp_path_info_extra_get(new);
3818 if (extra
->label
!= label
) {
3819 memcpy(&extra
->label
, label
,
3820 num_labels
* sizeof(mpls_label_t
));
3821 extra
->num_labels
= num_labels
;
3823 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3824 bgp_set_valid_label(&extra
->label
[0]);
3827 /* Update Overlay Index */
3828 if (afi
== AFI_L2VPN
) {
3829 overlay_index_update(new->attr
,
3830 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3831 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3833 /* Nexthop reachability check. */
3834 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3835 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3836 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3837 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3838 && peer
->ttl
== BGP_DEFAULT_TTL
3839 && !CHECK_FLAG(peer
->flags
,
3840 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3841 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3846 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3848 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3850 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3851 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3853 if (BGP_DEBUG(nht
, NHT
)) {
3854 char buf1
[INET6_ADDRSTRLEN
];
3856 (const void *)&attr_new
->nexthop
,
3857 buf1
, INET6_ADDRSTRLEN
);
3858 zlog_debug("%s(%s): NH unresolved",
3859 __FUNCTION__
, buf1
);
3861 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3864 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3867 new->addpath_rx_id
= addpath_id
;
3869 /* Increment prefix */
3870 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3872 /* Register new BGP information. */
3873 bgp_path_info_add(rn
, new);
3875 /* route_node_get lock */
3876 bgp_unlock_node(rn
);
3879 if (safi
== SAFI_MPLS_VPN
) {
3880 struct bgp_node
*prn
= NULL
;
3881 struct bgp_table
*table
= NULL
;
3883 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3884 if (bgp_node_has_bgp_path_info_data(prn
)) {
3885 table
= bgp_node_get_bgp_table_info(prn
);
3887 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3888 bgp
, prd
, table
, p
, new);
3890 bgp_unlock_node(prn
);
3894 /* If maximum prefix count is configured and current prefix
3896 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3899 /* If this is an EVPN route, process for import. */
3900 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3901 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3903 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3905 /* Process change. */
3906 bgp_process(bgp
, rn
, afi
, safi
);
3908 if (SAFI_UNICAST
== safi
3909 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3910 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3911 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3913 if ((SAFI_MPLS_VPN
== safi
)
3914 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3916 vpn_leak_to_vrf_update(bgp
, new);
3919 if (SAFI_MPLS_VPN
== safi
) {
3920 mpls_label_t label_decoded
= decode_label(label
);
3922 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3923 sub_type
, &label_decoded
);
3925 if (SAFI_ENCAP
== safi
) {
3926 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3933 /* This BGP update is filtered. Log the reason then update BGP
3936 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3938 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3939 if (!peer
->rcvd_attr_printed
) {
3940 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3941 peer
->rcvd_attr_str
);
3942 peer
->rcvd_attr_printed
= 1;
3945 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3946 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3948 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3949 peer
->host
, pfx_buf
, reason
);
3953 /* If this is an EVPN route, un-import it as it is now filtered.
3955 if (safi
== SAFI_EVPN
)
3956 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3958 if (SAFI_UNICAST
== safi
3959 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3960 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3962 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3964 if ((SAFI_MPLS_VPN
== safi
)
3965 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3967 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3970 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3973 bgp_unlock_node(rn
);
3977 * Filtered update is treated as an implicit withdrawal (see
3979 * a few lines above)
3981 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3982 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3990 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3991 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3992 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3993 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3996 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3997 struct bgp_node
*rn
;
3998 struct bgp_path_info
*pi
;
4001 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4002 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4010 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4012 /* If peer is soft reconfiguration enabled. Record input packet for
4013 * further calculation.
4015 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4016 * routes that are filtered. This tanks out Quagga RS pretty badly due
4018 * the iteration over all RS clients.
4019 * Since we need to remove the entry from adj_in anyway, do that first
4021 * if there was no entry, we don't need to do anything more.
4023 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4024 && peer
!= bgp
->peer_self
)
4025 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
4026 peer
->stat_pfx_dup_withdraw
++;
4028 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4029 bgp_debug_rdpfxpath2str(
4030 afi
, safi
, prd
, p
, label
, num_labels
,
4031 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4034 "%s withdrawing route %s not in adj-in",
4035 peer
->host
, pfx_buf
);
4037 bgp_unlock_node(rn
);
4041 /* Lookup withdrawn route. */
4042 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4043 if (pi
->peer
== peer
&& pi
->type
== type
4044 && pi
->sub_type
== sub_type
4045 && pi
->addpath_rx_id
== addpath_id
)
4049 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4050 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4051 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4053 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4057 /* Withdraw specified route from routing table. */
4058 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4059 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
4060 if (SAFI_UNICAST
== safi
4061 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4062 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4063 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4065 if ((SAFI_MPLS_VPN
== safi
)
4066 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4068 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4070 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4071 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4072 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4074 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4077 /* Unlock bgp_node_get() lock. */
4078 bgp_unlock_node(rn
);
4083 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4086 struct update_subgroup
*subgrp
;
4087 subgrp
= peer_subgroup(peer
, afi
, safi
);
4088 subgroup_default_originate(subgrp
, withdraw
);
4093 * bgp_stop_announce_route_timer
4095 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4097 if (!paf
->t_announce_route
)
4100 THREAD_TIMER_OFF(paf
->t_announce_route
);
4104 * bgp_announce_route_timer_expired
4106 * Callback that is invoked when the route announcement timer for a
4109 static int bgp_announce_route_timer_expired(struct thread
*t
)
4111 struct peer_af
*paf
;
4114 paf
= THREAD_ARG(t
);
4117 if (peer
->status
!= Established
)
4120 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4123 peer_af_announce_route(paf
, 1);
4128 * bgp_announce_route
4130 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4132 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4134 struct peer_af
*paf
;
4135 struct update_subgroup
*subgrp
;
4137 paf
= peer_af_find(peer
, afi
, safi
);
4140 subgrp
= PAF_SUBGRP(paf
);
4143 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4144 * or a refresh has already been triggered.
4146 if (!subgrp
|| paf
->t_announce_route
)
4150 * Start a timer to stagger/delay the announce. This serves
4151 * two purposes - announcement can potentially be combined for
4152 * multiple peers and the announcement doesn't happen in the
4155 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4156 (subgrp
->peer_count
== 1)
4157 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4158 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4159 &paf
->t_announce_route
);
4163 * Announce routes from all AF tables to a peer.
4165 * This should ONLY be called when there is a need to refresh the
4166 * routes to the peer based on a policy change for this peer alone
4167 * or a route refresh request received from the peer.
4168 * The operation will result in splitting the peer from its existing
4169 * subgroups and putting it in new subgroups.
4171 void bgp_announce_route_all(struct peer
*peer
)
4176 FOREACH_AFI_SAFI (afi
, safi
)
4177 bgp_announce_route(peer
, afi
, safi
);
4180 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4181 struct bgp_table
*table
,
4182 struct prefix_rd
*prd
)
4185 struct bgp_node
*rn
;
4186 struct bgp_adj_in
*ain
;
4189 table
= peer
->bgp
->rib
[afi
][safi
];
4191 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4192 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
4193 if (ain
->peer
!= peer
)
4196 struct bgp_path_info
*pi
;
4197 uint32_t num_labels
= 0;
4198 mpls_label_t
*label_pnt
= NULL
;
4199 struct bgp_route_evpn evpn
;
4201 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4203 if (pi
->peer
== peer
)
4206 if (pi
&& pi
->extra
)
4207 num_labels
= pi
->extra
->num_labels
;
4209 label_pnt
= &pi
->extra
->label
[0];
4211 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4214 memset(&evpn
, 0, sizeof(evpn
));
4216 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
4217 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4218 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4219 num_labels
, 1, &evpn
);
4222 bgp_unlock_node(rn
);
4228 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4230 struct bgp_node
*rn
;
4231 struct bgp_table
*table
;
4233 if (peer
->status
!= Established
)
4236 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4237 && (safi
!= SAFI_EVPN
))
4238 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4240 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4241 rn
= bgp_route_next(rn
)) {
4242 table
= bgp_node_get_bgp_table_info(rn
);
4243 if (table
!= NULL
) {
4244 struct prefix_rd prd
;
4246 prd
.family
= AF_UNSPEC
;
4248 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4250 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4257 struct bgp_clear_node_queue
{
4258 struct bgp_node
*rn
;
4261 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4263 struct bgp_clear_node_queue
*cnq
= data
;
4264 struct bgp_node
*rn
= cnq
->rn
;
4265 struct peer
*peer
= wq
->spec
.data
;
4266 struct bgp_path_info
*pi
;
4268 afi_t afi
= bgp_node_table(rn
)->afi
;
4269 safi_t safi
= bgp_node_table(rn
)->safi
;
4274 /* It is possible that we have multiple paths for a prefix from a peer
4275 * if that peer is using AddPath.
4277 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4278 if (pi
->peer
!= peer
)
4281 /* graceful restart STALE flag set. */
4282 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4283 && peer
->nsf
[afi
][safi
]
4284 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4285 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4286 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4288 /* If this is an EVPN route, process for
4290 if (safi
== SAFI_EVPN
)
4291 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4293 /* Handle withdraw for VRF route-leaking and L3VPN */
4294 if (SAFI_UNICAST
== safi
4295 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4296 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4297 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4300 if (SAFI_MPLS_VPN
== safi
&&
4301 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4302 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4305 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4311 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4313 struct bgp_clear_node_queue
*cnq
= data
;
4314 struct bgp_node
*rn
= cnq
->rn
;
4315 struct bgp_table
*table
= bgp_node_table(rn
);
4317 bgp_unlock_node(rn
);
4318 bgp_table_unlock(table
);
4319 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4322 static void bgp_clear_node_complete(struct work_queue
*wq
)
4324 struct peer
*peer
= wq
->spec
.data
;
4326 /* Tickle FSM to start moving again */
4327 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4329 peer_unlock(peer
); /* bgp_clear_route */
4332 static void bgp_clear_node_queue_init(struct peer
*peer
)
4334 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4336 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4337 #undef CLEAR_QUEUE_NAME_LEN
4339 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4340 peer
->clear_node_queue
->spec
.hold
= 10;
4341 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4342 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4343 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4344 peer
->clear_node_queue
->spec
.max_retries
= 0;
4346 /* we only 'lock' this peer reference when the queue is actually active
4348 peer
->clear_node_queue
->spec
.data
= peer
;
4351 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4352 struct bgp_table
*table
)
4354 struct bgp_node
*rn
;
4355 int force
= bm
->process_main_queue
? 0 : 1;
4358 table
= peer
->bgp
->rib
[afi
][safi
];
4360 /* If still no table => afi/safi isn't configured at all or smth. */
4364 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4365 struct bgp_path_info
*pi
, *next
;
4366 struct bgp_adj_in
*ain
;
4367 struct bgp_adj_in
*ain_next
;
4369 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4370 * queued for every clearing peer, regardless of whether it is
4371 * relevant to the peer at hand.
4373 * Overview: There are 3 different indices which need to be
4374 * scrubbed, potentially, when a peer is removed:
4376 * 1 peer's routes visible via the RIB (ie accepted routes)
4377 * 2 peer's routes visible by the (optional) peer's adj-in index
4378 * 3 other routes visible by the peer's adj-out index
4380 * 3 there is no hurry in scrubbing, once the struct peer is
4381 * removed from bgp->peer, we could just GC such deleted peer's
4382 * adj-outs at our leisure.
4384 * 1 and 2 must be 'scrubbed' in some way, at least made
4385 * invisible via RIB index before peer session is allowed to be
4386 * brought back up. So one needs to know when such a 'search' is
4391 * - there'd be a single global queue or a single RIB walker
4392 * - rather than tracking which route_nodes still need to be
4393 * examined on a peer basis, we'd track which peers still
4396 * Given that our per-peer prefix-counts now should be reliable,
4397 * this may actually be achievable. It doesn't seem to be a huge
4398 * problem at this time,
4400 * It is possible that we have multiple paths for a prefix from
4402 * if that peer is using AddPath.
4406 ain_next
= ain
->next
;
4408 if (ain
->peer
== peer
) {
4409 bgp_adj_in_remove(rn
, ain
);
4410 bgp_unlock_node(rn
);
4416 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4418 if (pi
->peer
!= peer
)
4422 bgp_path_info_reap(rn
, pi
);
4424 struct bgp_clear_node_queue
*cnq
;
4426 /* both unlocked in bgp_clear_node_queue_del */
4427 bgp_table_lock(bgp_node_table(rn
));
4430 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4431 sizeof(struct bgp_clear_node_queue
));
4433 work_queue_add(peer
->clear_node_queue
, cnq
);
4441 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4443 struct bgp_node
*rn
;
4444 struct bgp_table
*table
;
4446 if (peer
->clear_node_queue
== NULL
)
4447 bgp_clear_node_queue_init(peer
);
4449 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4450 * Idle until it receives a Clearing_Completed event. This protects
4451 * against peers which flap faster than we can we clear, which could
4454 * a) race with routes from the new session being installed before
4455 * clear_route_node visits the node (to delete the route of that
4457 * b) resource exhaustion, clear_route_node likely leads to an entry
4458 * on the process_main queue. Fast-flapping could cause that queue
4462 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4463 * the unlock will happen upon work-queue completion; other wise, the
4464 * unlock happens at the end of this function.
4466 if (!peer
->clear_node_queue
->thread
)
4469 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4470 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4472 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4473 rn
= bgp_route_next(rn
)) {
4474 table
= bgp_node_get_bgp_table_info(rn
);
4478 bgp_clear_route_table(peer
, afi
, safi
, table
);
4481 /* unlock if no nodes got added to the clear-node-queue. */
4482 if (!peer
->clear_node_queue
->thread
)
4486 void bgp_clear_route_all(struct peer
*peer
)
4491 FOREACH_AFI_SAFI (afi
, safi
)
4492 bgp_clear_route(peer
, afi
, safi
);
4495 rfapiProcessPeerDown(peer
);
4499 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4501 struct bgp_table
*table
;
4502 struct bgp_node
*rn
;
4503 struct bgp_adj_in
*ain
;
4504 struct bgp_adj_in
*ain_next
;
4506 table
= peer
->bgp
->rib
[afi
][safi
];
4508 /* It is possible that we have multiple paths for a prefix from a peer
4509 * if that peer is using AddPath.
4511 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4515 ain_next
= ain
->next
;
4517 if (ain
->peer
== peer
) {
4518 bgp_adj_in_remove(rn
, ain
);
4519 bgp_unlock_node(rn
);
4527 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4529 struct bgp_node
*rn
;
4530 struct bgp_path_info
*pi
;
4531 struct bgp_table
*table
;
4533 if (safi
== SAFI_MPLS_VPN
) {
4534 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4535 rn
= bgp_route_next(rn
)) {
4536 struct bgp_node
*rm
;
4538 /* look for neighbor in tables */
4539 table
= bgp_node_get_bgp_table_info(rn
);
4543 for (rm
= bgp_table_top(table
); rm
;
4544 rm
= bgp_route_next(rm
))
4545 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4547 if (pi
->peer
!= peer
)
4549 if (!CHECK_FLAG(pi
->flags
,
4553 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4558 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4559 rn
= bgp_route_next(rn
))
4560 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4562 if (pi
->peer
!= peer
)
4564 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4566 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4572 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4574 if (peer
->sort
== BGP_PEER_IBGP
)
4577 if (peer
->sort
== BGP_PEER_EBGP
4578 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4579 || FILTER_LIST_OUT_NAME(filter
)
4580 || DISTRIBUTE_OUT_NAME(filter
)))
4585 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4587 if (peer
->sort
== BGP_PEER_IBGP
)
4590 if (peer
->sort
== BGP_PEER_EBGP
4591 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4592 || FILTER_LIST_IN_NAME(filter
)
4593 || DISTRIBUTE_IN_NAME(filter
)))
4598 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4601 struct bgp_node
*rn
;
4602 struct bgp_path_info
*pi
;
4603 struct bgp_path_info
*next
;
4605 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4606 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4609 /* Unimport EVPN routes from VRFs */
4610 if (safi
== SAFI_EVPN
)
4611 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4615 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4616 && pi
->type
== ZEBRA_ROUTE_BGP
4617 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4618 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4619 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4621 if (bgp_fibupd_safi(safi
))
4622 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4624 bgp_path_info_reap(rn
, pi
);
4629 /* Delete all kernel routes. */
4630 void bgp_cleanup_routes(struct bgp
*bgp
)
4633 struct bgp_node
*rn
;
4634 struct bgp_table
*table
;
4636 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4637 if (afi
== AFI_L2VPN
)
4639 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4642 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4644 if (afi
!= AFI_L2VPN
) {
4646 safi
= SAFI_MPLS_VPN
;
4647 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4648 rn
= bgp_route_next(rn
)) {
4649 table
= bgp_node_get_bgp_table_info(rn
);
4650 if (table
!= NULL
) {
4651 bgp_cleanup_table(bgp
, table
, safi
);
4652 bgp_table_finish(&table
);
4653 bgp_node_set_bgp_table_info(rn
, NULL
);
4654 bgp_unlock_node(rn
);
4658 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4659 rn
= bgp_route_next(rn
)) {
4660 table
= bgp_node_get_bgp_table_info(rn
);
4661 if (table
!= NULL
) {
4662 bgp_cleanup_table(bgp
, table
, safi
);
4663 bgp_table_finish(&table
);
4664 bgp_node_set_bgp_table_info(rn
, NULL
);
4665 bgp_unlock_node(rn
);
4670 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4671 rn
= bgp_route_next(rn
)) {
4672 table
= bgp_node_get_bgp_table_info(rn
);
4673 if (table
!= NULL
) {
4674 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4675 bgp_table_finish(&table
);
4676 bgp_node_set_bgp_table_info(rn
, NULL
);
4677 bgp_unlock_node(rn
);
4682 void bgp_reset(void)
4685 bgp_zclient_reset();
4686 access_list_reset();
4687 prefix_list_reset();
4690 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4692 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4693 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4694 PEER_CAP_ADDPATH_AF_TX_RCV
));
4697 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4699 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4700 struct bgp_nlri
*packet
)
4709 int addpath_encoded
;
4710 uint32_t addpath_id
;
4713 lim
= pnt
+ packet
->length
;
4715 safi
= packet
->safi
;
4717 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4719 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4720 syntactic validity. If the field is syntactically incorrect,
4721 then the Error Subcode is set to Invalid Network Field. */
4722 for (; pnt
< lim
; pnt
+= psize
) {
4723 /* Clear prefix structure. */
4724 memset(&p
, 0, sizeof(struct prefix
));
4726 if (addpath_encoded
) {
4728 /* When packet overflow occurs return immediately. */
4729 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4730 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4732 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4733 addpath_id
= ntohl(addpath_id
);
4734 pnt
+= BGP_ADDPATH_ID_LEN
;
4737 /* Fetch prefix length. */
4738 p
.prefixlen
= *pnt
++;
4739 /* afi/safi validity already verified by caller,
4740 * bgp_update_receive */
4741 p
.family
= afi2family(afi
);
4743 /* Prefix length check. */
4744 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4747 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4748 peer
->host
, p
.prefixlen
, packet
->afi
);
4749 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4752 /* Packet size overflow check. */
4753 psize
= PSIZE(p
.prefixlen
);
4755 /* When packet overflow occur return immediately. */
4756 if (pnt
+ psize
> lim
) {
4759 "%s [Error] Update packet error (prefix length %d overflows packet)",
4760 peer
->host
, p
.prefixlen
);
4761 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4764 /* Defensive coding, double-check the psize fits in a struct
4766 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4769 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4770 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4771 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4774 /* Fetch prefix from NLRI packet. */
4775 memcpy(p
.u
.val
, pnt
, psize
);
4777 /* Check address. */
4778 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4779 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4780 /* From RFC4271 Section 6.3:
4782 * If a prefix in the NLRI field is semantically
4784 * (e.g., an unexpected multicast IP address),
4786 * be logged locally, and the prefix SHOULD be
4791 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4792 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4797 /* Check address. */
4798 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4799 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4804 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4806 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4811 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4816 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4818 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4825 /* Normal process. */
4827 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4828 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4829 NULL
, NULL
, 0, 0, NULL
);
4831 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4832 safi
, ZEBRA_ROUTE_BGP
,
4833 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4836 /* Do not send BGP notification twice when maximum-prefix count
4838 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4839 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4841 /* Address family configuration mismatch. */
4843 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4846 /* Packet length consistency check. */
4850 "%s [Error] Update packet error (prefix length mismatch with total length)",
4852 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4855 return BGP_NLRI_PARSE_OK
;
4858 static struct bgp_static
*bgp_static_new(void)
4860 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4863 static void bgp_static_free(struct bgp_static
*bgp_static
)
4865 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4866 route_map_counter_decrement(bgp_static
->rmap
.map
);
4868 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4869 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4872 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4873 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4875 struct bgp_node
*rn
;
4876 struct bgp_path_info
*pi
;
4877 struct bgp_path_info
*new;
4878 struct bgp_path_info rmap_path
;
4880 struct attr
*attr_new
;
4881 route_map_result_t ret
;
4883 int vnc_implicit_withdraw
= 0;
4890 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4892 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4894 attr
.nexthop
= bgp_static
->igpnexthop
;
4895 attr
.med
= bgp_static
->igpmetric
;
4896 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4898 if (bgp_static
->atomic
)
4899 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4901 /* Store label index, if required. */
4902 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4903 attr
.label_index
= bgp_static
->label_index
;
4904 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4907 /* Apply route-map. */
4908 if (bgp_static
->rmap
.name
) {
4909 struct attr attr_tmp
= attr
;
4911 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4912 rmap_path
.peer
= bgp
->peer_self
;
4913 rmap_path
.attr
= &attr_tmp
;
4915 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4917 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4920 bgp
->peer_self
->rmap_type
= 0;
4922 if (ret
== RMAP_DENYMATCH
) {
4923 /* Free uninterned attribute. */
4924 bgp_attr_flush(&attr_tmp
);
4926 /* Unintern original. */
4927 aspath_unintern(&attr
.aspath
);
4928 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4932 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4933 bgp_attr_add_gshut_community(&attr_tmp
);
4935 attr_new
= bgp_attr_intern(&attr_tmp
);
4938 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4939 bgp_attr_add_gshut_community(&attr
);
4941 attr_new
= bgp_attr_intern(&attr
);
4944 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4945 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4946 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4950 if (attrhash_cmp(pi
->attr
, attr_new
)
4951 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4952 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4953 bgp_unlock_node(rn
);
4954 bgp_attr_unintern(&attr_new
);
4955 aspath_unintern(&attr
.aspath
);
4958 /* The attribute is changed. */
4959 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4961 /* Rewrite BGP route information. */
4962 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4963 bgp_path_info_restore(rn
, pi
);
4965 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4967 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4968 && (safi
== SAFI_UNICAST
)) {
4969 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4971 * Implicit withdraw case.
4972 * We have to do this before pi is
4975 ++vnc_implicit_withdraw
;
4976 vnc_import_bgp_del_route(bgp
, p
, pi
);
4977 vnc_import_bgp_exterior_del_route(
4982 bgp_attr_unintern(&pi
->attr
);
4983 pi
->attr
= attr_new
;
4984 pi
->uptime
= bgp_clock();
4986 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4987 && (safi
== SAFI_UNICAST
)) {
4988 if (vnc_implicit_withdraw
) {
4989 vnc_import_bgp_add_route(bgp
, p
, pi
);
4990 vnc_import_bgp_exterior_add_route(
4996 /* Nexthop reachability check. */
4997 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4998 && (safi
== SAFI_UNICAST
4999 || safi
== SAFI_LABELED_UNICAST
)) {
5001 struct bgp
*bgp_nexthop
= bgp
;
5003 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5004 bgp_nexthop
= pi
->extra
->bgp_orig
;
5006 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5008 bgp_path_info_set_flag(rn
, pi
,
5011 if (BGP_DEBUG(nht
, NHT
)) {
5012 char buf1
[INET6_ADDRSTRLEN
];
5013 inet_ntop(p
->family
,
5017 "%s(%s): Route not in table, not advertising",
5018 __FUNCTION__
, buf1
);
5020 bgp_path_info_unset_flag(
5021 rn
, pi
, BGP_PATH_VALID
);
5024 /* Delete the NHT structure if any, if we're
5026 * enabling/disabling import check. We
5027 * deregister the route
5028 * from NHT to avoid overloading NHT and the
5029 * process interaction
5031 bgp_unlink_nexthop(pi
);
5032 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
5034 /* Process change. */
5035 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5036 bgp_process(bgp
, rn
, afi
, safi
);
5038 if (SAFI_UNICAST
== safi
5039 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5041 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5042 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5046 bgp_unlock_node(rn
);
5047 aspath_unintern(&attr
.aspath
);
5052 /* Make new BGP info. */
5053 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5055 /* Nexthop reachability check. */
5056 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5057 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5058 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5059 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5061 if (BGP_DEBUG(nht
, NHT
)) {
5062 char buf1
[INET6_ADDRSTRLEN
];
5063 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5066 "%s(%s): Route not in table, not advertising",
5067 __FUNCTION__
, buf1
);
5069 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
5072 /* Delete the NHT structure if any, if we're toggling between
5073 * enabling/disabling import check. We deregister the route
5074 * from NHT to avoid overloading NHT and the process interaction
5076 bgp_unlink_nexthop(new);
5078 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5081 /* Aggregate address increment. */
5082 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5084 /* Register new BGP information. */
5085 bgp_path_info_add(rn
, new);
5087 /* route_node_get lock */
5088 bgp_unlock_node(rn
);
5090 /* Process change. */
5091 bgp_process(bgp
, rn
, afi
, safi
);
5093 if (SAFI_UNICAST
== safi
5094 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5095 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5096 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5099 /* Unintern original. */
5100 aspath_unintern(&attr
.aspath
);
5103 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5106 struct bgp_node
*rn
;
5107 struct bgp_path_info
*pi
;
5109 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5111 /* Check selected route and self inserted route. */
5112 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5113 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5114 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5117 /* Withdraw static BGP route from routing table. */
5119 if (SAFI_UNICAST
== safi
5120 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5121 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5122 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5124 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5125 bgp_unlink_nexthop(pi
);
5126 bgp_path_info_delete(rn
, pi
);
5127 bgp_process(bgp
, rn
, afi
, safi
);
5130 /* Unlock bgp_node_lookup. */
5131 bgp_unlock_node(rn
);
5135 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5137 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
5138 afi_t afi
, safi_t safi
,
5139 struct prefix_rd
*prd
)
5141 struct bgp_node
*rn
;
5142 struct bgp_path_info
*pi
;
5144 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5146 /* Check selected route and self inserted route. */
5147 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5148 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5149 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5152 /* Withdraw static BGP route from routing table. */
5155 rfapiProcessWithdraw(
5156 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5157 1); /* Kill, since it is an administrative change */
5159 if (SAFI_MPLS_VPN
== safi
5160 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5161 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5163 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5164 bgp_path_info_delete(rn
, pi
);
5165 bgp_process(bgp
, rn
, afi
, safi
);
5168 /* Unlock bgp_node_lookup. */
5169 bgp_unlock_node(rn
);
5172 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
5173 struct bgp_static
*bgp_static
, afi_t afi
,
5176 struct bgp_node
*rn
;
5177 struct bgp_path_info
*new;
5178 struct attr
*attr_new
;
5179 struct attr attr
= {0};
5180 struct bgp_path_info
*pi
;
5182 mpls_label_t label
= 0;
5184 uint32_t num_labels
= 0;
5189 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5191 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5194 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5196 attr
.nexthop
= bgp_static
->igpnexthop
;
5197 attr
.med
= bgp_static
->igpmetric
;
5198 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5200 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5201 || (safi
== SAFI_ENCAP
)) {
5202 if (afi
== AFI_IP
) {
5203 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5204 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5207 if (afi
== AFI_L2VPN
) {
5208 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5210 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5211 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5212 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5213 sizeof(struct in6_addr
));
5214 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5215 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5216 struct bgp_encap_type_vxlan bet
;
5217 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5218 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5219 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5221 if (bgp_static
->router_mac
) {
5222 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5225 /* Apply route-map. */
5226 if (bgp_static
->rmap
.name
) {
5227 struct attr attr_tmp
= attr
;
5228 struct bgp_path_info rmap_path
;
5229 route_map_result_t ret
;
5231 rmap_path
.peer
= bgp
->peer_self
;
5232 rmap_path
.attr
= &attr_tmp
;
5234 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5236 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5239 bgp
->peer_self
->rmap_type
= 0;
5241 if (ret
== RMAP_DENYMATCH
) {
5242 /* Free uninterned attribute. */
5243 bgp_attr_flush(&attr_tmp
);
5245 /* Unintern original. */
5246 aspath_unintern(&attr
.aspath
);
5247 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5252 attr_new
= bgp_attr_intern(&attr_tmp
);
5254 attr_new
= bgp_attr_intern(&attr
);
5257 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5258 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5259 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5263 memset(&add
, 0, sizeof(union gw_addr
));
5264 if (attrhash_cmp(pi
->attr
, attr_new
)
5265 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5266 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5267 bgp_unlock_node(rn
);
5268 bgp_attr_unintern(&attr_new
);
5269 aspath_unintern(&attr
.aspath
);
5272 /* The attribute is changed. */
5273 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5275 /* Rewrite BGP route information. */
5276 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5277 bgp_path_info_restore(rn
, pi
);
5279 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5280 bgp_attr_unintern(&pi
->attr
);
5281 pi
->attr
= attr_new
;
5282 pi
->uptime
= bgp_clock();
5285 label
= decode_label(&pi
->extra
->label
[0]);
5288 /* Process change. */
5289 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5290 bgp_process(bgp
, rn
, afi
, safi
);
5292 if (SAFI_MPLS_VPN
== safi
5293 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5294 vpn_leak_to_vrf_update(bgp
, pi
);
5297 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5298 pi
->attr
, afi
, safi
, pi
->type
,
5299 pi
->sub_type
, &label
);
5301 bgp_unlock_node(rn
);
5302 aspath_unintern(&attr
.aspath
);
5308 /* Make new BGP info. */
5309 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5311 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5312 new->extra
= bgp_path_info_extra_new();
5314 new->extra
->label
[0] = bgp_static
->label
;
5315 new->extra
->num_labels
= num_labels
;
5318 label
= decode_label(&bgp_static
->label
);
5321 /* Aggregate address increment. */
5322 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5324 /* Register new BGP information. */
5325 bgp_path_info_add(rn
, new);
5326 /* route_node_get lock */
5327 bgp_unlock_node(rn
);
5329 /* Process change. */
5330 bgp_process(bgp
, rn
, afi
, safi
);
5332 if (SAFI_MPLS_VPN
== safi
5333 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5334 vpn_leak_to_vrf_update(bgp
, new);
5337 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5338 safi
, new->type
, new->sub_type
, &label
);
5341 /* Unintern original. */
5342 aspath_unintern(&attr
.aspath
);
5345 /* Configure static BGP network. When user don't run zebra, static
5346 route should be installed as valid. */
5347 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5348 const char *ip_str
, afi_t afi
, safi_t safi
,
5349 const char *rmap
, int backdoor
, uint32_t label_index
)
5351 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5354 struct bgp_static
*bgp_static
;
5355 struct bgp_node
*rn
;
5356 uint8_t need_update
= 0;
5358 /* Convert IP prefix string to struct prefix. */
5359 ret
= str2prefix(ip_str
, &p
);
5361 vty_out(vty
, "%% Malformed prefix\n");
5362 return CMD_WARNING_CONFIG_FAILED
;
5364 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5365 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5366 return CMD_WARNING_CONFIG_FAILED
;
5373 /* Set BGP static route configuration. */
5374 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5377 vty_out(vty
, "%% Can't find static route specified\n");
5378 return CMD_WARNING_CONFIG_FAILED
;
5381 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5383 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5384 && (label_index
!= bgp_static
->label_index
)) {
5386 "%% label-index doesn't match static route\n");
5387 return CMD_WARNING_CONFIG_FAILED
;
5390 if ((rmap
&& bgp_static
->rmap
.name
)
5391 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5393 "%% route-map name doesn't match static route\n");
5394 return CMD_WARNING_CONFIG_FAILED
;
5397 /* Update BGP RIB. */
5398 if (!bgp_static
->backdoor
)
5399 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5401 /* Clear configuration. */
5402 bgp_static_free(bgp_static
);
5403 bgp_node_set_bgp_static_info(rn
, NULL
);
5404 bgp_unlock_node(rn
);
5405 bgp_unlock_node(rn
);
5408 /* Set BGP static route configuration. */
5409 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5411 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5413 /* Configuration change. */
5414 /* Label index cannot be changed. */
5415 if (bgp_static
->label_index
!= label_index
) {
5416 vty_out(vty
, "%% cannot change label-index\n");
5417 return CMD_WARNING_CONFIG_FAILED
;
5420 /* Check previous routes are installed into BGP. */
5421 if (bgp_static
->valid
5422 && bgp_static
->backdoor
!= backdoor
)
5425 bgp_static
->backdoor
= backdoor
;
5428 XFREE(MTYPE_ROUTE_MAP_NAME
,
5429 bgp_static
->rmap
.name
);
5430 route_map_counter_decrement(
5431 bgp_static
->rmap
.map
);
5432 bgp_static
->rmap
.name
=
5433 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5434 bgp_static
->rmap
.map
=
5435 route_map_lookup_by_name(rmap
);
5436 route_map_counter_increment(
5437 bgp_static
->rmap
.map
);
5439 XFREE(MTYPE_ROUTE_MAP_NAME
,
5440 bgp_static
->rmap
.name
);
5441 route_map_counter_decrement(
5442 bgp_static
->rmap
.map
);
5443 bgp_static
->rmap
.name
= NULL
;
5444 bgp_static
->rmap
.map
= NULL
;
5445 bgp_static
->valid
= 0;
5447 bgp_unlock_node(rn
);
5449 /* New configuration. */
5450 bgp_static
= bgp_static_new();
5451 bgp_static
->backdoor
= backdoor
;
5452 bgp_static
->valid
= 0;
5453 bgp_static
->igpmetric
= 0;
5454 bgp_static
->igpnexthop
.s_addr
= 0;
5455 bgp_static
->label_index
= label_index
;
5458 XFREE(MTYPE_ROUTE_MAP_NAME
,
5459 bgp_static
->rmap
.name
);
5460 route_map_counter_decrement(
5461 bgp_static
->rmap
.map
);
5462 bgp_static
->rmap
.name
=
5463 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5464 bgp_static
->rmap
.map
=
5465 route_map_lookup_by_name(rmap
);
5466 route_map_counter_increment(
5467 bgp_static
->rmap
.map
);
5469 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5472 bgp_static
->valid
= 1;
5474 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5476 if (!bgp_static
->backdoor
)
5477 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5483 void bgp_static_add(struct bgp
*bgp
)
5487 struct bgp_node
*rn
;
5488 struct bgp_node
*rm
;
5489 struct bgp_table
*table
;
5490 struct bgp_static
*bgp_static
;
5492 FOREACH_AFI_SAFI (afi
, safi
)
5493 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5494 rn
= bgp_route_next(rn
)) {
5495 if (!bgp_node_has_bgp_path_info_data(rn
))
5498 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5499 || (safi
== SAFI_EVPN
)) {
5500 table
= bgp_node_get_bgp_table_info(rn
);
5502 for (rm
= bgp_table_top(table
); rm
;
5503 rm
= bgp_route_next(rm
)) {
5505 bgp_node_get_bgp_static_info(
5507 bgp_static_update_safi(bgp
, &rm
->p
,
5514 bgp_node_get_bgp_static_info(rn
), afi
,
5520 /* Called from bgp_delete(). Delete all static routes from the BGP
5522 void bgp_static_delete(struct bgp
*bgp
)
5526 struct bgp_node
*rn
;
5527 struct bgp_node
*rm
;
5528 struct bgp_table
*table
;
5529 struct bgp_static
*bgp_static
;
5531 FOREACH_AFI_SAFI (afi
, safi
)
5532 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5533 rn
= bgp_route_next(rn
)) {
5534 if (!bgp_node_has_bgp_path_info_data(rn
))
5537 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5538 || (safi
== SAFI_EVPN
)) {
5539 table
= bgp_node_get_bgp_table_info(rn
);
5541 for (rm
= bgp_table_top(table
); rm
;
5542 rm
= bgp_route_next(rm
)) {
5544 bgp_node_get_bgp_static_info(
5549 bgp_static_withdraw_safi(
5550 bgp
, &rm
->p
, AFI_IP
, safi
,
5551 (struct prefix_rd
*)&rn
->p
);
5552 bgp_static_free(bgp_static
);
5553 bgp_node_set_bgp_static_info(rn
, NULL
);
5554 bgp_unlock_node(rn
);
5557 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5558 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5559 bgp_static_free(bgp_static
);
5560 bgp_node_set_bgp_static_info(rn
, NULL
);
5561 bgp_unlock_node(rn
);
5566 void bgp_static_redo_import_check(struct bgp
*bgp
)
5570 struct bgp_node
*rn
;
5571 struct bgp_node
*rm
;
5572 struct bgp_table
*table
;
5573 struct bgp_static
*bgp_static
;
5575 /* Use this flag to force reprocessing of the route */
5576 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5577 FOREACH_AFI_SAFI (afi
, safi
) {
5578 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5579 rn
= bgp_route_next(rn
)) {
5580 if (!bgp_node_has_bgp_path_info_data(rn
))
5583 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5584 || (safi
== SAFI_EVPN
)) {
5585 table
= bgp_node_get_bgp_table_info(rn
);
5587 for (rm
= bgp_table_top(table
); rm
;
5588 rm
= bgp_route_next(rm
)) {
5590 bgp_node_get_bgp_static_info(
5592 bgp_static_update_safi(bgp
, &rm
->p
,
5597 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5598 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5603 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5606 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5609 struct bgp_table
*table
;
5610 struct bgp_node
*rn
;
5611 struct bgp_path_info
*pi
;
5613 /* Do not install the aggregate route if BGP is in the
5614 * process of termination.
5616 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5617 (bgp
->peer_self
== NULL
))
5620 table
= bgp
->rib
[afi
][safi
];
5621 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5622 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5623 if (pi
->peer
== bgp
->peer_self
5624 && ((pi
->type
== ZEBRA_ROUTE_BGP
5625 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5626 || (pi
->type
!= ZEBRA_ROUTE_BGP
5628 == BGP_ROUTE_REDISTRIBUTE
))) {
5629 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5631 bgp_unlink_nexthop(pi
);
5632 bgp_path_info_delete(rn
, pi
);
5633 bgp_process(bgp
, rn
, afi
, safi
);
5640 * Purge all networks and redistributed routes from routing table.
5641 * Invoked upon the instance going down.
5643 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5648 FOREACH_AFI_SAFI (afi
, safi
)
5649 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5654 * Currently this is used to set static routes for VPN and ENCAP.
5655 * I think it can probably be factored with bgp_static_set.
5657 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5658 const char *ip_str
, const char *rd_str
,
5659 const char *label_str
, const char *rmap_str
,
5660 int evpn_type
, const char *esi
, const char *gwip
,
5661 const char *ethtag
, const char *routermac
)
5663 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5666 struct prefix_rd prd
;
5667 struct bgp_node
*prn
;
5668 struct bgp_node
*rn
;
5669 struct bgp_table
*table
;
5670 struct bgp_static
*bgp_static
;
5671 mpls_label_t label
= MPLS_INVALID_LABEL
;
5672 struct prefix gw_ip
;
5674 /* validate ip prefix */
5675 ret
= str2prefix(ip_str
, &p
);
5677 vty_out(vty
, "%% Malformed prefix\n");
5678 return CMD_WARNING_CONFIG_FAILED
;
5681 if ((afi
== AFI_L2VPN
)
5682 && (bgp_build_evpn_prefix(evpn_type
,
5683 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5684 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5685 return CMD_WARNING_CONFIG_FAILED
;
5688 ret
= str2prefix_rd(rd_str
, &prd
);
5690 vty_out(vty
, "%% Malformed rd\n");
5691 return CMD_WARNING_CONFIG_FAILED
;
5695 unsigned long label_val
;
5696 label_val
= strtoul(label_str
, NULL
, 10);
5697 encode_label(label_val
, &label
);
5700 if (safi
== SAFI_EVPN
) {
5701 if (esi
&& str2esi(esi
, NULL
) == 0) {
5702 vty_out(vty
, "%% Malformed ESI\n");
5703 return CMD_WARNING_CONFIG_FAILED
;
5705 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5706 vty_out(vty
, "%% Malformed Router MAC\n");
5707 return CMD_WARNING_CONFIG_FAILED
;
5710 memset(&gw_ip
, 0, sizeof(struct prefix
));
5711 ret
= str2prefix(gwip
, &gw_ip
);
5713 vty_out(vty
, "%% Malformed GatewayIp\n");
5714 return CMD_WARNING_CONFIG_FAILED
;
5716 if ((gw_ip
.family
== AF_INET
5717 && is_evpn_prefix_ipaddr_v6(
5718 (struct prefix_evpn
*)&p
))
5719 || (gw_ip
.family
== AF_INET6
5720 && is_evpn_prefix_ipaddr_v4(
5721 (struct prefix_evpn
*)&p
))) {
5723 "%% GatewayIp family differs with IP prefix\n");
5724 return CMD_WARNING_CONFIG_FAILED
;
5728 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5729 if (!bgp_node_has_bgp_path_info_data(prn
))
5730 bgp_node_set_bgp_table_info(prn
,
5731 bgp_table_init(bgp
, afi
, safi
));
5732 table
= bgp_node_get_bgp_table_info(prn
);
5734 rn
= bgp_node_get(table
, &p
);
5736 if (bgp_node_has_bgp_path_info_data(rn
)) {
5737 vty_out(vty
, "%% Same network configuration exists\n");
5738 bgp_unlock_node(rn
);
5740 /* New configuration. */
5741 bgp_static
= bgp_static_new();
5742 bgp_static
->backdoor
= 0;
5743 bgp_static
->valid
= 0;
5744 bgp_static
->igpmetric
= 0;
5745 bgp_static
->igpnexthop
.s_addr
= 0;
5746 bgp_static
->label
= label
;
5747 bgp_static
->prd
= prd
;
5750 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5751 route_map_counter_decrement(bgp_static
->rmap
.map
);
5752 bgp_static
->rmap
.name
=
5753 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5754 bgp_static
->rmap
.map
=
5755 route_map_lookup_by_name(rmap_str
);
5756 route_map_counter_increment(bgp_static
->rmap
.map
);
5759 if (safi
== SAFI_EVPN
) {
5761 bgp_static
->eth_s_id
=
5763 sizeof(struct eth_segment_id
));
5764 str2esi(esi
, bgp_static
->eth_s_id
);
5767 bgp_static
->router_mac
=
5768 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5769 (void)prefix_str2mac(routermac
,
5770 bgp_static
->router_mac
);
5773 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5775 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5777 bgp_static
->valid
= 1;
5778 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5784 /* Configure static BGP network. */
5785 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5786 const char *ip_str
, const char *rd_str
,
5787 const char *label_str
, int evpn_type
, const char *esi
,
5788 const char *gwip
, const char *ethtag
)
5790 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5793 struct prefix_rd prd
;
5794 struct bgp_node
*prn
;
5795 struct bgp_node
*rn
;
5796 struct bgp_table
*table
;
5797 struct bgp_static
*bgp_static
;
5798 mpls_label_t label
= MPLS_INVALID_LABEL
;
5800 /* Convert IP prefix string to struct prefix. */
5801 ret
= str2prefix(ip_str
, &p
);
5803 vty_out(vty
, "%% Malformed prefix\n");
5804 return CMD_WARNING_CONFIG_FAILED
;
5807 if ((afi
== AFI_L2VPN
)
5808 && (bgp_build_evpn_prefix(evpn_type
,
5809 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5810 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5811 return CMD_WARNING_CONFIG_FAILED
;
5813 ret
= str2prefix_rd(rd_str
, &prd
);
5815 vty_out(vty
, "%% Malformed rd\n");
5816 return CMD_WARNING_CONFIG_FAILED
;
5820 unsigned long label_val
;
5821 label_val
= strtoul(label_str
, NULL
, 10);
5822 encode_label(label_val
, &label
);
5825 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5826 if (!bgp_node_has_bgp_path_info_data(prn
))
5827 bgp_node_set_bgp_table_info(prn
,
5828 bgp_table_init(bgp
, afi
, safi
));
5830 bgp_unlock_node(prn
);
5831 table
= bgp_node_get_bgp_table_info(prn
);
5833 rn
= bgp_node_lookup(table
, &p
);
5836 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5838 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5839 bgp_static_free(bgp_static
);
5840 bgp_node_set_bgp_static_info(rn
, NULL
);
5841 bgp_unlock_node(rn
);
5842 bgp_unlock_node(rn
);
5844 vty_out(vty
, "%% Can't find the route\n");
5849 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5850 const char *rmap_name
)
5852 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5853 struct bgp_rmap
*rmap
;
5855 rmap
= &bgp
->table_map
[afi
][safi
];
5857 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5858 route_map_counter_decrement(rmap
->map
);
5859 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5860 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5861 route_map_counter_increment(rmap
->map
);
5863 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5864 route_map_counter_decrement(rmap
->map
);
5869 if (bgp_fibupd_safi(safi
))
5870 bgp_zebra_announce_table(bgp
, afi
, safi
);
5875 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5876 const char *rmap_name
)
5878 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5879 struct bgp_rmap
*rmap
;
5881 rmap
= &bgp
->table_map
[afi
][safi
];
5882 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5883 route_map_counter_decrement(rmap
->map
);
5887 if (bgp_fibupd_safi(safi
))
5888 bgp_zebra_announce_table(bgp
, afi
, safi
);
5893 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5896 if (bgp
->table_map
[afi
][safi
].name
) {
5897 vty_out(vty
, " table-map %s\n",
5898 bgp
->table_map
[afi
][safi
].name
);
5902 DEFUN (bgp_table_map
,
5905 "BGP table to RIB route download filter\n"
5906 "Name of the route map\n")
5909 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5910 argv
[idx_word
]->arg
);
5912 DEFUN (no_bgp_table_map
,
5913 no_bgp_table_map_cmd
,
5914 "no table-map WORD",
5916 "BGP table to RIB route download filter\n"
5917 "Name of the route map\n")
5920 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5921 argv
[idx_word
]->arg
);
5927 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5928 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5929 backdoor$backdoor}]",
5931 "Specify a network to announce via BGP\n"
5936 "Route-map to modify the attributes\n"
5937 "Name of the route map\n"
5938 "Label index to associate with the prefix\n"
5939 "Label index value\n"
5940 "Specify a BGP backdoor route\n")
5942 char addr_prefix_str
[BUFSIZ
];
5947 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5950 vty_out(vty
, "%% Inconsistent address and mask\n");
5951 return CMD_WARNING_CONFIG_FAILED
;
5955 return bgp_static_set(
5956 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5957 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5958 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5961 DEFPY(ipv6_bgp_network
,
5962 ipv6_bgp_network_cmd
,
5963 "[no] network X:X::X:X/M$prefix \
5964 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5966 "Specify a network to announce via BGP\n"
5968 "Route-map to modify the attributes\n"
5969 "Name of the route map\n"
5970 "Label index to associate with the prefix\n"
5971 "Label index value\n")
5973 return bgp_static_set(
5974 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5975 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5978 static struct bgp_aggregate
*bgp_aggregate_new(void)
5980 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5983 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5985 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5986 route_map_counter_decrement(aggregate
->rmap
.map
);
5987 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5990 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5991 struct aspath
*aspath
,
5992 struct community
*comm
,
5993 struct ecommunity
*ecomm
,
5994 struct lcommunity
*lcomm
)
5996 static struct aspath
*ae
= NULL
;
5999 ae
= aspath_empty();
6004 if (origin
!= pi
->attr
->origin
)
6007 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6010 if (!community_cmp(pi
->attr
->community
, comm
))
6013 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6016 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6019 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6025 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
6026 struct prefix
*p
, uint8_t origin
,
6027 struct aspath
*aspath
,
6028 struct community
*community
,
6029 struct ecommunity
*ecommunity
,
6030 struct lcommunity
*lcommunity
,
6031 uint8_t atomic_aggregate
,
6032 struct bgp_aggregate
*aggregate
)
6034 struct bgp_node
*rn
;
6035 struct bgp_table
*table
;
6036 struct bgp_path_info
*pi
, *orig
, *new;
6039 table
= bgp
->rib
[afi
][safi
];
6041 rn
= bgp_node_get(table
, p
);
6043 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6044 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6045 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6048 if (aggregate
->count
> 0) {
6050 * If the aggregate information has not changed
6051 * no need to re-install it again.
6053 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6054 ecommunity
, lcommunity
)) {
6055 bgp_unlock_node(rn
);
6058 aspath_free(aspath
);
6060 community_free(&community
);
6062 ecommunity_free(&ecommunity
);
6064 lcommunity_free(&lcommunity
);
6070 * Mark the old as unusable
6073 bgp_path_info_delete(rn
, pi
);
6075 attr
= bgp_attr_aggregate_intern(
6076 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6077 aggregate
, atomic_aggregate
, p
);
6080 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6084 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6085 bgp
->peer_self
, attr
, rn
);
6087 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6089 bgp_path_info_add(rn
, new);
6090 bgp_process(bgp
, rn
, afi
, safi
);
6092 for (pi
= orig
; pi
; pi
= pi
->next
)
6093 if (pi
->peer
== bgp
->peer_self
6094 && pi
->type
== ZEBRA_ROUTE_BGP
6095 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6098 /* Withdraw static BGP route from routing table. */
6100 bgp_path_info_delete(rn
, pi
);
6101 bgp_process(bgp
, rn
, afi
, safi
);
6105 bgp_unlock_node(rn
);
6108 /* Update an aggregate as routes are added/removed from the BGP table */
6109 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
6110 afi_t afi
, safi_t safi
,
6111 struct bgp_aggregate
*aggregate
)
6113 struct bgp_table
*table
;
6114 struct bgp_node
*top
;
6115 struct bgp_node
*rn
;
6117 struct aspath
*aspath
= NULL
;
6118 struct community
*community
= NULL
;
6119 struct ecommunity
*ecommunity
= NULL
;
6120 struct lcommunity
*lcommunity
= NULL
;
6121 struct bgp_path_info
*pi
;
6122 unsigned long match
= 0;
6123 uint8_t atomic_aggregate
= 0;
6125 /* If the bgp instance is being deleted or self peer is deleted
6126 * then do not create aggregate route
6128 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
6129 (bgp
->peer_self
== NULL
))
6132 /* ORIGIN attribute: If at least one route among routes that are
6133 aggregated has ORIGIN with the value INCOMPLETE, then the
6134 aggregated route must have the ORIGIN attribute with the value
6135 INCOMPLETE. Otherwise, if at least one route among routes that
6136 are aggregated has ORIGIN with the value EGP, then the aggregated
6137 route must have the origin attribute with the value EGP. In all
6138 other case the value of the ORIGIN attribute of the aggregated
6139 route is INTERNAL. */
6140 origin
= BGP_ORIGIN_IGP
;
6142 table
= bgp
->rib
[afi
][safi
];
6144 top
= bgp_node_get(table
, p
);
6145 for (rn
= bgp_node_get(table
, p
); rn
;
6146 rn
= bgp_route_next_until(rn
, top
)) {
6147 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6152 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6153 if (BGP_PATH_HOLDDOWN(pi
))
6157 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6158 atomic_aggregate
= 1;
6160 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6164 * summary-only aggregate route suppress
6165 * aggregated route announcements.
6167 if (aggregate
->summary_only
) {
6168 (bgp_path_info_extra_get(pi
))->suppress
++;
6169 bgp_path_info_set_flag(rn
, pi
,
6170 BGP_PATH_ATTR_CHANGED
);
6177 * If at least one route among routes that are
6178 * aggregated has ORIGIN with the value INCOMPLETE,
6179 * then the aggregated route MUST have the ORIGIN
6180 * attribute with the value INCOMPLETE. Otherwise, if
6181 * at least one route among routes that are aggregated
6182 * has ORIGIN with the value EGP, then the aggregated
6183 * route MUST have the ORIGIN attribute with the value
6186 switch (pi
->attr
->origin
) {
6187 case BGP_ORIGIN_INCOMPLETE
:
6188 aggregate
->incomplete_origin_count
++;
6190 case BGP_ORIGIN_EGP
:
6191 aggregate
->egp_origin_count
++;
6199 if (!aggregate
->as_set
)
6203 * as-set aggregate route generate origin, as path,
6204 * and community aggregation.
6206 /* Compute aggregate route's as-path.
6208 bgp_compute_aggregate_aspath_hash(aggregate
,
6211 /* Compute aggregate route's community.
6213 if (pi
->attr
->community
)
6214 bgp_compute_aggregate_community_hash(
6216 pi
->attr
->community
);
6218 /* Compute aggregate route's extended community.
6220 if (pi
->attr
->ecommunity
)
6221 bgp_compute_aggregate_ecommunity_hash(
6223 pi
->attr
->ecommunity
);
6225 /* Compute aggregate route's large community.
6227 if (pi
->attr
->lcommunity
)
6228 bgp_compute_aggregate_lcommunity_hash(
6230 pi
->attr
->lcommunity
);
6233 bgp_process(bgp
, rn
, afi
, safi
);
6235 if (aggregate
->as_set
) {
6236 bgp_compute_aggregate_aspath_val(aggregate
);
6237 bgp_compute_aggregate_community_val(aggregate
);
6238 bgp_compute_aggregate_ecommunity_val(aggregate
);
6239 bgp_compute_aggregate_lcommunity_val(aggregate
);
6243 bgp_unlock_node(top
);
6246 if (aggregate
->incomplete_origin_count
> 0)
6247 origin
= BGP_ORIGIN_INCOMPLETE
;
6248 else if (aggregate
->egp_origin_count
> 0)
6249 origin
= BGP_ORIGIN_EGP
;
6251 if (aggregate
->as_set
) {
6252 if (aggregate
->aspath
)
6253 /* Retrieve aggregate route's as-path.
6255 aspath
= aspath_dup(aggregate
->aspath
);
6257 if (aggregate
->community
)
6258 /* Retrieve aggregate route's community.
6260 community
= community_dup(aggregate
->community
);
6262 if (aggregate
->ecommunity
)
6263 /* Retrieve aggregate route's ecommunity.
6265 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6267 if (aggregate
->lcommunity
)
6268 /* Retrieve aggregate route's lcommunity.
6270 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6273 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6274 ecommunity
, lcommunity
, atomic_aggregate
,
6278 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6279 safi_t safi
, struct bgp_aggregate
*aggregate
)
6281 struct bgp_table
*table
;
6282 struct bgp_node
*top
;
6283 struct bgp_node
*rn
;
6284 struct bgp_path_info
*pi
;
6285 unsigned long match
;
6287 table
= bgp
->rib
[afi
][safi
];
6289 /* If routes exists below this node, generate aggregate routes. */
6290 top
= bgp_node_get(table
, p
);
6291 for (rn
= bgp_node_get(table
, p
); rn
;
6292 rn
= bgp_route_next_until(rn
, top
)) {
6293 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6297 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6298 if (BGP_PATH_HOLDDOWN(pi
))
6301 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6304 if (aggregate
->summary_only
&& pi
->extra
) {
6305 pi
->extra
->suppress
--;
6307 if (pi
->extra
->suppress
== 0) {
6308 bgp_path_info_set_flag(
6309 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6315 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6316 aggregate
->incomplete_origin_count
--;
6317 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6318 aggregate
->egp_origin_count
--;
6320 if (aggregate
->as_set
) {
6321 /* Remove as-path from aggregate.
6323 bgp_remove_aspath_from_aggregate_hash(
6327 if (pi
->attr
->community
)
6328 /* Remove community from aggregate.
6330 bgp_remove_comm_from_aggregate_hash(
6332 pi
->attr
->community
);
6334 if (pi
->attr
->ecommunity
)
6335 /* Remove ecommunity from aggregate.
6337 bgp_remove_ecomm_from_aggregate_hash(
6339 pi
->attr
->ecommunity
);
6341 if (pi
->attr
->lcommunity
)
6342 /* Remove lcommunity from aggregate.
6344 bgp_remove_lcomm_from_aggregate_hash(
6346 pi
->attr
->lcommunity
);
6351 /* If this node was suppressed, process the change. */
6353 bgp_process(bgp
, rn
, afi
, safi
);
6355 if (aggregate
->as_set
) {
6356 aspath_free(aggregate
->aspath
);
6357 aggregate
->aspath
= NULL
;
6358 if (aggregate
->community
)
6359 community_free(&aggregate
->community
);
6360 if (aggregate
->ecommunity
)
6361 ecommunity_free(&aggregate
->ecommunity
);
6362 if (aggregate
->lcommunity
)
6363 lcommunity_free(&aggregate
->lcommunity
);
6366 bgp_unlock_node(top
);
6369 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6370 struct bgp_path_info
*pinew
, afi_t afi
,
6372 struct bgp_aggregate
*aggregate
)
6375 struct aspath
*aspath
= NULL
;
6376 uint8_t atomic_aggregate
= 0;
6377 struct community
*community
= NULL
;
6378 struct ecommunity
*ecommunity
= NULL
;
6379 struct lcommunity
*lcommunity
= NULL
;
6381 /* ORIGIN attribute: If at least one route among routes that are
6382 * aggregated has ORIGIN with the value INCOMPLETE, then the
6383 * aggregated route must have the ORIGIN attribute with the value
6384 * INCOMPLETE. Otherwise, if at least one route among routes that
6385 * are aggregated has ORIGIN with the value EGP, then the aggregated
6386 * route must have the origin attribute with the value EGP. In all
6387 * other case the value of the ORIGIN attribute of the aggregated
6388 * route is INTERNAL.
6390 origin
= BGP_ORIGIN_IGP
;
6394 if (aggregate
->summary_only
)
6395 (bgp_path_info_extra_get(pinew
))->suppress
++;
6397 switch (pinew
->attr
->origin
) {
6398 case BGP_ORIGIN_INCOMPLETE
:
6399 aggregate
->incomplete_origin_count
++;
6401 case BGP_ORIGIN_EGP
:
6402 aggregate
->egp_origin_count
++;
6410 if (aggregate
->incomplete_origin_count
> 0)
6411 origin
= BGP_ORIGIN_INCOMPLETE
;
6412 else if (aggregate
->egp_origin_count
> 0)
6413 origin
= BGP_ORIGIN_EGP
;
6415 if (aggregate
->as_set
) {
6416 /* Compute aggregate route's as-path.
6418 bgp_compute_aggregate_aspath(aggregate
,
6419 pinew
->attr
->aspath
);
6421 /* Compute aggregate route's community.
6423 if (pinew
->attr
->community
)
6424 bgp_compute_aggregate_community(
6426 pinew
->attr
->community
);
6428 /* Compute aggregate route's extended community.
6430 if (pinew
->attr
->ecommunity
)
6431 bgp_compute_aggregate_ecommunity(
6433 pinew
->attr
->ecommunity
);
6435 /* Compute aggregate route's large community.
6437 if (pinew
->attr
->lcommunity
)
6438 bgp_compute_aggregate_lcommunity(
6440 pinew
->attr
->lcommunity
);
6442 /* Retrieve aggregate route's as-path.
6444 if (aggregate
->aspath
)
6445 aspath
= aspath_dup(aggregate
->aspath
);
6447 /* Retrieve aggregate route's community.
6449 if (aggregate
->community
)
6450 community
= community_dup(aggregate
->community
);
6452 /* Retrieve aggregate route's ecommunity.
6454 if (aggregate
->ecommunity
)
6455 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6457 /* Retrieve aggregate route's lcommunity.
6459 if (aggregate
->lcommunity
)
6460 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6463 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6464 aspath
, community
, ecommunity
,
6465 lcommunity
, atomic_aggregate
, aggregate
);
6468 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6470 struct bgp_path_info
*pi
,
6471 struct bgp_aggregate
*aggregate
,
6472 struct prefix
*aggr_p
)
6475 struct aspath
*aspath
= NULL
;
6476 uint8_t atomic_aggregate
= 0;
6477 struct community
*community
= NULL
;
6478 struct ecommunity
*ecommunity
= NULL
;
6479 struct lcommunity
*lcommunity
= NULL
;
6480 unsigned long match
= 0;
6482 if (BGP_PATH_HOLDDOWN(pi
))
6485 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6488 if (aggregate
->summary_only
6490 && pi
->extra
->suppress
> 0) {
6491 pi
->extra
->suppress
--;
6493 if (pi
->extra
->suppress
== 0) {
6494 bgp_path_info_set_flag(pi
->net
, pi
,
6495 BGP_PATH_ATTR_CHANGED
);
6500 if (aggregate
->count
> 0)
6503 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6504 aggregate
->incomplete_origin_count
--;
6505 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6506 aggregate
->egp_origin_count
--;
6508 if (aggregate
->as_set
) {
6509 /* Remove as-path from aggregate.
6511 bgp_remove_aspath_from_aggregate(aggregate
,
6514 if (pi
->attr
->community
)
6515 /* Remove community from aggregate.
6517 bgp_remove_community_from_aggregate(
6519 pi
->attr
->community
);
6521 if (pi
->attr
->ecommunity
)
6522 /* Remove ecommunity from aggregate.
6524 bgp_remove_ecommunity_from_aggregate(
6526 pi
->attr
->ecommunity
);
6528 if (pi
->attr
->lcommunity
)
6529 /* Remove lcommunity from aggregate.
6531 bgp_remove_lcommunity_from_aggregate(
6533 pi
->attr
->lcommunity
);
6536 /* If this node was suppressed, process the change. */
6538 bgp_process(bgp
, pi
->net
, afi
, safi
);
6540 origin
= BGP_ORIGIN_IGP
;
6541 if (aggregate
->incomplete_origin_count
> 0)
6542 origin
= BGP_ORIGIN_INCOMPLETE
;
6543 else if (aggregate
->egp_origin_count
> 0)
6544 origin
= BGP_ORIGIN_EGP
;
6546 if (aggregate
->as_set
) {
6547 /* Retrieve aggregate route's as-path.
6549 if (aggregate
->aspath
)
6550 aspath
= aspath_dup(aggregate
->aspath
);
6552 /* Retrieve aggregate route's community.
6554 if (aggregate
->community
)
6555 community
= community_dup(aggregate
->community
);
6557 /* Retrieve aggregate route's ecommunity.
6559 if (aggregate
->ecommunity
)
6560 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6562 /* Retrieve aggregate route's lcommunity.
6564 if (aggregate
->lcommunity
)
6565 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6568 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6569 aspath
, community
, ecommunity
,
6570 lcommunity
, atomic_aggregate
, aggregate
);
6573 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6574 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6576 struct bgp_node
*child
;
6577 struct bgp_node
*rn
;
6578 struct bgp_aggregate
*aggregate
;
6579 struct bgp_table
*table
;
6581 table
= bgp
->aggregate
[afi
][safi
];
6583 /* No aggregates configured. */
6584 if (bgp_table_top_nolock(table
) == NULL
)
6587 if (p
->prefixlen
== 0)
6590 if (BGP_PATH_HOLDDOWN(pi
))
6593 child
= bgp_node_get(table
, p
);
6595 /* Aggregate address configuration check. */
6596 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6597 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6598 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6599 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6603 bgp_unlock_node(child
);
6606 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6607 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6609 struct bgp_node
*child
;
6610 struct bgp_node
*rn
;
6611 struct bgp_aggregate
*aggregate
;
6612 struct bgp_table
*table
;
6614 table
= bgp
->aggregate
[afi
][safi
];
6616 /* No aggregates configured. */
6617 if (bgp_table_top_nolock(table
) == NULL
)
6620 if (p
->prefixlen
== 0)
6623 child
= bgp_node_get(table
, p
);
6625 /* Aggregate address configuration check. */
6626 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6627 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6628 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6629 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6630 del
, aggregate
, &rn
->p
);
6633 bgp_unlock_node(child
);
6636 /* Aggregate route attribute. */
6637 #define AGGREGATE_SUMMARY_ONLY 1
6638 #define AGGREGATE_AS_SET 1
6639 #define AGGREGATE_AS_UNSET 0
6641 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6642 afi_t afi
, safi_t safi
)
6644 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6647 struct bgp_node
*rn
;
6648 struct bgp_aggregate
*aggregate
;
6650 /* Convert string to prefix structure. */
6651 ret
= str2prefix(prefix_str
, &p
);
6653 vty_out(vty
, "Malformed prefix\n");
6654 return CMD_WARNING_CONFIG_FAILED
;
6658 /* Old configuration check. */
6659 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6662 "%% There is no aggregate-address configuration.\n");
6663 return CMD_WARNING_CONFIG_FAILED
;
6666 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6667 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6668 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6669 NULL
, NULL
, 0, aggregate
);
6671 /* Unlock aggregate address configuration. */
6672 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6674 if (aggregate
->community
)
6675 community_free(&aggregate
->community
);
6677 if (aggregate
->community_hash
) {
6678 /* Delete all communities in the hash.
6680 hash_clean(aggregate
->community_hash
,
6681 bgp_aggr_community_remove
);
6682 /* Free up the community_hash.
6684 hash_free(aggregate
->community_hash
);
6687 if (aggregate
->ecommunity
)
6688 ecommunity_free(&aggregate
->ecommunity
);
6690 if (aggregate
->ecommunity_hash
) {
6691 /* Delete all ecommunities in the hash.
6693 hash_clean(aggregate
->ecommunity_hash
,
6694 bgp_aggr_ecommunity_remove
);
6695 /* Free up the ecommunity_hash.
6697 hash_free(aggregate
->ecommunity_hash
);
6700 if (aggregate
->lcommunity
)
6701 lcommunity_free(&aggregate
->lcommunity
);
6703 if (aggregate
->lcommunity_hash
) {
6704 /* Delete all lcommunities in the hash.
6706 hash_clean(aggregate
->lcommunity_hash
,
6707 bgp_aggr_lcommunity_remove
);
6708 /* Free up the lcommunity_hash.
6710 hash_free(aggregate
->lcommunity_hash
);
6713 if (aggregate
->aspath
)
6714 aspath_free(aggregate
->aspath
);
6716 if (aggregate
->aspath_hash
) {
6717 /* Delete all as-paths in the hash.
6719 hash_clean(aggregate
->aspath_hash
,
6720 bgp_aggr_aspath_remove
);
6721 /* Free up the aspath_hash.
6723 hash_free(aggregate
->aspath_hash
);
6726 bgp_aggregate_free(aggregate
);
6727 bgp_unlock_node(rn
);
6728 bgp_unlock_node(rn
);
6733 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6734 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6737 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6740 struct bgp_node
*rn
;
6741 struct bgp_aggregate
*aggregate
;
6742 uint8_t as_set_new
= as_set
;
6744 /* Convert string to prefix structure. */
6745 ret
= str2prefix(prefix_str
, &p
);
6747 vty_out(vty
, "Malformed prefix\n");
6748 return CMD_WARNING_CONFIG_FAILED
;
6752 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6753 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6754 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6756 return CMD_WARNING_CONFIG_FAILED
;
6759 /* Old configuration check. */
6760 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6761 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6764 vty_out(vty
, "There is already same aggregate network.\n");
6765 /* try to remove the old entry */
6766 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6768 vty_out(vty
, "Error deleting aggregate.\n");
6769 bgp_unlock_node(rn
);
6770 return CMD_WARNING_CONFIG_FAILED
;
6774 /* Make aggregate address structure. */
6775 aggregate
= bgp_aggregate_new();
6776 aggregate
->summary_only
= summary_only
;
6778 /* Network operators MUST NOT locally generate any new
6779 * announcements containing AS_SET or AS_CONFED_SET. If they have
6780 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6781 * SHOULD withdraw those routes and re-announce routes for the
6782 * aggregate or component prefixes (i.e., the more-specific routes
6783 * subsumed by the previously aggregated route) without AS_SET
6784 * or AS_CONFED_SET in the updates.
6786 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6787 if (as_set
== AGGREGATE_AS_SET
) {
6788 as_set_new
= AGGREGATE_AS_UNSET
;
6790 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6793 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6797 aggregate
->as_set
= as_set_new
;
6798 aggregate
->safi
= safi
;
6801 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6802 route_map_counter_decrement(aggregate
->rmap
.map
);
6803 aggregate
->rmap
.name
=
6804 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6805 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6806 route_map_counter_increment(aggregate
->rmap
.map
);
6808 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6810 /* Aggregate address insert into BGP routing table. */
6811 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6816 DEFUN (aggregate_address
,
6817 aggregate_address_cmd
,
6818 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6819 "Configure BGP aggregate entries\n"
6820 "Aggregate prefix\n"
6821 "Generate AS set path information\n"
6822 "Filter more specific routes from updates\n"
6823 "Filter more specific routes from updates\n"
6824 "Generate AS set path information\n"
6825 "Apply route map to aggregate network\n"
6826 "Name of route map\n")
6829 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6830 char *prefix
= argv
[idx
]->arg
;
6832 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6833 : AGGREGATE_AS_UNSET
;
6835 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6836 ? AGGREGATE_SUMMARY_ONLY
6840 argv_find(argv
, argc
, "WORD", &idx
);
6842 rmap
= argv
[idx
]->arg
;
6844 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6845 rmap
, summary_only
, as_set
);
6848 DEFUN (aggregate_address_mask
,
6849 aggregate_address_mask_cmd
,
6850 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6851 "Configure BGP aggregate entries\n"
6852 "Aggregate address\n"
6854 "Generate AS set path information\n"
6855 "Filter more specific routes from updates\n"
6856 "Filter more specific routes from updates\n"
6857 "Generate AS set path information\n"
6858 "Apply route map to aggregate network\n"
6859 "Name of route map\n")
6862 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6863 char *prefix
= argv
[idx
]->arg
;
6864 char *mask
= argv
[idx
+ 1]->arg
;
6867 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6868 : AGGREGATE_AS_UNSET
;
6870 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6871 ? AGGREGATE_SUMMARY_ONLY
6874 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6876 rmap
= argv
[idx
]->arg
;
6878 char prefix_str
[BUFSIZ
];
6879 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6882 vty_out(vty
, "%% Inconsistent address and mask\n");
6883 return CMD_WARNING_CONFIG_FAILED
;
6886 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6887 rmap
, summary_only
, as_set
);
6890 DEFUN (no_aggregate_address
,
6891 no_aggregate_address_cmd
,
6892 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6894 "Configure BGP aggregate entries\n"
6895 "Aggregate prefix\n"
6896 "Generate AS set path information\n"
6897 "Filter more specific routes from updates\n"
6898 "Filter more specific routes from updates\n"
6899 "Generate AS set path information\n"
6900 "Apply route map to aggregate network\n"
6901 "Name of route map\n")
6904 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6905 char *prefix
= argv
[idx
]->arg
;
6906 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6909 DEFUN (no_aggregate_address_mask
,
6910 no_aggregate_address_mask_cmd
,
6911 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6913 "Configure BGP aggregate entries\n"
6914 "Aggregate address\n"
6916 "Generate AS set path information\n"
6917 "Filter more specific routes from updates\n"
6918 "Filter more specific routes from updates\n"
6919 "Generate AS set path information\n"
6920 "Apply route map to aggregate network\n"
6921 "Name of route map\n")
6924 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6925 char *prefix
= argv
[idx
]->arg
;
6926 char *mask
= argv
[idx
+ 1]->arg
;
6928 char prefix_str
[BUFSIZ
];
6929 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6932 vty_out(vty
, "%% Inconsistent address and mask\n");
6933 return CMD_WARNING_CONFIG_FAILED
;
6936 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6939 DEFUN (ipv6_aggregate_address
,
6940 ipv6_aggregate_address_cmd
,
6941 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6942 "Configure BGP aggregate entries\n"
6943 "Aggregate prefix\n"
6944 "Generate AS set path information\n"
6945 "Filter more specific routes from updates\n"
6946 "Filter more specific routes from updates\n"
6947 "Generate AS set path information\n"
6948 "Apply route map to aggregate network\n"
6949 "Name of route map\n")
6952 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6953 char *prefix
= argv
[idx
]->arg
;
6956 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6957 : AGGREGATE_AS_UNSET
;
6960 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6961 ? AGGREGATE_SUMMARY_ONLY
6964 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6966 rmap
= argv
[idx
]->arg
;
6968 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6972 DEFUN (no_ipv6_aggregate_address
,
6973 no_ipv6_aggregate_address_cmd
,
6974 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6976 "Configure BGP aggregate entries\n"
6977 "Aggregate prefix\n"
6978 "Generate AS set path information\n"
6979 "Filter more specific routes from updates\n"
6980 "Filter more specific routes from updates\n"
6981 "Generate AS set path information\n"
6982 "Apply route map to aggregate network\n"
6983 "Name of route map\n")
6986 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6987 char *prefix
= argv
[idx
]->arg
;
6988 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6991 /* Redistribute route treatment. */
6992 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6993 const union g_addr
*nexthop
, ifindex_t ifindex
,
6994 enum nexthop_types_t nhtype
, uint32_t metric
,
6995 uint8_t type
, unsigned short instance
,
6998 struct bgp_path_info
*new;
6999 struct bgp_path_info
*bpi
;
7000 struct bgp_path_info rmap_path
;
7001 struct bgp_node
*bn
;
7003 struct attr
*new_attr
;
7005 route_map_result_t ret
;
7006 struct bgp_redist
*red
;
7008 /* Make default attribute. */
7009 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7011 * This must not be NULL to satisfy Coverity SA
7013 assert(attr
.aspath
);
7016 case NEXTHOP_TYPE_IFINDEX
:
7018 case NEXTHOP_TYPE_IPV4
:
7019 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7020 attr
.nexthop
= nexthop
->ipv4
;
7022 case NEXTHOP_TYPE_IPV6
:
7023 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7024 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7025 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7027 case NEXTHOP_TYPE_BLACKHOLE
:
7028 switch (p
->family
) {
7030 attr
.nexthop
.s_addr
= INADDR_ANY
;
7033 memset(&attr
.mp_nexthop_global
, 0,
7034 sizeof(attr
.mp_nexthop_global
));
7035 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7040 attr
.nh_ifindex
= ifindex
;
7043 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7046 afi
= family2afi(p
->family
);
7048 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7050 struct attr attr_new
;
7052 /* Copy attribute for modification. */
7055 if (red
->redist_metric_flag
)
7056 attr_new
.med
= red
->redist_metric
;
7058 /* Apply route-map. */
7059 if (red
->rmap
.name
) {
7060 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7061 rmap_path
.peer
= bgp
->peer_self
;
7062 rmap_path
.attr
= &attr_new
;
7064 SET_FLAG(bgp
->peer_self
->rmap_type
,
7065 PEER_RMAP_TYPE_REDISTRIBUTE
);
7067 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7070 bgp
->peer_self
->rmap_type
= 0;
7072 if (ret
== RMAP_DENYMATCH
) {
7073 /* Free uninterned attribute. */
7074 bgp_attr_flush(&attr_new
);
7076 /* Unintern original. */
7077 aspath_unintern(&attr
.aspath
);
7078 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7083 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7084 bgp_attr_add_gshut_community(&attr_new
);
7086 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7087 SAFI_UNICAST
, p
, NULL
);
7089 new_attr
= bgp_attr_intern(&attr_new
);
7091 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
7093 if (bpi
->peer
== bgp
->peer_self
7094 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7098 /* Ensure the (source route) type is updated. */
7100 if (attrhash_cmp(bpi
->attr
, new_attr
)
7101 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7102 bgp_attr_unintern(&new_attr
);
7103 aspath_unintern(&attr
.aspath
);
7104 bgp_unlock_node(bn
);
7107 /* The attribute is changed. */
7108 bgp_path_info_set_flag(bn
, bpi
,
7109 BGP_PATH_ATTR_CHANGED
);
7111 /* Rewrite BGP route information. */
7112 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7113 bgp_path_info_restore(bn
, bpi
);
7115 bgp_aggregate_decrement(
7116 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7117 bgp_attr_unintern(&bpi
->attr
);
7118 bpi
->attr
= new_attr
;
7119 bpi
->uptime
= bgp_clock();
7121 /* Process change. */
7122 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7124 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7125 bgp_unlock_node(bn
);
7126 aspath_unintern(&attr
.aspath
);
7128 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7130 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7132 vpn_leak_from_vrf_update(
7133 bgp_get_default(), bgp
, bpi
);
7139 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7140 bgp
->peer_self
, new_attr
, bn
);
7141 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7143 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7144 bgp_path_info_add(bn
, new);
7145 bgp_unlock_node(bn
);
7146 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7148 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7149 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7151 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7155 /* Unintern original. */
7156 aspath_unintern(&attr
.aspath
);
7159 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7160 unsigned short instance
)
7163 struct bgp_node
*rn
;
7164 struct bgp_path_info
*pi
;
7165 struct bgp_redist
*red
;
7167 afi
= family2afi(p
->family
);
7169 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7171 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7172 SAFI_UNICAST
, p
, NULL
);
7174 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7175 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7179 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7180 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7182 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7185 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7186 bgp_path_info_delete(rn
, pi
);
7187 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7189 bgp_unlock_node(rn
);
7193 /* Withdraw specified route type's route. */
7194 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7195 unsigned short instance
)
7197 struct bgp_node
*rn
;
7198 struct bgp_path_info
*pi
;
7199 struct bgp_table
*table
;
7201 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7203 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7204 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7205 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7206 && pi
->instance
== instance
)
7210 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7211 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7213 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7216 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7218 bgp_path_info_delete(rn
, pi
);
7219 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7224 /* Static function to display route. */
7225 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7232 if (p
->family
== AF_INET
) {
7236 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7239 json_object_string_add(json
, "prefix",
7240 inet_ntop(p
->family
,
7243 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7244 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7245 json_object_string_add(json
, "network", buf2
);
7247 } else if (p
->family
== AF_ETHERNET
) {
7248 prefix2str(p
, buf
, PREFIX_STRLEN
);
7249 len
= vty_out(vty
, "%s", buf
);
7250 } else if (p
->family
== AF_EVPN
) {
7254 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7257 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7258 } else if (p
->family
== AF_FLOWSPEC
) {
7259 route_vty_out_flowspec(vty
, p
, NULL
,
7261 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7262 NLRI_STRING_FORMAT_MIN
, json
);
7267 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7270 json_object_string_add(json
, "prefix",
7271 inet_ntop(p
->family
,
7274 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7275 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7276 json_object_string_add(json
, "network", buf2
);
7283 vty_out(vty
, "\n%*s", 20, " ");
7285 vty_out(vty
, "%*s", len
, " ");
7289 enum bgp_display_type
{
7293 /* Print the short form route status for a bgp_path_info */
7294 static void route_vty_short_status_out(struct vty
*vty
,
7295 struct bgp_path_info
*path
,
7296 json_object
*json_path
)
7300 /* Route status display. */
7301 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7302 json_object_boolean_true_add(json_path
, "removed");
7304 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7305 json_object_boolean_true_add(json_path
, "stale");
7307 if (path
->extra
&& path
->extra
->suppress
)
7308 json_object_boolean_true_add(json_path
, "suppressed");
7310 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7311 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7312 json_object_boolean_true_add(json_path
, "valid");
7315 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7316 json_object_boolean_true_add(json_path
, "history");
7318 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7319 json_object_boolean_true_add(json_path
, "damped");
7321 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7322 json_object_boolean_true_add(json_path
, "bestpath");
7324 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7325 json_object_boolean_true_add(json_path
, "multipath");
7327 /* Internal route. */
7328 if ((path
->peer
->as
)
7329 && (path
->peer
->as
== path
->peer
->local_as
))
7330 json_object_string_add(json_path
, "pathFrom",
7333 json_object_string_add(json_path
, "pathFrom",
7339 /* Route status display. */
7340 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7342 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7344 else if (path
->extra
&& path
->extra
->suppress
)
7346 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7347 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7353 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7355 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7357 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7359 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7364 /* Internal route. */
7365 if (path
->peer
&& (path
->peer
->as
)
7366 && (path
->peer
->as
== path
->peer
->local_as
))
7372 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7374 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7375 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7376 return peer
->hostname
;
7380 /* called from terminal list command */
7381 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7382 struct bgp_path_info
*path
, int display
, safi_t safi
,
7383 json_object
*json_paths
)
7385 struct attr
*attr
= path
->attr
;
7386 json_object
*json_path
= NULL
;
7387 json_object
*json_nexthops
= NULL
;
7388 json_object
*json_nexthop_global
= NULL
;
7389 json_object
*json_nexthop_ll
= NULL
;
7390 json_object
*json_ext_community
= NULL
;
7391 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7393 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7394 bool nexthop_othervrf
= false;
7395 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7396 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7397 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7400 json_path
= json_object_new_object();
7402 /* short status lead text */
7403 route_vty_short_status_out(vty
, path
, json_path
);
7406 /* print prefix and mask */
7408 route_vty_out_route(p
, vty
, json_path
);
7410 vty_out(vty
, "%*s", 17, " ");
7412 route_vty_out_route(p
, vty
, json_path
);
7416 * If vrf id of nexthop is different from that of prefix,
7417 * set up printable string to append
7419 if (path
->extra
&& path
->extra
->bgp_orig
) {
7420 const char *self
= "";
7425 nexthop_othervrf
= true;
7426 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7428 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7429 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7430 "@%s%s", VRFID_NONE_STR
, self
);
7432 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7433 path
->extra
->bgp_orig
->vrf_id
, self
);
7435 if (path
->extra
->bgp_orig
->inst_type
7436 != BGP_INSTANCE_TYPE_DEFAULT
)
7438 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7440 const char *self
= "";
7445 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7449 * For ENCAP and EVPN routes, nexthop address family is not
7450 * neccessarily the same as the prefix address family.
7451 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7452 * EVPN routes are also exchanged with a MP nexthop. Currently,
7454 * is only IPv4, the value will be present in either
7456 * attr->mp_nexthop_global_in
7458 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7461 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7465 sprintf(nexthop
, "%s",
7466 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7470 sprintf(nexthop
, "%s",
7471 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7475 sprintf(nexthop
, "?");
7480 json_nexthop_global
= json_object_new_object();
7482 json_object_string_add(json_nexthop_global
, "ip",
7485 if (nexthop_hostname
)
7486 json_object_string_add(json_nexthop_global
,
7490 json_object_string_add(json_nexthop_global
, "afi",
7491 (af
== AF_INET
) ? "ipv4"
7493 json_object_boolean_true_add(json_nexthop_global
,
7496 vty_out(vty
, "%s%s",
7497 nexthop_hostname
? nexthop_hostname
: nexthop
,
7499 } else if (safi
== SAFI_EVPN
) {
7501 json_nexthop_global
= json_object_new_object();
7503 json_object_string_add(json_nexthop_global
, "ip",
7504 inet_ntoa(attr
->nexthop
));
7506 if (nexthop_hostname
)
7507 json_object_string_add(json_nexthop_global
,
7511 json_object_string_add(json_nexthop_global
, "afi",
7513 json_object_boolean_true_add(json_nexthop_global
,
7516 vty_out(vty
, "%-16s%s",
7517 nexthop_hostname
? nexthop_hostname
7518 : inet_ntoa(attr
->nexthop
),
7520 } else if (safi
== SAFI_FLOWSPEC
) {
7521 if (attr
->nexthop
.s_addr
!= 0) {
7523 json_nexthop_global
= json_object_new_object();
7525 json_object_string_add(json_nexthop_global
,
7527 json_object_string_add(
7528 json_nexthop_global
, "ip",
7529 inet_ntoa(attr
->nexthop
));
7531 if (nexthop_hostname
)
7532 json_object_string_add(
7533 json_nexthop_global
, "hostname",
7536 json_object_boolean_true_add(
7537 json_nexthop_global
,
7540 vty_out(vty
, "%-16s",
7543 : inet_ntoa(attr
->nexthop
));
7546 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7548 json_nexthop_global
= json_object_new_object();
7550 json_object_string_add(json_nexthop_global
, "ip",
7551 inet_ntoa(attr
->nexthop
));
7553 if (nexthop_hostname
)
7554 json_object_string_add(json_nexthop_global
,
7558 json_object_string_add(json_nexthop_global
, "afi",
7560 json_object_boolean_true_add(json_nexthop_global
,
7565 snprintf(buf
, sizeof(buf
), "%s%s",
7566 nexthop_hostname
? nexthop_hostname
7567 : inet_ntoa(attr
->nexthop
),
7569 vty_out(vty
, "%-16s", buf
);
7574 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7579 json_nexthop_global
= json_object_new_object();
7580 json_object_string_add(
7581 json_nexthop_global
, "ip",
7582 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7585 if (nexthop_hostname
)
7586 json_object_string_add(json_nexthop_global
,
7590 json_object_string_add(json_nexthop_global
, "afi",
7592 json_object_string_add(json_nexthop_global
, "scope",
7595 /* We display both LL & GL if both have been
7597 if ((attr
->mp_nexthop_len
7598 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7599 || (path
->peer
->conf_if
)) {
7600 json_nexthop_ll
= json_object_new_object();
7601 json_object_string_add(
7602 json_nexthop_ll
, "ip",
7604 &attr
->mp_nexthop_local
, buf
,
7607 if (nexthop_hostname
)
7608 json_object_string_add(
7609 json_nexthop_ll
, "hostname",
7612 json_object_string_add(json_nexthop_ll
, "afi",
7614 json_object_string_add(json_nexthop_ll
, "scope",
7617 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7618 &attr
->mp_nexthop_local
)
7620 && !attr
->mp_nexthop_prefer_global
)
7621 json_object_boolean_true_add(
7622 json_nexthop_ll
, "used");
7624 json_object_boolean_true_add(
7625 json_nexthop_global
, "used");
7627 json_object_boolean_true_add(
7628 json_nexthop_global
, "used");
7630 /* Display LL if LL/Global both in table unless
7631 * prefer-global is set */
7632 if (((attr
->mp_nexthop_len
7633 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7634 && !attr
->mp_nexthop_prefer_global
)
7635 || (path
->peer
->conf_if
)) {
7636 if (path
->peer
->conf_if
) {
7637 len
= vty_out(vty
, "%s",
7638 path
->peer
->conf_if
);
7639 len
= 16 - len
; /* len of IPv6
7645 vty_out(vty
, "\n%*s", 36, " ");
7647 vty_out(vty
, "%*s", len
, " ");
7655 &attr
->mp_nexthop_local
,
7661 vty_out(vty
, "\n%*s", 36, " ");
7663 vty_out(vty
, "%*s", len
, " ");
7672 &attr
->mp_nexthop_global
,
7678 vty_out(vty
, "\n%*s", 36, " ");
7680 vty_out(vty
, "%*s", len
, " ");
7686 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7690 * Adding "metric" field to match with corresponding
7691 * CLI. "med" will be deprecated in future.
7693 json_object_int_add(json_path
, "med", attr
->med
);
7694 json_object_int_add(json_path
, "metric", attr
->med
);
7696 vty_out(vty
, "%10u", attr
->med
);
7697 else if (!json_paths
)
7701 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7705 * Adding "locPrf" field to match with corresponding
7706 * CLI. "localPref" will be deprecated in future.
7708 json_object_int_add(json_path
, "localpref",
7710 json_object_int_add(json_path
, "locPrf",
7713 vty_out(vty
, "%7u", attr
->local_pref
);
7714 else if (!json_paths
)
7718 json_object_int_add(json_path
, "weight", attr
->weight
);
7720 vty_out(vty
, "%7u ", attr
->weight
);
7724 json_object_string_add(
7725 json_path
, "peerId",
7726 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7734 * Adding "path" field to match with corresponding
7735 * CLI. "aspath" will be deprecated in future.
7737 json_object_string_add(json_path
, "aspath",
7739 json_object_string_add(json_path
, "path",
7742 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7747 json_object_string_add(json_path
, "origin",
7748 bgp_origin_long_str
[attr
->origin
]);
7750 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7753 if (safi
== SAFI_EVPN
&&
7754 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7755 json_ext_community
= json_object_new_object();
7756 json_object_string_add(json_ext_community
,
7758 attr
->ecommunity
->str
);
7759 json_object_object_add(json_path
,
7760 "extendedCommunity",
7761 json_ext_community
);
7765 json_object_boolean_true_add(json_path
,
7766 "announceNexthopSelf");
7767 if (nexthop_othervrf
) {
7768 json_object_string_add(json_path
, "nhVrfName",
7771 json_object_int_add(json_path
, "nhVrfId",
7772 ((nexthop_vrfid
== VRF_UNKNOWN
)
7774 : (int)nexthop_vrfid
));
7779 if (json_nexthop_global
|| json_nexthop_ll
) {
7780 json_nexthops
= json_object_new_array();
7782 if (json_nexthop_global
)
7783 json_object_array_add(json_nexthops
,
7784 json_nexthop_global
);
7786 if (json_nexthop_ll
)
7787 json_object_array_add(json_nexthops
,
7790 json_object_object_add(json_path
, "nexthops",
7794 json_object_array_add(json_paths
, json_path
);
7798 if (safi
== SAFI_EVPN
&&
7799 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7800 vty_out(vty
, "%*s", 20, " ");
7801 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7805 /* prints an additional line, indented, with VNC info, if
7807 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7808 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7813 /* called from terminal list command */
7814 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7815 safi_t safi
, bool use_json
, json_object
*json_ar
)
7817 json_object
*json_status
= NULL
;
7818 json_object
*json_net
= NULL
;
7821 /* Route status display. */
7823 json_status
= json_object_new_object();
7824 json_net
= json_object_new_object();
7831 /* print prefix and mask */
7833 if (safi
== SAFI_EVPN
)
7834 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7835 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7836 json_object_string_add(
7837 json_net
, "addrPrefix",
7838 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7840 json_object_int_add(json_net
, "prefixLen",
7842 prefix2str(p
, buff
, PREFIX_STRLEN
);
7843 json_object_string_add(json_net
, "network", buff
);
7846 route_vty_out_route(p
, vty
, NULL
);
7848 /* Print attribute */
7851 if (p
->family
== AF_INET
7852 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7853 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7854 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7855 json_object_string_add(
7856 json_net
, "nextHop",
7858 attr
->mp_nexthop_global_in
));
7860 json_object_string_add(
7861 json_net
, "nextHop",
7862 inet_ntoa(attr
->nexthop
));
7863 } else if (p
->family
== AF_INET6
7864 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7867 json_object_string_add(
7868 json_net
, "nextHopGlobal",
7870 &attr
->mp_nexthop_global
, buf
,
7872 } else if (p
->family
== AF_EVPN
&&
7873 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7874 json_object_string_add(json_net
,
7875 "nextHop", inet_ntoa(
7876 attr
->mp_nexthop_global_in
));
7879 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7880 json_object_int_add(json_net
, "metric",
7883 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7886 * Adding "locPrf" field to match with
7887 * corresponding CLI. "localPref" will be
7888 * deprecated in future.
7890 json_object_int_add(json_net
, "localPref",
7892 json_object_int_add(json_net
, "locPrf",
7896 json_object_int_add(json_net
, "weight", attr
->weight
);
7902 * Adding "path" field to match with
7903 * corresponding CLI. "localPref" will be
7904 * deprecated in future.
7906 json_object_string_add(json_net
, "asPath",
7908 json_object_string_add(json_net
, "path",
7913 json_object_string_add(json_net
, "bgpOriginCode",
7914 bgp_origin_str
[attr
->origin
]);
7916 if (p
->family
== AF_INET
7917 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7918 || safi
== SAFI_EVPN
7919 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7920 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7921 || safi
== SAFI_EVPN
)
7922 vty_out(vty
, "%-16s",
7924 attr
->mp_nexthop_global_in
));
7926 vty_out(vty
, "%-16s",
7927 inet_ntoa(attr
->nexthop
));
7928 } else if (p
->family
== AF_INET6
7929 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7936 &attr
->mp_nexthop_global
, buf
,
7940 vty_out(vty
, "\n%*s", 36, " ");
7942 vty_out(vty
, "%*s", len
, " ");
7945 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7946 vty_out(vty
, "%10u", attr
->med
);
7950 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7951 vty_out(vty
, "%7u", attr
->local_pref
);
7955 vty_out(vty
, "%7u ", attr
->weight
);
7959 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7962 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7966 json_object_boolean_true_add(json_status
, "*");
7967 json_object_boolean_true_add(json_status
, ">");
7968 json_object_object_add(json_net
, "appliedStatusSymbols",
7971 prefix2str(p
, buff
, PREFIX_STRLEN
);
7972 json_object_object_add(json_ar
, buff
, json_net
);
7977 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7978 struct bgp_path_info
*path
, int display
, safi_t safi
,
7981 json_object
*json_out
= NULL
;
7983 mpls_label_t label
= MPLS_INVALID_LABEL
;
7989 json_out
= json_object_new_object();
7991 /* short status lead text */
7992 route_vty_short_status_out(vty
, path
, json_out
);
7994 /* print prefix and mask */
7997 route_vty_out_route(p
, vty
, NULL
);
7999 vty_out(vty
, "%*s", 17, " ");
8002 /* Print attribute */
8004 if (((p
->family
== AF_INET
)
8005 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8006 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8007 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8008 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8009 || safi
== SAFI_EVPN
) {
8011 json_object_string_add(
8012 json_out
, "mpNexthopGlobalIn",
8013 inet_ntoa(attr
->mp_nexthop_global_in
));
8015 vty_out(vty
, "%-16s",
8016 inet_ntoa(attr
->mp_nexthop_global_in
));
8019 json_object_string_add(
8020 json_out
, "nexthop",
8021 inet_ntoa(attr
->nexthop
));
8023 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8025 } else if (((p
->family
== AF_INET6
)
8026 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8027 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8028 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8031 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8033 json_object_string_add(
8034 json_out
, "mpNexthopGlobalIn",
8036 &attr
->mp_nexthop_global
,
8037 buf_a
, sizeof(buf_a
)));
8041 &attr
->mp_nexthop_global
,
8042 buf_a
, sizeof(buf_a
)));
8043 } else if (attr
->mp_nexthop_len
8044 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8045 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8046 &attr
->mp_nexthop_global
,
8047 &attr
->mp_nexthop_local
);
8049 json_object_string_add(json_out
,
8050 "mpNexthopGlobalLocal",
8053 vty_out(vty
, "%s", buf_a
);
8057 label
= decode_label(&path
->extra
->label
[0]);
8059 if (bgp_is_valid_label(&label
)) {
8061 json_object_int_add(json_out
, "notag", label
);
8062 json_object_array_add(json
, json_out
);
8064 vty_out(vty
, "notag/%d", label
);
8070 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
8071 struct bgp_path_info
*path
, int display
,
8072 json_object
*json_paths
)
8075 char buf
[BUFSIZ
] = {0};
8076 json_object
*json_path
= NULL
;
8077 json_object
*json_nexthop
= NULL
;
8078 json_object
*json_overlay
= NULL
;
8084 json_path
= json_object_new_object();
8085 json_overlay
= json_object_new_object();
8086 json_nexthop
= json_object_new_object();
8089 /* short status lead text */
8090 route_vty_short_status_out(vty
, path
, json_path
);
8092 /* print prefix and mask */
8094 route_vty_out_route(p
, vty
, json_path
);
8096 vty_out(vty
, "%*s", 17, " ");
8098 /* Print attribute */
8101 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8105 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8107 vty_out(vty
, "%-16s", buf
);
8109 json_object_string_add(json_nexthop
, "ip", buf
);
8111 json_object_string_add(json_nexthop
, "afi", "ipv4");
8113 json_object_object_add(json_path
, "nexthop",
8118 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8119 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8121 vty_out(vty
, "%s(%s)", buf
, buf1
);
8123 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8125 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8128 json_object_string_add(json_nexthop
, "afi", "ipv6");
8130 json_object_object_add(json_path
, "nexthop",
8138 json_object_string_add(json_nexthop
, "Error",
8139 "Unsupported address-family");
8143 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
8146 vty_out(vty
, "%s", str
);
8148 json_object_string_add(json_overlay
, "esi", str
);
8150 XFREE(MTYPE_TMP
, str
);
8152 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8153 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8155 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8156 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8161 vty_out(vty
, "/%s", buf
);
8163 json_object_string_add(json_overlay
, "gw", buf
);
8165 if (attr
->ecommunity
) {
8167 struct ecommunity_val
*routermac
= ecommunity_lookup(
8168 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8169 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8172 mac
= ecom_mac2str((char *)routermac
->val
);
8175 vty_out(vty
, "/%s", (char *)mac
);
8177 json_object_string_add(json_overlay
, "rmac",
8180 XFREE(MTYPE_TMP
, mac
);
8187 json_object_object_add(json_path
, "overlay", json_overlay
);
8189 json_object_array_add(json_paths
, json_path
);
8193 /* dampening route */
8194 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8195 struct bgp_path_info
*path
, int display
, afi_t afi
,
8196 safi_t safi
, bool use_json
, json_object
*json
)
8200 char timebuf
[BGP_UPTIME_LEN
];
8202 /* short status lead text */
8203 route_vty_short_status_out(vty
, path
, json
);
8205 /* print prefix and mask */
8208 route_vty_out_route(p
, vty
, NULL
);
8210 vty_out(vty
, "%*s", 17, " ");
8213 len
= vty_out(vty
, "%s", path
->peer
->host
);
8217 vty_out(vty
, "\n%*s", 34, " ");
8220 json_object_int_add(json
, "peerHost", len
);
8222 vty_out(vty
, "%*s", len
, " ");
8226 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8227 safi
, use_json
, json
);
8230 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8231 BGP_UPTIME_LEN
, afi
, safi
,
8234 /* Print attribute */
8240 json_object_string_add(json
, "asPath",
8243 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8248 json_object_string_add(json
, "origin",
8249 bgp_origin_str
[attr
->origin
]);
8251 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8258 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8259 struct bgp_path_info
*path
, int display
, afi_t afi
,
8260 safi_t safi
, bool use_json
, json_object
*json
)
8263 struct bgp_damp_info
*bdi
;
8264 char timebuf
[BGP_UPTIME_LEN
];
8270 bdi
= path
->extra
->damp_info
;
8272 /* short status lead text */
8273 route_vty_short_status_out(vty
, path
, json
);
8275 /* print prefix and mask */
8278 route_vty_out_route(p
, vty
, NULL
);
8280 vty_out(vty
, "%*s", 17, " ");
8283 len
= vty_out(vty
, "%s", path
->peer
->host
);
8287 vty_out(vty
, "\n%*s", 33, " ");
8290 json_object_int_add(json
, "peerHost", len
);
8292 vty_out(vty
, "%*s", len
, " ");
8295 len
= vty_out(vty
, "%d", bdi
->flap
);
8302 json_object_int_add(json
, "bdiFlap", len
);
8304 vty_out(vty
, "%*s", len
, " ");
8308 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8311 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8312 BGP_UPTIME_LEN
, 0, NULL
));
8314 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8315 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8317 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8318 BGP_UPTIME_LEN
, afi
, safi
,
8322 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8323 BGP_UPTIME_LEN
, afi
,
8324 safi
, use_json
, json
));
8327 vty_out(vty
, "%*s ", 8, " ");
8330 /* Print attribute */
8336 json_object_string_add(json
, "asPath",
8339 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8344 json_object_string_add(json
, "origin",
8345 bgp_origin_str
[attr
->origin
]);
8347 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8353 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8354 int *first
, const char *header
,
8355 json_object
*json_adv_to
)
8357 char buf1
[INET6_ADDRSTRLEN
];
8358 json_object
*json_peer
= NULL
;
8361 /* 'advertised-to' is a dictionary of peers we have advertised
8363 * prefix too. The key is the peer's IP or swpX, the value is
8365 * hostname if we know it and "" if not.
8367 json_peer
= json_object_new_object();
8370 json_object_string_add(json_peer
, "hostname",
8374 json_object_object_add(json_adv_to
, peer
->conf_if
,
8377 json_object_object_add(
8379 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8383 vty_out(vty
, "%s", header
);
8388 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8390 vty_out(vty
, " %s(%s)", peer
->hostname
,
8393 vty_out(vty
, " %s(%s)", peer
->hostname
,
8394 sockunion2str(&peer
->su
, buf1
,
8398 vty_out(vty
, " %s", peer
->conf_if
);
8401 sockunion2str(&peer
->su
, buf1
,
8407 static void route_vty_out_tx_ids(struct vty
*vty
,
8408 struct bgp_addpath_info_data
*d
)
8412 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8413 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8414 d
->addpath_tx_id
[i
],
8415 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8419 static const char *bgp_path_selection_reason2str(
8420 enum bgp_path_selection_reason reason
)
8423 case bgp_path_selection_none
:
8424 return "Nothing to Select";
8426 case bgp_path_selection_first
:
8427 return "First path received";
8429 case bgp_path_selection_evpn_sticky_mac
:
8430 return "EVPN Sticky Mac";
8432 case bgp_path_selection_evpn_seq
:
8433 return "EVPN sequence number";
8435 case bgp_path_selection_evpn_lower_ip
:
8436 return "EVPN lower IP";
8438 case bgp_path_selection_weight
:
8441 case bgp_path_selection_local_pref
:
8442 return "Local Pref";
8444 case bgp_path_selection_local_route
:
8445 return "Local Route";
8447 case bgp_path_selection_confed_as_path
:
8448 return "Confederation based AS Path";
8450 case bgp_path_selection_as_path
:
8453 case bgp_path_selection_origin
:
8456 case bgp_path_selection_med
:
8459 case bgp_path_selection_peer
:
8462 case bgp_path_selection_confed
:
8463 return "Confed Peer Type";
8465 case bgp_path_selection_igp_metric
:
8466 return "IGP Metric";
8468 case bgp_path_selection_older
:
8469 return "Older Path";
8471 case bgp_path_selection_router_id
:
8474 case bgp_path_selection_cluster_length
:
8475 return "Cluser length";
8477 case bgp_path_selection_stale
:
8478 return "Path Staleness";
8480 case bgp_path_selection_local_configured
:
8481 return "Locally configured route";
8483 case bgp_path_selection_neighbor_ip
:
8484 return "Neighbor IP";
8486 case bgp_path_selection_default
:
8487 return "Nothing left to compare";
8490 return "Invalid (internal error)";
8493 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8494 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8495 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8497 char buf
[INET6_ADDRSTRLEN
];
8499 char buf2
[EVPN_ROUTE_STRLEN
];
8500 struct attr
*attr
= path
->attr
;
8501 int sockunion_vty_out(struct vty
*, union sockunion
*);
8503 json_object
*json_bestpath
= NULL
;
8504 json_object
*json_cluster_list
= NULL
;
8505 json_object
*json_cluster_list_list
= NULL
;
8506 json_object
*json_ext_community
= NULL
;
8507 json_object
*json_last_update
= NULL
;
8508 json_object
*json_pmsi
= NULL
;
8509 json_object
*json_nexthop_global
= NULL
;
8510 json_object
*json_nexthop_ll
= NULL
;
8511 json_object
*json_nexthops
= NULL
;
8512 json_object
*json_path
= NULL
;
8513 json_object
*json_peer
= NULL
;
8514 json_object
*json_string
= NULL
;
8515 json_object
*json_adv_to
= NULL
;
8517 struct listnode
*node
, *nnode
;
8519 int addpath_capable
;
8521 unsigned int first_as
;
8523 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8525 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8528 json_path
= json_object_new_object();
8529 json_peer
= json_object_new_object();
8530 json_nexthop_global
= json_object_new_object();
8538 if (path
->extra
&& path
->extra
->num_labels
) {
8539 bgp_evpn_label2str(path
->extra
->label
,
8540 path
->extra
->num_labels
, tag_buf
,
8543 if (safi
== SAFI_EVPN
) {
8545 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8546 buf2
, sizeof(buf2
));
8547 vty_out(vty
, " Route %s", buf2
);
8548 if (tag_buf
[0] != '\0')
8549 vty_out(vty
, " VNI %s", tag_buf
);
8553 json_object_string_add(json_path
, "VNI",
8558 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8559 struct bgp_path_info
*parent_ri
;
8560 struct bgp_node
*rn
, *prn
;
8562 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8563 rn
= parent_ri
->net
;
8564 if (rn
&& rn
->prn
) {
8566 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8567 buf1
, sizeof(buf1
));
8568 if (is_pi_family_evpn(parent_ri
)) {
8569 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8570 buf2
, sizeof(buf2
));
8571 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8573 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8578 /* Line1 display AS-path, Aggregator */
8581 if (!attr
->aspath
->json
)
8582 aspath_str_update(attr
->aspath
, true);
8583 json_object_lock(attr
->aspath
->json
);
8584 json_object_object_add(json_path
, "aspath",
8585 attr
->aspath
->json
);
8587 if (attr
->aspath
->segments
)
8588 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8590 vty_out(vty
, " Local");
8594 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8596 json_object_boolean_true_add(json_path
, "removed");
8598 vty_out(vty
, ", (removed)");
8601 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8603 json_object_boolean_true_add(json_path
, "stale");
8605 vty_out(vty
, ", (stale)");
8608 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8610 json_object_int_add(json_path
, "aggregatorAs",
8611 attr
->aggregator_as
);
8612 json_object_string_add(
8613 json_path
, "aggregatorId",
8614 inet_ntoa(attr
->aggregator_addr
));
8616 vty_out(vty
, ", (aggregated by %u %s)",
8617 attr
->aggregator_as
,
8618 inet_ntoa(attr
->aggregator_addr
));
8622 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8623 PEER_FLAG_REFLECTOR_CLIENT
)) {
8625 json_object_boolean_true_add(json_path
,
8626 "rxedFromRrClient");
8628 vty_out(vty
, ", (Received from a RR-client)");
8631 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8632 PEER_FLAG_RSERVER_CLIENT
)) {
8634 json_object_boolean_true_add(json_path
,
8635 "rxedFromRsClient");
8637 vty_out(vty
, ", (Received from a RS-client)");
8640 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8642 json_object_boolean_true_add(json_path
,
8643 "dampeningHistoryEntry");
8645 vty_out(vty
, ", (history entry)");
8646 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8648 json_object_boolean_true_add(json_path
,
8649 "dampeningSuppressed");
8651 vty_out(vty
, ", (suppressed due to dampening)");
8657 /* Line2 display Next-hop, Neighbor, Router-id */
8658 /* Display the nexthop */
8659 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8660 || bn
->p
.family
== AF_EVPN
)
8661 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8662 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8663 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8664 || safi
== SAFI_EVPN
) {
8666 json_object_string_add(
8667 json_nexthop_global
, "ip",
8668 inet_ntoa(attr
->mp_nexthop_global_in
));
8670 if (nexthop_hostname
)
8671 json_object_string_add(
8672 json_nexthop_global
, "hostname",
8679 attr
->mp_nexthop_global_in
));
8682 json_object_string_add(
8683 json_nexthop_global
, "ip",
8684 inet_ntoa(attr
->nexthop
));
8686 if (nexthop_hostname
)
8687 json_object_string_add(
8688 json_nexthop_global
, "hostname",
8694 : inet_ntoa(attr
->nexthop
));
8698 json_object_string_add(json_nexthop_global
, "afi",
8702 json_object_string_add(
8703 json_nexthop_global
, "ip",
8704 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8705 buf
, INET6_ADDRSTRLEN
));
8707 if (nexthop_hostname
)
8708 json_object_string_add(json_nexthop_global
,
8712 json_object_string_add(json_nexthop_global
, "afi",
8714 json_object_string_add(json_nexthop_global
, "scope",
8720 : inet_ntop(AF_INET6
,
8721 &attr
->mp_nexthop_global
,
8722 buf
, INET6_ADDRSTRLEN
));
8726 /* Display the IGP cost or 'inaccessible' */
8727 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8729 json_object_boolean_false_add(json_nexthop_global
,
8732 vty_out(vty
, " (inaccessible)");
8734 if (path
->extra
&& path
->extra
->igpmetric
) {
8736 json_object_int_add(json_nexthop_global
,
8738 path
->extra
->igpmetric
);
8740 vty_out(vty
, " (metric %u)",
8741 path
->extra
->igpmetric
);
8744 /* IGP cost is 0, display this only for json */
8747 json_object_int_add(json_nexthop_global
,
8752 json_object_boolean_true_add(json_nexthop_global
,
8756 /* Display peer "from" output */
8757 /* This path was originated locally */
8758 if (path
->peer
== bgp
->peer_self
) {
8760 if (safi
== SAFI_EVPN
8761 || (bn
->p
.family
== AF_INET
8762 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8764 json_object_string_add(json_peer
, "peerId",
8767 vty_out(vty
, " from 0.0.0.0 ");
8770 json_object_string_add(json_peer
, "peerId",
8773 vty_out(vty
, " from :: ");
8777 json_object_string_add(json_peer
, "routerId",
8778 inet_ntoa(bgp
->router_id
));
8780 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8783 /* We RXed this path from one of our peers */
8787 json_object_string_add(json_peer
, "peerId",
8788 sockunion2str(&path
->peer
->su
,
8791 json_object_string_add(json_peer
, "routerId",
8793 &path
->peer
->remote_id
,
8794 buf1
, sizeof(buf1
)));
8796 if (path
->peer
->hostname
)
8797 json_object_string_add(json_peer
, "hostname",
8798 path
->peer
->hostname
);
8800 if (path
->peer
->domainname
)
8801 json_object_string_add(json_peer
, "domainname",
8802 path
->peer
->domainname
);
8804 if (path
->peer
->conf_if
)
8805 json_object_string_add(json_peer
, "interface",
8806 path
->peer
->conf_if
);
8808 if (path
->peer
->conf_if
) {
8809 if (path
->peer
->hostname
8810 && bgp_flag_check(path
->peer
->bgp
,
8811 BGP_FLAG_SHOW_HOSTNAME
))
8812 vty_out(vty
, " from %s(%s)",
8813 path
->peer
->hostname
,
8814 path
->peer
->conf_if
);
8816 vty_out(vty
, " from %s",
8817 path
->peer
->conf_if
);
8819 if (path
->peer
->hostname
8820 && bgp_flag_check(path
->peer
->bgp
,
8821 BGP_FLAG_SHOW_HOSTNAME
))
8822 vty_out(vty
, " from %s(%s)",
8823 path
->peer
->hostname
,
8826 vty_out(vty
, " from %s",
8827 sockunion2str(&path
->peer
->su
,
8832 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8833 vty_out(vty
, " (%s)",
8834 inet_ntoa(attr
->originator_id
));
8836 vty_out(vty
, " (%s)",
8838 &path
->peer
->remote_id
, buf1
,
8844 * Note when vrfid of nexthop is different from that of prefix
8846 if (path
->extra
&& path
->extra
->bgp_orig
) {
8847 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8852 if (path
->extra
->bgp_orig
->inst_type
8853 == BGP_INSTANCE_TYPE_DEFAULT
)
8854 vn
= VRF_DEFAULT_NAME
;
8856 vn
= path
->extra
->bgp_orig
->name
;
8858 json_object_string_add(json_path
, "nhVrfName", vn
);
8860 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8861 json_object_int_add(json_path
, "nhVrfId", -1);
8863 json_object_int_add(json_path
, "nhVrfId",
8864 (int)nexthop_vrfid
);
8867 if (nexthop_vrfid
== VRF_UNKNOWN
)
8868 vty_out(vty
, " vrf ?");
8870 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8876 json_object_boolean_true_add(json_path
,
8877 "announceNexthopSelf");
8879 vty_out(vty
, " announce-nh-self");
8886 /* display the link-local nexthop */
8887 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8889 json_nexthop_ll
= json_object_new_object();
8890 json_object_string_add(
8891 json_nexthop_ll
, "ip",
8892 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8893 buf
, INET6_ADDRSTRLEN
));
8895 if (nexthop_hostname
)
8896 json_object_string_add(json_nexthop_ll
,
8900 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8901 json_object_string_add(json_nexthop_ll
, "scope",
8904 json_object_boolean_true_add(json_nexthop_ll
,
8907 if (!attr
->mp_nexthop_prefer_global
)
8908 json_object_boolean_true_add(json_nexthop_ll
,
8911 json_object_boolean_true_add(
8912 json_nexthop_global
, "used");
8914 vty_out(vty
, " (%s) %s\n",
8915 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8916 buf
, INET6_ADDRSTRLEN
),
8917 attr
->mp_nexthop_prefer_global
8922 /* If we do not have a link-local nexthop then we must flag the
8926 json_object_boolean_true_add(json_nexthop_global
,
8930 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8931 * Int/Ext/Local, Atomic, best */
8933 json_object_string_add(json_path
, "origin",
8934 bgp_origin_long_str
[attr
->origin
]);
8936 vty_out(vty
, " Origin %s",
8937 bgp_origin_long_str
[attr
->origin
]);
8939 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8942 * Adding "metric" field to match with
8943 * corresponding CLI. "med" will be
8944 * deprecated in future.
8946 json_object_int_add(json_path
, "med", attr
->med
);
8947 json_object_int_add(json_path
, "metric", attr
->med
);
8949 vty_out(vty
, ", metric %u", attr
->med
);
8952 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8954 json_object_int_add(json_path
, "localpref",
8957 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8960 if (attr
->weight
!= 0) {
8962 json_object_int_add(json_path
, "weight", attr
->weight
);
8964 vty_out(vty
, ", weight %u", attr
->weight
);
8967 if (attr
->tag
!= 0) {
8969 json_object_int_add(json_path
, "tag", attr
->tag
);
8971 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8974 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8976 json_object_boolean_false_add(json_path
, "valid");
8978 vty_out(vty
, ", invalid");
8979 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8981 json_object_boolean_true_add(json_path
, "valid");
8983 vty_out(vty
, ", valid");
8986 if (path
->peer
!= bgp
->peer_self
) {
8987 if (path
->peer
->as
== path
->peer
->local_as
) {
8988 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8990 json_object_string_add(
8994 vty_out(vty
, ", confed-internal");
8997 json_object_string_add(
8998 json_peer
, "type", "internal");
9000 vty_out(vty
, ", internal");
9003 if (bgp_confederation_peers_check(bgp
,
9006 json_object_string_add(
9010 vty_out(vty
, ", confed-external");
9013 json_object_string_add(
9014 json_peer
, "type", "external");
9016 vty_out(vty
, ", external");
9019 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9021 json_object_boolean_true_add(json_path
, "aggregated");
9022 json_object_boolean_true_add(json_path
, "local");
9024 vty_out(vty
, ", aggregated, local");
9026 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9028 json_object_boolean_true_add(json_path
, "sourced");
9030 vty_out(vty
, ", sourced");
9033 json_object_boolean_true_add(json_path
, "sourced");
9034 json_object_boolean_true_add(json_path
, "local");
9036 vty_out(vty
, ", sourced, local");
9040 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9042 json_object_boolean_true_add(json_path
,
9045 vty_out(vty
, ", atomic-aggregate");
9048 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9049 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9050 && bgp_path_info_mpath_count(path
))) {
9052 json_object_boolean_true_add(json_path
, "multipath");
9054 vty_out(vty
, ", multipath");
9057 // Mark the bestpath(s)
9058 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9059 first_as
= aspath_get_first_as(attr
->aspath
);
9063 json_bestpath
= json_object_new_object();
9064 json_object_int_add(json_bestpath
, "bestpathFromAs",
9068 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9070 vty_out(vty
, ", bestpath-from-AS Local");
9074 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9077 json_bestpath
= json_object_new_object();
9078 json_object_boolean_true_add(json_bestpath
, "overall");
9079 json_object_string_add(
9080 json_bestpath
, "selectionReason",
9081 bgp_path_selection_reason2str(bn
->reason
));
9083 vty_out(vty
, ", best");
9084 vty_out(vty
, " (%s)",
9085 bgp_path_selection_reason2str(bn
->reason
));
9090 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9095 /* Line 4 display Community */
9096 if (attr
->community
) {
9098 if (!attr
->community
->json
)
9099 community_str(attr
->community
, true);
9100 json_object_lock(attr
->community
->json
);
9101 json_object_object_add(json_path
, "community",
9102 attr
->community
->json
);
9104 vty_out(vty
, " Community: %s\n",
9105 attr
->community
->str
);
9109 /* Line 5 display Extended-community */
9110 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9112 json_ext_community
= json_object_new_object();
9113 json_object_string_add(json_ext_community
, "string",
9114 attr
->ecommunity
->str
);
9115 json_object_object_add(json_path
, "extendedCommunity",
9116 json_ext_community
);
9118 vty_out(vty
, " Extended Community: %s\n",
9119 attr
->ecommunity
->str
);
9123 /* Line 6 display Large community */
9124 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9126 if (!attr
->lcommunity
->json
)
9127 lcommunity_str(attr
->lcommunity
, true);
9128 json_object_lock(attr
->lcommunity
->json
);
9129 json_object_object_add(json_path
, "largeCommunity",
9130 attr
->lcommunity
->json
);
9132 vty_out(vty
, " Large Community: %s\n",
9133 attr
->lcommunity
->str
);
9137 /* Line 7 display Originator, Cluster-id */
9138 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9139 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9140 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9142 json_object_string_add(
9143 json_path
, "originatorId",
9144 inet_ntoa(attr
->originator_id
));
9146 vty_out(vty
, " Originator: %s",
9147 inet_ntoa(attr
->originator_id
));
9150 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9154 json_cluster_list
= json_object_new_object();
9155 json_cluster_list_list
=
9156 json_object_new_array();
9158 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9160 json_string
= json_object_new_string(
9161 inet_ntoa(attr
->cluster
9163 json_object_array_add(
9164 json_cluster_list_list
,
9169 * struct cluster_list does not have
9170 * "str" variable like aspath and community
9171 * do. Add this someday if someone asks
9173 * json_object_string_add(json_cluster_list,
9174 * "string", attr->cluster->str);
9176 json_object_object_add(json_cluster_list
,
9178 json_cluster_list_list
);
9179 json_object_object_add(json_path
, "clusterList",
9182 vty_out(vty
, ", Cluster list: ");
9184 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9187 inet_ntoa(attr
->cluster
9197 if (path
->extra
&& path
->extra
->damp_info
)
9198 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9201 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9202 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9203 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9206 json_object_int_add(json_path
, "remoteLabel", label
);
9208 vty_out(vty
, " Remote label: %d\n", label
);
9212 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9214 json_object_int_add(json_path
, "labelIndex",
9217 vty_out(vty
, " Label Index: %d\n",
9221 /* Line 8 display Addpath IDs */
9222 if (path
->addpath_rx_id
9223 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9225 json_object_int_add(json_path
, "addpathRxId",
9226 path
->addpath_rx_id
);
9228 /* Keep backwards compatibility with the old API
9229 * by putting TX All's ID in the old field
9231 json_object_int_add(
9232 json_path
, "addpathTxId",
9234 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9236 /* ... but create a specific field for each
9239 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9240 json_object_int_add(
9242 bgp_addpath_names(i
)->id_json_name
,
9243 path
->tx_addpath
.addpath_tx_id
[i
]);
9246 vty_out(vty
, " AddPath ID: RX %u, ",
9247 path
->addpath_rx_id
);
9249 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9253 /* If we used addpath to TX a non-bestpath we need to display
9254 * "Advertised to" on a path-by-path basis
9256 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9259 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9261 bgp_addpath_encode_tx(peer
, afi
, safi
);
9262 has_adj
= bgp_adj_out_lookup(
9264 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9265 &path
->tx_addpath
));
9267 if ((addpath_capable
&& has_adj
)
9268 || (!addpath_capable
&& has_adj
9269 && CHECK_FLAG(path
->flags
,
9270 BGP_PATH_SELECTED
))) {
9271 if (json_path
&& !json_adv_to
)
9272 json_adv_to
= json_object_new_object();
9274 route_vty_out_advertised_to(
9276 " Advertised to:", json_adv_to
);
9282 json_object_object_add(
9283 json_path
, "advertisedTo", json_adv_to
);
9292 /* Line 9 display Uptime */
9293 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9295 json_last_update
= json_object_new_object();
9296 json_object_int_add(json_last_update
, "epoch", tbuf
);
9297 json_object_string_add(json_last_update
, "string",
9299 json_object_object_add(json_path
, "lastUpdate",
9302 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9304 /* Line 10 display PMSI tunnel attribute, if present */
9305 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9307 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9308 PMSI_TNLTYPE_STR_DEFAULT
);
9311 json_pmsi
= json_object_new_object();
9312 json_object_string_add(json_pmsi
, "tunnelType", str
);
9313 json_object_int_add(json_pmsi
, "label",
9314 label2vni(&attr
->label
));
9315 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9317 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9318 str
, label2vni(&attr
->label
));
9321 /* We've constructed the json object for this path, add it to the json
9325 if (json_nexthop_global
|| json_nexthop_ll
) {
9326 json_nexthops
= json_object_new_array();
9328 if (json_nexthop_global
)
9329 json_object_array_add(json_nexthops
,
9330 json_nexthop_global
);
9332 if (json_nexthop_ll
)
9333 json_object_array_add(json_nexthops
,
9336 json_object_object_add(json_path
, "nexthops",
9340 json_object_object_add(json_path
, "peer", json_peer
);
9341 json_object_array_add(json_paths
, json_path
);
9345 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9346 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9347 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9349 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9350 const char *prefix_list_str
, afi_t afi
,
9351 safi_t safi
, enum bgp_show_type type
);
9352 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9353 const char *filter
, afi_t afi
, safi_t safi
,
9354 enum bgp_show_type type
);
9355 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9356 const char *rmap_str
, afi_t afi
, safi_t safi
,
9357 enum bgp_show_type type
);
9358 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9359 const char *com
, int exact
, afi_t afi
,
9361 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9362 const char *prefix
, afi_t afi
, safi_t safi
,
9363 enum bgp_show_type type
);
9364 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9365 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9367 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9368 const char *comstr
, int exact
, afi_t afi
,
9369 safi_t safi
, bool use_json
);
9372 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9373 struct bgp_table
*table
, enum bgp_show_type type
,
9374 void *output_arg
, bool use_json
, char *rd
,
9375 int is_last
, unsigned long *output_cum
,
9376 unsigned long *total_cum
,
9377 unsigned long *json_header_depth
)
9379 struct bgp_path_info
*pi
;
9380 struct bgp_node
*rn
;
9383 unsigned long output_count
= 0;
9384 unsigned long total_count
= 0;
9387 json_object
*json_paths
= NULL
;
9390 if (output_cum
&& *output_cum
!= 0)
9393 if (use_json
&& !*json_header_depth
) {
9395 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9396 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9397 " \"localAS\": %u,\n \"routes\": { ",
9398 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9399 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9402 table
->version
, inet_ntoa(bgp
->router_id
),
9403 bgp
->default_local_pref
, bgp
->as
);
9404 *json_header_depth
= 2;
9406 vty_out(vty
, " \"routeDistinguishers\" : {");
9407 ++*json_header_depth
;
9411 if (use_json
&& rd
) {
9412 vty_out(vty
, " \"%s\" : { ", rd
);
9415 /* Start processing of routes. */
9416 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9417 pi
= bgp_node_get_bgp_path_info(rn
);
9423 json_paths
= json_object_new_array();
9427 for (; pi
; pi
= pi
->next
) {
9429 if (type
== bgp_show_type_flap_statistics
9430 || type
== bgp_show_type_flap_neighbor
9431 || type
== bgp_show_type_dampend_paths
9432 || type
== bgp_show_type_damp_neighbor
) {
9433 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9436 if (type
== bgp_show_type_regexp
) {
9437 regex_t
*regex
= output_arg
;
9439 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9443 if (type
== bgp_show_type_prefix_list
) {
9444 struct prefix_list
*plist
= output_arg
;
9446 if (prefix_list_apply(plist
, &rn
->p
)
9450 if (type
== bgp_show_type_filter_list
) {
9451 struct as_list
*as_list
= output_arg
;
9453 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9454 != AS_FILTER_PERMIT
)
9457 if (type
== bgp_show_type_route_map
) {
9458 struct route_map
*rmap
= output_arg
;
9459 struct bgp_path_info path
;
9460 struct attr dummy_attr
;
9461 route_map_result_t ret
;
9463 dummy_attr
= *pi
->attr
;
9465 path
.peer
= pi
->peer
;
9466 path
.attr
= &dummy_attr
;
9468 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9470 if (ret
== RMAP_DENYMATCH
)
9473 if (type
== bgp_show_type_neighbor
9474 || type
== bgp_show_type_flap_neighbor
9475 || type
== bgp_show_type_damp_neighbor
) {
9476 union sockunion
*su
= output_arg
;
9478 if (pi
->peer
== NULL
9479 || pi
->peer
->su_remote
== NULL
9480 || !sockunion_same(pi
->peer
->su_remote
, su
))
9483 if (type
== bgp_show_type_cidr_only
) {
9484 uint32_t destination
;
9486 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9487 if (IN_CLASSC(destination
)
9488 && rn
->p
.prefixlen
== 24)
9490 if (IN_CLASSB(destination
)
9491 && rn
->p
.prefixlen
== 16)
9493 if (IN_CLASSA(destination
)
9494 && rn
->p
.prefixlen
== 8)
9497 if (type
== bgp_show_type_prefix_longer
) {
9499 if (!prefix_match(p
, &rn
->p
))
9502 if (type
== bgp_show_type_community_all
) {
9503 if (!pi
->attr
->community
)
9506 if (type
== bgp_show_type_community
) {
9507 struct community
*com
= output_arg
;
9509 if (!pi
->attr
->community
9510 || !community_match(pi
->attr
->community
,
9514 if (type
== bgp_show_type_community_exact
) {
9515 struct community
*com
= output_arg
;
9517 if (!pi
->attr
->community
9518 || !community_cmp(pi
->attr
->community
, com
))
9521 if (type
== bgp_show_type_community_list
) {
9522 struct community_list
*list
= output_arg
;
9524 if (!community_list_match(pi
->attr
->community
,
9528 if (type
== bgp_show_type_community_list_exact
) {
9529 struct community_list
*list
= output_arg
;
9531 if (!community_list_exact_match(
9532 pi
->attr
->community
, list
))
9535 if (type
== bgp_show_type_lcommunity
) {
9536 struct lcommunity
*lcom
= output_arg
;
9538 if (!pi
->attr
->lcommunity
9539 || !lcommunity_match(pi
->attr
->lcommunity
,
9544 if (type
== bgp_show_type_lcommunity_exact
) {
9545 struct lcommunity
*lcom
= output_arg
;
9547 if (!pi
->attr
->lcommunity
9548 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9552 if (type
== bgp_show_type_lcommunity_list
) {
9553 struct community_list
*list
= output_arg
;
9555 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9560 == bgp_show_type_lcommunity_list_exact
) {
9561 struct community_list
*list
= output_arg
;
9563 if (!lcommunity_list_exact_match(
9564 pi
->attr
->lcommunity
, list
))
9567 if (type
== bgp_show_type_lcommunity_all
) {
9568 if (!pi
->attr
->lcommunity
)
9571 if (type
== bgp_show_type_dampend_paths
9572 || type
== bgp_show_type_damp_neighbor
) {
9573 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9574 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9578 if (!use_json
&& header
) {
9579 vty_out(vty
, "BGP table version is %" PRIu64
9580 ", local router ID is %s, vrf id ",
9582 inet_ntoa(bgp
->router_id
));
9583 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9584 vty_out(vty
, "%s", VRFID_NONE_STR
);
9586 vty_out(vty
, "%u", bgp
->vrf_id
);
9588 vty_out(vty
, "Default local pref %u, ",
9589 bgp
->default_local_pref
);
9590 vty_out(vty
, "local AS %u\n", bgp
->as
);
9591 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9592 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9593 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9594 if (type
== bgp_show_type_dampend_paths
9595 || type
== bgp_show_type_damp_neighbor
)
9596 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9597 else if (type
== bgp_show_type_flap_statistics
9598 || type
== bgp_show_type_flap_neighbor
)
9599 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9601 vty_out(vty
, BGP_SHOW_HEADER
);
9604 if (rd
!= NULL
&& !display
&& !output_count
) {
9607 "Route Distinguisher: %s\n",
9610 if (type
== bgp_show_type_dampend_paths
9611 || type
== bgp_show_type_damp_neighbor
)
9612 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9613 safi
, use_json
, json_paths
);
9614 else if (type
== bgp_show_type_flap_statistics
9615 || type
== bgp_show_type_flap_neighbor
)
9616 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9617 safi
, use_json
, json_paths
);
9619 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9631 if (p
->family
== AF_FLOWSPEC
) {
9632 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9634 bgp_fs_nlri_get_string((unsigned char *)
9635 p
->u
.prefix_flowspec
.ptr
,
9636 p
->u
.prefix_flowspec
9639 NLRI_STRING_FORMAT_MIN
,
9642 vty_out(vty
, "\"%s/%d\": ",
9644 p
->u
.prefix_flowspec
.prefixlen
);
9646 vty_out(vty
, ",\"%s/%d\": ",
9648 p
->u
.prefix_flowspec
.prefixlen
);
9650 prefix2str(p
, buf2
, sizeof(buf2
));
9652 vty_out(vty
, "\"%s\": ", buf2
);
9654 vty_out(vty
, ",\"%s\": ", buf2
);
9657 json_object_to_json_string_ext(
9658 json_paths
, JSON_C_TO_STRING_PRETTY
));
9659 json_object_free(json_paths
);
9663 json_object_free(json_paths
);
9667 output_count
+= *output_cum
;
9668 *output_cum
= output_count
;
9671 total_count
+= *total_cum
;
9672 *total_cum
= total_count
;
9676 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9680 for (i
= 0; i
< *json_header_depth
; ++i
)
9681 vty_out(vty
, " } ");
9686 /* No route is displayed */
9687 if (output_count
== 0) {
9688 if (type
== bgp_show_type_normal
)
9690 "No BGP prefixes displayed, %ld exist\n",
9694 "\nDisplayed %ld routes and %ld total paths\n",
9695 output_count
, total_count
);
9702 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9703 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9704 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9706 struct bgp_node
*rn
, *next
;
9707 unsigned long output_cum
= 0;
9708 unsigned long total_cum
= 0;
9709 unsigned long json_header_depth
= 0;
9710 struct bgp_table
*itable
;
9713 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9715 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9716 next
= bgp_route_next(rn
);
9717 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9720 itable
= bgp_node_get_bgp_table_info(rn
);
9721 if (itable
!= NULL
) {
9722 struct prefix_rd prd
;
9723 char rd
[RD_ADDRSTRLEN
];
9725 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9726 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9727 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9728 use_json
, rd
, next
== NULL
, &output_cum
,
9729 &total_cum
, &json_header_depth
);
9735 if (output_cum
== 0)
9736 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9740 "\nDisplayed %ld routes and %ld total paths\n",
9741 output_cum
, total_cum
);
9745 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9746 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9748 struct bgp_table
*table
;
9749 unsigned long json_header_depth
= 0;
9752 bgp
= bgp_get_default();
9757 vty_out(vty
, "No BGP process is configured\n");
9759 vty_out(vty
, "{}\n");
9763 table
= bgp
->rib
[afi
][safi
];
9764 /* use MPLS and ENCAP specific shows until they are merged */
9765 if (safi
== SAFI_MPLS_VPN
) {
9766 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9767 output_arg
, use_json
);
9770 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9771 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9772 output_arg
, use_json
,
9775 /* labeled-unicast routes live in the unicast table */
9776 else if (safi
== SAFI_LABELED_UNICAST
)
9777 safi
= SAFI_UNICAST
;
9779 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9780 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9783 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9784 safi_t safi
, bool use_json
)
9786 struct listnode
*node
, *nnode
;
9789 bool route_output
= false;
9792 vty_out(vty
, "{\n");
9794 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9795 route_output
= true;
9798 vty_out(vty
, ",\n");
9802 vty_out(vty
, "\"%s\":",
9803 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9807 vty_out(vty
, "\nInstance %s:\n",
9808 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9812 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9817 vty_out(vty
, "}\n");
9818 else if (!route_output
)
9819 vty_out(vty
, "%% BGP instance not found\n");
9822 /* Header of detailed BGP route information */
9823 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9824 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9825 afi_t afi
, safi_t safi
, json_object
*json
)
9827 struct bgp_path_info
*pi
;
9830 struct listnode
*node
, *nnode
;
9831 char buf1
[RD_ADDRSTRLEN
];
9832 char buf2
[INET6_ADDRSTRLEN
];
9833 char buf3
[EVPN_ROUTE_STRLEN
];
9834 char prefix_str
[BUFSIZ
];
9839 int route_filter_translated_v4
= 0;
9840 int route_filter_v4
= 0;
9841 int route_filter_translated_v6
= 0;
9842 int route_filter_v6
= 0;
9845 int accept_own_nexthop
= 0;
9848 int no_advertise
= 0;
9852 int has_valid_label
= 0;
9853 mpls_label_t label
= 0;
9854 json_object
*json_adv_to
= NULL
;
9857 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9859 if (has_valid_label
)
9860 label
= label_pton(&rn
->local_label
);
9862 if (safi
== SAFI_EVPN
) {
9865 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9866 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9867 : "", prd
? ":" : "",
9868 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9869 buf3
, sizeof(buf3
)));
9871 json_object_string_add(json
, "rd",
9872 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9874 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9878 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9879 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9880 ? prefix_rd2str(prd
, buf1
,
9883 safi
== SAFI_MPLS_VPN
? ":" : "",
9884 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9889 json_object_string_add(json
, "prefix",
9890 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9893 if (has_valid_label
) {
9895 json_object_int_add(json
, "localLabel", label
);
9897 vty_out(vty
, "Local label: %d\n", label
);
9901 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9902 vty_out(vty
, "not allocated\n");
9904 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9906 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9908 if (pi
->extra
&& pi
->extra
->suppress
)
9911 if (pi
->attr
->community
== NULL
)
9914 no_advertise
+= community_include(
9915 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9916 no_export
+= community_include(pi
->attr
->community
,
9917 COMMUNITY_NO_EXPORT
);
9918 local_as
+= community_include(pi
->attr
->community
,
9919 COMMUNITY_LOCAL_AS
);
9920 accept_own
+= community_include(pi
->attr
->community
,
9921 COMMUNITY_ACCEPT_OWN
);
9922 route_filter_translated_v4
+= community_include(
9923 pi
->attr
->community
,
9924 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9925 route_filter_translated_v6
+= community_include(
9926 pi
->attr
->community
,
9927 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9928 route_filter_v4
+= community_include(
9929 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9930 route_filter_v6
+= community_include(
9931 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9932 llgr_stale
+= community_include(pi
->attr
->community
,
9933 COMMUNITY_LLGR_STALE
);
9934 no_llgr
+= community_include(pi
->attr
->community
,
9936 accept_own_nexthop
+=
9937 community_include(pi
->attr
->community
,
9938 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9939 blackhole
+= community_include(pi
->attr
->community
,
9940 COMMUNITY_BLACKHOLE
);
9941 no_peer
+= community_include(pi
->attr
->community
,
9947 vty_out(vty
, "Paths: (%d available", count
);
9949 vty_out(vty
, ", best #%d", best
);
9950 if (safi
== SAFI_UNICAST
) {
9951 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9952 vty_out(vty
, ", table %s",
9955 vty_out(vty
, ", vrf %s",
9959 vty_out(vty
, ", no best path");
9963 ", accept own local route exported and imported in different VRF");
9964 else if (route_filter_translated_v4
)
9966 ", mark translated RTs for VPNv4 route filtering");
9967 else if (route_filter_v4
)
9969 ", attach RT as-is for VPNv4 route filtering");
9970 else if (route_filter_translated_v6
)
9972 ", mark translated RTs for VPNv6 route filtering");
9973 else if (route_filter_v6
)
9975 ", attach RT as-is for VPNv6 route filtering");
9976 else if (llgr_stale
)
9978 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9981 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9982 else if (accept_own_nexthop
)
9984 ", accept local nexthop");
9986 vty_out(vty
, ", inform peer to blackhole prefix");
9988 vty_out(vty
, ", not advertised to EBGP peer");
9989 else if (no_advertise
)
9990 vty_out(vty
, ", not advertised to any peer");
9992 vty_out(vty
, ", not advertised outside local AS");
9995 ", inform EBGP peer not to advertise to their EBGP peers");
9999 ", Advertisements suppressed by an aggregate.");
10000 vty_out(vty
, ")\n");
10003 /* If we are not using addpath then we can display Advertised to and
10005 * show what peers we advertised the bestpath to. If we are using
10007 * though then we must display Advertised to on a path-by-path basis. */
10008 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10009 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10010 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
10011 if (json
&& !json_adv_to
)
10012 json_adv_to
= json_object_new_object();
10014 route_vty_out_advertised_to(
10016 " Advertised to non peer-group peers:\n ",
10023 json_object_object_add(json
, "advertisedTo",
10028 vty_out(vty
, " Not advertised to any peer");
10029 vty_out(vty
, "\n");
10034 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10035 struct bgp_node
*bgp_node
, struct vty
*vty
,
10036 struct bgp
*bgp
, afi_t afi
,
10037 safi_t safi
, json_object
*json
,
10038 enum bgp_path_type pathtype
, int *display
)
10040 struct bgp_path_info
*pi
;
10042 char rdbuf
[RD_ADDRSTRLEN
];
10043 json_object
*json_header
= NULL
;
10044 json_object
*json_paths
= NULL
;
10046 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
10049 if (json
&& !json_paths
) {
10050 /* Instantiate json_paths only if path is valid */
10051 json_paths
= json_object_new_array();
10053 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10054 json_header
= json_object_new_object();
10056 json_header
= json
;
10060 route_vty_out_detail_header(
10061 vty
, bgp
, bgp_node
, pfx_rd
,
10062 AFI_IP
, safi
, json_header
);
10067 if (pathtype
== BGP_PATH_SHOW_ALL
10068 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10069 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10070 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10071 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10072 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10073 route_vty_out_detail(vty
, bgp
, bgp_node
,
10078 if (json
&& json_paths
) {
10079 json_object_object_add(json_header
, "paths", json_paths
);
10082 json_object_object_add(json
, rdbuf
, json_header
);
10086 /* Display specified route of BGP table. */
10087 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10088 struct bgp_table
*rib
, const char *ip_str
,
10089 afi_t afi
, safi_t safi
,
10090 struct prefix_rd
*prd
, int prefix_check
,
10091 enum bgp_path_type pathtype
, bool use_json
)
10095 struct prefix match
;
10096 struct bgp_node
*rn
;
10097 struct bgp_node
*rm
;
10098 struct bgp_table
*table
;
10099 json_object
*json
= NULL
;
10100 json_object
*json_paths
= NULL
;
10102 /* Check IP address argument. */
10103 ret
= str2prefix(ip_str
, &match
);
10105 vty_out(vty
, "address is malformed\n");
10106 return CMD_WARNING
;
10109 match
.family
= afi2family(afi
);
10112 json
= json_object_new_object();
10114 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10115 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10116 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10118 table
= bgp_node_get_bgp_table_info(rn
);
10122 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10126 && rm
->p
.prefixlen
!= match
.prefixlen
) {
10127 bgp_unlock_node(rm
);
10131 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10132 vty
, bgp
, afi
, safi
, json
,
10133 pathtype
, &display
);
10135 bgp_unlock_node(rm
);
10137 } else if (safi
== SAFI_EVPN
) {
10138 struct bgp_node
*longest_pfx
;
10139 bool is_exact_pfxlen_match
= FALSE
;
10141 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10142 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10144 table
= bgp_node_get_bgp_table_info(rn
);
10148 longest_pfx
= NULL
;
10149 is_exact_pfxlen_match
= FALSE
;
10151 * Search through all the prefixes for a match. The
10152 * pfx's are enumerated in ascending order of pfxlens.
10153 * So, the last pfx match is the longest match. Set
10154 * is_exact_pfxlen_match when we get exact pfxlen match
10156 for (rm
= bgp_table_top(table
); rm
;
10157 rm
= bgp_route_next(rm
)) {
10159 * Get prefixlen of the ip-prefix within type5
10162 if (evpn_type5_prefix_match(&rm
->p
,
10163 &match
) && rm
->info
) {
10166 bgp_evpn_get_type5_prefixlen(&rm
->p
);
10167 if (type5_pfxlen
== match
.prefixlen
) {
10168 is_exact_pfxlen_match
= TRUE
;
10169 bgp_unlock_node(rm
);
10178 if (prefix_check
&& !is_exact_pfxlen_match
)
10184 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10185 vty
, bgp
, afi
, safi
, json
,
10186 pathtype
, &display
);
10188 bgp_unlock_node(rm
);
10190 } else if (safi
== SAFI_FLOWSPEC
) {
10192 json_paths
= json_object_new_array();
10194 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10195 &match
, prefix_check
,
10199 if (use_json
&& display
)
10200 json_object_object_add(json
, "paths", json_paths
);
10202 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
10204 || rn
->p
.prefixlen
== match
.prefixlen
) {
10205 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
10207 pathtype
, &display
);
10210 bgp_unlock_node(rn
);
10215 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10216 json
, JSON_C_TO_STRING_PRETTY
|
10217 JSON_C_TO_STRING_NOSLASHESCAPE
));
10218 json_object_free(json
);
10221 vty_out(vty
, "%% Network not in table\n");
10222 return CMD_WARNING
;
10226 return CMD_SUCCESS
;
10229 /* Display specified route of Main RIB */
10230 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10231 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10232 int prefix_check
, enum bgp_path_type pathtype
,
10236 bgp
= bgp_get_default();
10239 vty_out(vty
, "No BGP process is configured\n");
10241 vty_out(vty
, "{}\n");
10242 return CMD_WARNING
;
10246 /* labeled-unicast routes live in the unicast table */
10247 if (safi
== SAFI_LABELED_UNICAST
)
10248 safi
= SAFI_UNICAST
;
10250 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10251 afi
, safi
, prd
, prefix_check
, pathtype
,
10255 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10256 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10257 safi_t safi
, bool uj
)
10259 struct lcommunity
*lcom
;
10265 b
= buffer_new(1024);
10266 for (i
= 0; i
< argc
; i
++) {
10268 buffer_putc(b
, ' ');
10270 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10272 buffer_putstr(b
, argv
[i
]->arg
);
10276 buffer_putc(b
, '\0');
10278 str
= buffer_getstr(b
);
10281 lcom
= lcommunity_str2com(str
);
10282 XFREE(MTYPE_TMP
, str
);
10284 vty_out(vty
, "%% Large-community malformed\n");
10285 return CMD_WARNING
;
10288 return bgp_show(vty
, bgp
, afi
, safi
,
10289 (exact
? bgp_show_type_lcommunity_exact
10290 : bgp_show_type_lcommunity
),
10294 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10295 const char *lcom
, bool exact
, afi_t afi
,
10296 safi_t safi
, bool uj
)
10298 struct community_list
*list
;
10300 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10301 LARGE_COMMUNITY_LIST_MASTER
);
10302 if (list
== NULL
) {
10303 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10305 return CMD_WARNING
;
10308 return bgp_show(vty
, bgp
, afi
, safi
,
10309 (exact
? bgp_show_type_lcommunity_list_exact
10310 : bgp_show_type_lcommunity_list
),
10314 DEFUN (show_ip_bgp_large_community_list
,
10315 show_ip_bgp_large_community_list_cmd
,
10316 "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]",
10320 BGP_INSTANCE_HELP_STR
10322 BGP_SAFI_WITH_LABEL_HELP_STR
10323 "Display routes matching the large-community-list\n"
10324 "large-community-list number\n"
10325 "large-community-list name\n"
10326 "Exact match of the large-communities\n"
10330 afi_t afi
= AFI_IP6
;
10331 safi_t safi
= SAFI_UNICAST
;
10333 bool exact_match
= 0;
10335 if (argv_find(argv
, argc
, "ip", &idx
))
10337 if (argv_find(argv
, argc
, "view", &idx
)
10338 || argv_find(argv
, argc
, "vrf", &idx
))
10339 vrf
= argv
[++idx
]->arg
;
10340 if (argv_find(argv
, argc
, "ipv4", &idx
)
10341 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10342 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10343 if (argv_find(argv
, argc
, "unicast", &idx
)
10344 || argv_find(argv
, argc
, "multicast", &idx
))
10345 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10348 bool uj
= use_json(argc
, argv
);
10350 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10352 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10353 return CMD_WARNING
;
10356 argv_find(argv
, argc
, "large-community-list", &idx
);
10358 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10360 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10363 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10364 exact_match
, afi
, safi
, uj
);
10366 DEFUN (show_ip_bgp_large_community
,
10367 show_ip_bgp_large_community_cmd
,
10368 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10372 BGP_INSTANCE_HELP_STR
10374 BGP_SAFI_WITH_LABEL_HELP_STR
10375 "Display routes matching the large-communities\n"
10376 "List of large-community numbers\n"
10377 "Exact match of the large-communities\n"
10381 afi_t afi
= AFI_IP6
;
10382 safi_t safi
= SAFI_UNICAST
;
10384 bool exact_match
= 0;
10386 if (argv_find(argv
, argc
, "ip", &idx
))
10388 if (argv_find(argv
, argc
, "view", &idx
)
10389 || argv_find(argv
, argc
, "vrf", &idx
))
10390 vrf
= argv
[++idx
]->arg
;
10391 if (argv_find(argv
, argc
, "ipv4", &idx
)
10392 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10393 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10394 if (argv_find(argv
, argc
, "unicast", &idx
)
10395 || argv_find(argv
, argc
, "multicast", &idx
))
10396 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10399 bool uj
= use_json(argc
, argv
);
10401 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10403 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10404 return CMD_WARNING
;
10407 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10408 if (argv_find(argv
, argc
, "exact-match", &idx
))
10410 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10411 exact_match
, afi
, safi
, uj
);
10413 return bgp_show(vty
, bgp
, afi
, safi
,
10414 bgp_show_type_lcommunity_all
, NULL
, uj
);
10417 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10421 /* BGP route print out function without JSON */
10422 DEFUN (show_ip_bgp
,
10424 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10425 <dampening <parameters>\
10430 |community-list <(1-500)|WORD> [exact-match]\
10431 |A.B.C.D/M longer-prefixes\
10432 |X:X::X:X/M longer-prefixes\
10437 BGP_INSTANCE_HELP_STR
10439 BGP_SAFI_WITH_LABEL_HELP_STR
10440 "Display detailed information about dampening\n"
10441 "Display detail of configured dampening parameters\n"
10442 "Display routes matching the route-map\n"
10443 "A route-map to match on\n"
10444 "Display routes conforming to the prefix-list\n"
10445 "Prefix-list name\n"
10446 "Display routes conforming to the filter-list\n"
10447 "Regular expression access list name\n"
10448 "BGP RIB advertisement statistics\n"
10449 "Display routes matching the community-list\n"
10450 "community-list number\n"
10451 "community-list name\n"
10452 "Exact match of the communities\n"
10454 "Display route and more specific routes\n"
10456 "Display route and more specific routes\n")
10458 afi_t afi
= AFI_IP6
;
10459 safi_t safi
= SAFI_UNICAST
;
10460 int exact_match
= 0;
10461 struct bgp
*bgp
= NULL
;
10464 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10467 return CMD_WARNING
;
10469 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10470 if (argv_find(argv
, argc
, "parameters", &idx
))
10471 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10474 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10475 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10476 safi
, bgp_show_type_prefix_list
);
10478 if (argv_find(argv
, argc
, "filter-list", &idx
))
10479 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10480 safi
, bgp_show_type_filter_list
);
10482 if (argv_find(argv
, argc
, "statistics", &idx
))
10483 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10485 if (argv_find(argv
, argc
, "route-map", &idx
))
10486 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10487 safi
, bgp_show_type_route_map
);
10489 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10490 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10491 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10493 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10494 exact_match
, afi
, safi
);
10496 /* prefix-longer */
10497 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10498 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10499 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10501 bgp_show_type_prefix_longer
);
10503 return CMD_WARNING
;
10506 /* BGP route print out function with JSON */
10507 DEFUN (show_ip_bgp_json
,
10508 show_ip_bgp_json_cmd
,
10509 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10511 |dampening <flap-statistics|dampened-paths>\
10512 |community [AA:NN|local-AS|no-advertise|no-export\
10513 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10514 |accept-own|accept-own-nexthop|route-filter-v6\
10515 |route-filter-v4|route-filter-translated-v6\
10516 |route-filter-translated-v4] [exact-match]\
10521 BGP_INSTANCE_HELP_STR
10523 BGP_SAFI_WITH_LABEL_HELP_STR
10524 "Display only routes with non-natural netmasks\n"
10525 "Display detailed information about dampening\n"
10526 "Display flap statistics of routes\n"
10527 "Display paths suppressed due to dampening\n"
10528 "Display routes matching the communities\n"
10530 "Do not send outside local AS (well-known community)\n"
10531 "Do not advertise to any peer (well-known community)\n"
10532 "Do not export to next AS (well-known community)\n"
10533 "Graceful shutdown (well-known community)\n"
10534 "Do not export to any peer (well-known community)\n"
10535 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10536 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10537 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10538 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10539 "Should accept VPN route with local nexthop (well-known community)\n"
10540 "RT VPNv6 route filtering (well-known community)\n"
10541 "RT VPNv4 route filtering (well-known community)\n"
10542 "RT translated VPNv6 route filtering (well-known community)\n"
10543 "RT translated VPNv4 route filtering (well-known community)\n"
10544 "Exact match of the communities\n"
10547 afi_t afi
= AFI_IP6
;
10548 safi_t safi
= SAFI_UNICAST
;
10549 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10550 struct bgp
*bgp
= NULL
;
10552 int exact_match
= 0;
10553 bool uj
= use_json(argc
, argv
);
10558 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10561 return CMD_WARNING
;
10563 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10564 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10567 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10568 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10569 return bgp_show(vty
, bgp
, afi
, safi
,
10570 bgp_show_type_dampend_paths
, NULL
, uj
);
10571 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10572 return bgp_show(vty
, bgp
, afi
, safi
,
10573 bgp_show_type_flap_statistics
, NULL
,
10577 if (argv_find(argv
, argc
, "community", &idx
)) {
10578 char *maybecomm
= NULL
;
10579 char *community
= NULL
;
10581 if (idx
+ 1 < argc
) {
10582 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10583 maybecomm
= argv
[idx
+ 1]->arg
;
10585 maybecomm
= argv
[idx
+ 1]->text
;
10588 if (maybecomm
&& !strmatch(maybecomm
, "json")
10589 && !strmatch(maybecomm
, "exact-match"))
10590 community
= maybecomm
;
10592 if (argv_find(argv
, argc
, "exact-match", &idx
))
10596 return bgp_show_community(vty
, bgp
, community
,
10597 exact_match
, afi
, safi
, uj
);
10599 return (bgp_show(vty
, bgp
, afi
, safi
,
10600 bgp_show_type_community_all
, NULL
,
10604 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10607 DEFUN (show_ip_bgp_route
,
10608 show_ip_bgp_route_cmd
,
10609 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10610 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10614 BGP_INSTANCE_HELP_STR
10616 BGP_SAFI_WITH_LABEL_HELP_STR
10617 "Network in the BGP routing table to display\n"
10619 "Network in the BGP routing table to display\n"
10621 "Display only the bestpath\n"
10622 "Display only multipaths\n"
10625 int prefix_check
= 0;
10627 afi_t afi
= AFI_IP6
;
10628 safi_t safi
= SAFI_UNICAST
;
10629 char *prefix
= NULL
;
10630 struct bgp
*bgp
= NULL
;
10631 enum bgp_path_type path_type
;
10632 bool uj
= use_json(argc
, argv
);
10636 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10639 return CMD_WARNING
;
10643 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10644 return CMD_WARNING
;
10647 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10648 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10649 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10651 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10652 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10655 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10656 && afi
!= AFI_IP6
) {
10658 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10659 return CMD_WARNING
;
10661 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10662 && afi
!= AFI_IP
) {
10664 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10665 return CMD_WARNING
;
10668 prefix
= argv
[idx
]->arg
;
10670 /* [<bestpath|multipath>] */
10671 if (argv_find(argv
, argc
, "bestpath", &idx
))
10672 path_type
= BGP_PATH_SHOW_BESTPATH
;
10673 else if (argv_find(argv
, argc
, "multipath", &idx
))
10674 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10676 path_type
= BGP_PATH_SHOW_ALL
;
10678 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10682 DEFUN (show_ip_bgp_regexp
,
10683 show_ip_bgp_regexp_cmd
,
10684 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10688 BGP_INSTANCE_HELP_STR
10690 BGP_SAFI_WITH_LABEL_HELP_STR
10691 "Display routes matching the AS path regular expression\n"
10692 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10695 afi_t afi
= AFI_IP6
;
10696 safi_t safi
= SAFI_UNICAST
;
10697 struct bgp
*bgp
= NULL
;
10698 bool uj
= use_json(argc
, argv
);
10699 char *regstr
= NULL
;
10702 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10705 return CMD_WARNING
;
10707 // get index of regex
10708 if (argv_find(argv
, argc
, "REGEX", &idx
))
10709 regstr
= argv
[idx
]->arg
;
10712 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10713 bgp_show_type_regexp
, uj
);
10716 DEFUN (show_ip_bgp_instance_all
,
10717 show_ip_bgp_instance_all_cmd
,
10718 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10722 BGP_INSTANCE_ALL_HELP_STR
10724 BGP_SAFI_WITH_LABEL_HELP_STR
10727 afi_t afi
= AFI_IP
;
10728 safi_t safi
= SAFI_UNICAST
;
10729 struct bgp
*bgp
= NULL
;
10731 bool uj
= use_json(argc
, argv
);
10736 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10739 return CMD_WARNING
;
10741 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10742 return CMD_SUCCESS
;
10745 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10746 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10752 if (!config_bgp_aspath_validate(regstr
)) {
10753 vty_out(vty
, "Invalid character in REGEX %s\n",
10755 return CMD_WARNING_CONFIG_FAILED
;
10758 regex
= bgp_regcomp(regstr
);
10760 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10761 return CMD_WARNING
;
10764 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
10765 bgp_regex_free(regex
);
10769 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10770 const char *prefix_list_str
, afi_t afi
,
10771 safi_t safi
, enum bgp_show_type type
)
10773 struct prefix_list
*plist
;
10775 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10776 if (plist
== NULL
) {
10777 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10779 return CMD_WARNING
;
10782 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10785 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10786 const char *filter
, afi_t afi
, safi_t safi
,
10787 enum bgp_show_type type
)
10789 struct as_list
*as_list
;
10791 as_list
= as_list_lookup(filter
);
10792 if (as_list
== NULL
) {
10793 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10795 return CMD_WARNING
;
10798 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10801 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10802 const char *rmap_str
, afi_t afi
, safi_t safi
,
10803 enum bgp_show_type type
)
10805 struct route_map
*rmap
;
10807 rmap
= route_map_lookup_by_name(rmap_str
);
10809 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10810 return CMD_WARNING
;
10813 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10816 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10817 const char *comstr
, int exact
, afi_t afi
,
10818 safi_t safi
, bool use_json
)
10820 struct community
*com
;
10823 com
= community_str2com(comstr
);
10825 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10826 return CMD_WARNING
;
10829 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10830 (exact
? bgp_show_type_community_exact
10831 : bgp_show_type_community
),
10833 community_free(&com
);
10838 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10839 const char *com
, int exact
, afi_t afi
,
10842 struct community_list
*list
;
10844 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10845 if (list
== NULL
) {
10846 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10847 return CMD_WARNING
;
10850 return bgp_show(vty
, bgp
, afi
, safi
,
10851 (exact
? bgp_show_type_community_list_exact
10852 : bgp_show_type_community_list
),
10856 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10857 const char *prefix
, afi_t afi
, safi_t safi
,
10858 enum bgp_show_type type
)
10865 ret
= str2prefix(prefix
, p
);
10867 vty_out(vty
, "%% Malformed Prefix\n");
10868 return CMD_WARNING
;
10871 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10877 BGP_STATS_MAXBITLEN
= 0,
10879 BGP_STATS_PREFIXES
,
10881 BGP_STATS_UNAGGREGATEABLE
,
10882 BGP_STATS_MAX_AGGREGATEABLE
,
10883 BGP_STATS_AGGREGATES
,
10885 BGP_STATS_ASPATH_COUNT
,
10886 BGP_STATS_ASPATH_MAXHOPS
,
10887 BGP_STATS_ASPATH_TOTHOPS
,
10888 BGP_STATS_ASPATH_MAXSIZE
,
10889 BGP_STATS_ASPATH_TOTSIZE
,
10890 BGP_STATS_ASN_HIGHEST
,
10894 static const char *const table_stats_strs
[] = {
10895 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10896 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10897 [BGP_STATS_RIB
] = "Total Advertisements",
10898 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10899 [BGP_STATS_MAX_AGGREGATEABLE
] =
10900 "Maximum aggregateable prefixes",
10901 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10902 [BGP_STATS_SPACE
] = "Address space advertised",
10903 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10904 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10905 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10906 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10907 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10908 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10909 [BGP_STATS_MAX
] = NULL
,
10912 struct bgp_table_stats
{
10913 struct bgp_table
*table
;
10914 unsigned long long counts
[BGP_STATS_MAX
];
10915 double total_space
;
10919 #define TALLY_SIGFIG 100000
10920 static unsigned long
10921 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10923 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10924 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10925 unsigned long ret
= newtot
/ count
;
10927 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10934 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10935 struct bgp_table_stats
*ts
, unsigned int space
)
10937 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10938 struct bgp_path_info
*pi
;
10943 if (!bgp_node_has_bgp_path_info_data(rn
))
10946 ts
->counts
[BGP_STATS_PREFIXES
]++;
10947 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10950 ts
->counts
[BGP_STATS_AVGPLEN
]
10951 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10952 ts
->counts
[BGP_STATS_AVGPLEN
],
10956 /* check if the prefix is included by any other announcements */
10957 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10958 prn
= bgp_node_parent_nolock(prn
);
10960 if (prn
== NULL
|| prn
== top
) {
10961 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10962 /* announced address space */
10964 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10965 } else if (bgp_node_has_bgp_path_info_data(prn
))
10966 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10969 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10970 ts
->counts
[BGP_STATS_RIB
]++;
10972 if (CHECK_FLAG(pi
->attr
->flag
,
10973 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10974 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10976 /* as-path stats */
10977 if (pi
->attr
->aspath
) {
10978 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10979 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10980 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10982 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10984 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10985 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10987 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10988 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10990 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10991 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10993 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10994 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10995 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10997 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10998 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10999 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11002 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11003 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11008 static int bgp_table_stats_walker(struct thread
*t
)
11010 struct bgp_node
*rn
, *nrn
;
11011 struct bgp_node
*top
;
11012 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11013 unsigned int space
= 0;
11015 if (!(top
= bgp_table_top(ts
->table
)))
11018 switch (ts
->table
->afi
) {
11020 space
= IPV4_MAX_BITLEN
;
11023 space
= IPV6_MAX_BITLEN
;
11029 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11031 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
11032 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
11033 struct bgp_table
*table
;
11035 table
= bgp_node_get_bgp_table_info(rn
);
11039 top
= bgp_table_top(table
);
11040 for (nrn
= bgp_table_top(table
); nrn
;
11041 nrn
= bgp_route_next(nrn
))
11042 bgp_table_stats_rn(nrn
, top
, ts
, space
);
11044 bgp_table_stats_rn(rn
, top
, ts
, space
);
11051 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11054 struct bgp_table_stats ts
;
11057 if (!bgp
->rib
[afi
][safi
]) {
11058 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11060 return CMD_WARNING
;
11063 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
11065 /* labeled-unicast routes live in the unicast table */
11066 if (safi
== SAFI_LABELED_UNICAST
)
11067 safi
= SAFI_UNICAST
;
11069 memset(&ts
, 0, sizeof(ts
));
11070 ts
.table
= bgp
->rib
[afi
][safi
];
11071 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11073 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11074 if (!table_stats_strs
[i
])
11079 case BGP_STATS_ASPATH_AVGHOPS
:
11080 case BGP_STATS_ASPATH_AVGSIZE
:
11081 case BGP_STATS_AVGPLEN
:
11082 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11083 vty_out (vty
, "%12.2f",
11084 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11087 case BGP_STATS_ASPATH_TOTHOPS
:
11088 case BGP_STATS_ASPATH_TOTSIZE
:
11089 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11090 vty_out(vty
, "%12.2f",
11092 ? (float)ts
.counts
[i
]
11094 [BGP_STATS_ASPATH_COUNT
]
11097 case BGP_STATS_TOTPLEN
:
11098 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11099 vty_out(vty
, "%12.2f",
11101 ? (float)ts
.counts
[i
]
11103 [BGP_STATS_PREFIXES
]
11106 case BGP_STATS_SPACE
:
11107 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11108 vty_out(vty
, "%12g\n", ts
.total_space
);
11110 if (afi
== AFI_IP6
) {
11111 vty_out(vty
, "%30s: ", "/32 equivalent ");
11112 vty_out(vty
, "%12g\n",
11113 ts
.total_space
* pow(2.0, -128 + 32));
11114 vty_out(vty
, "%30s: ", "/48 equivalent ");
11115 vty_out(vty
, "%12g\n",
11116 ts
.total_space
* pow(2.0, -128 + 48));
11118 vty_out(vty
, "%30s: ", "% announced ");
11119 vty_out(vty
, "%12.2f\n",
11120 ts
.total_space
* 100. * pow(2.0, -32));
11121 vty_out(vty
, "%30s: ", "/8 equivalent ");
11122 vty_out(vty
, "%12.2f\n",
11123 ts
.total_space
* pow(2.0, -32 + 8));
11124 vty_out(vty
, "%30s: ", "/24 equivalent ");
11125 vty_out(vty
, "%12.2f\n",
11126 ts
.total_space
* pow(2.0, -32 + 24));
11130 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11131 vty_out(vty
, "%12llu", ts
.counts
[i
]);
11134 vty_out(vty
, "\n");
11136 return CMD_SUCCESS
;
11148 PCOUNT_PFCNT
, /* the figure we display to users */
11152 static const char *const pcount_strs
[] = {
11153 [PCOUNT_ADJ_IN
] = "Adj-in",
11154 [PCOUNT_DAMPED
] = "Damped",
11155 [PCOUNT_REMOVED
] = "Removed",
11156 [PCOUNT_HISTORY
] = "History",
11157 [PCOUNT_STALE
] = "Stale",
11158 [PCOUNT_VALID
] = "Valid",
11159 [PCOUNT_ALL
] = "All RIB",
11160 [PCOUNT_COUNTED
] = "PfxCt counted",
11161 [PCOUNT_PFCNT
] = "Useable",
11162 [PCOUNT_MAX
] = NULL
,
11165 struct peer_pcounts
{
11166 unsigned int count
[PCOUNT_MAX
];
11167 const struct peer
*peer
;
11168 const struct bgp_table
*table
;
11172 static void bgp_peer_count_proc(struct bgp_node
*rn
,
11173 struct peer_pcounts
*pc
)
11175 const struct bgp_adj_in
*ain
;
11176 const struct bgp_path_info
*pi
;
11177 const struct peer
*peer
= pc
->peer
;
11179 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11180 if (ain
->peer
== peer
)
11181 pc
->count
[PCOUNT_ADJ_IN
]++;
11183 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11185 if (pi
->peer
!= peer
)
11188 pc
->count
[PCOUNT_ALL
]++;
11190 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11191 pc
->count
[PCOUNT_DAMPED
]++;
11192 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11193 pc
->count
[PCOUNT_HISTORY
]++;
11194 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11195 pc
->count
[PCOUNT_REMOVED
]++;
11196 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11197 pc
->count
[PCOUNT_STALE
]++;
11198 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11199 pc
->count
[PCOUNT_VALID
]++;
11200 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11201 pc
->count
[PCOUNT_PFCNT
]++;
11203 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11204 pc
->count
[PCOUNT_COUNTED
]++;
11205 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11207 EC_LIB_DEVELOPMENT
,
11208 "Attempting to count but flags say it is unusable");
11210 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11212 EC_LIB_DEVELOPMENT
,
11213 "Not counted but flags say we should");
11218 static int bgp_peer_count_walker(struct thread
*t
)
11220 struct bgp_node
*rn
, *rm
;
11221 const struct bgp_table
*table
;
11222 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11224 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11225 || pc
->safi
== SAFI_EVPN
) {
11226 /* Special handling for 2-level routing tables. */
11227 for (rn
= bgp_table_top(pc
->table
); rn
;
11228 rn
= bgp_route_next(rn
)) {
11229 table
= bgp_node_get_bgp_table_info(rn
);
11231 for (rm
= bgp_table_top(table
); rm
;
11232 rm
= bgp_route_next(rm
))
11233 bgp_peer_count_proc(rm
, pc
);
11236 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11237 bgp_peer_count_proc(rn
, pc
);
11242 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11243 safi_t safi
, bool use_json
)
11245 struct peer_pcounts pcounts
= {.peer
= peer
};
11247 json_object
*json
= NULL
;
11248 json_object
*json_loop
= NULL
;
11251 json
= json_object_new_object();
11252 json_loop
= json_object_new_object();
11255 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11256 || !peer
->bgp
->rib
[afi
][safi
]) {
11258 json_object_string_add(
11260 "No such neighbor or address family");
11261 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11262 json_object_free(json
);
11264 vty_out(vty
, "%% No such neighbor or address family\n");
11266 return CMD_WARNING
;
11269 memset(&pcounts
, 0, sizeof(pcounts
));
11270 pcounts
.peer
= peer
;
11271 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11272 pcounts
.safi
= safi
;
11274 /* in-place call via thread subsystem so as to record execution time
11275 * stats for the thread-walk (i.e. ensure this can't be blamed on
11276 * on just vty_read()).
11278 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11281 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11282 json_object_string_add(json
, "multiProtocol",
11283 get_afi_safi_str(afi
, safi
, true));
11284 json_object_int_add(json
, "pfxCounter",
11285 peer
->pcount
[afi
][safi
]);
11287 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11288 json_object_int_add(json_loop
, pcount_strs
[i
],
11291 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11293 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11294 json_object_string_add(json
, "pfxctDriftFor",
11296 json_object_string_add(
11297 json
, "recommended",
11298 "Please report this bug, with the above command output");
11300 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11301 json
, JSON_C_TO_STRING_PRETTY
));
11302 json_object_free(json
);
11306 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11307 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11308 peer
->hostname
, peer
->host
,
11309 get_afi_safi_str(afi
, safi
, false));
11311 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11312 get_afi_safi_str(afi
, safi
, false));
11315 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11316 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11318 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11319 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11322 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11323 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11325 "Please report this bug, with the above command output\n");
11329 return CMD_SUCCESS
;
11332 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11333 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11334 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11335 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11339 BGP_INSTANCE_HELP_STR
11342 "Detailed information on TCP and BGP neighbor connections\n"
11343 "Neighbor to display information about\n"
11344 "Neighbor to display information about\n"
11345 "Neighbor on BGP configured interface\n"
11346 "Display detailed prefix count information\n"
11349 afi_t afi
= AFI_IP6
;
11350 safi_t safi
= SAFI_UNICAST
;
11353 struct bgp
*bgp
= NULL
;
11354 bool uj
= use_json(argc
, argv
);
11359 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11362 return CMD_WARNING
;
11364 argv_find(argv
, argc
, "neighbors", &idx
);
11365 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11367 return CMD_WARNING
;
11369 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11372 #ifdef KEEP_OLD_VPN_COMMANDS
11373 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11374 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11375 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11380 "Display information about all VPNv4 NLRIs\n"
11381 "Detailed information on TCP and BGP neighbor connections\n"
11382 "Neighbor to display information about\n"
11383 "Neighbor to display information about\n"
11384 "Neighbor on BGP configured interface\n"
11385 "Display detailed prefix count information\n"
11390 bool uj
= use_json(argc
, argv
);
11392 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11394 return CMD_WARNING
;
11396 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11399 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11400 show_ip_bgp_vpn_all_route_prefix_cmd
,
11401 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11406 "Display information about all VPNv4 NLRIs\n"
11407 "Network in the BGP routing table to display\n"
11408 "Network in the BGP routing table to display\n"
11412 char *network
= NULL
;
11413 struct bgp
*bgp
= bgp_get_default();
11415 vty_out(vty
, "Can't find default instance\n");
11416 return CMD_WARNING
;
11419 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11420 network
= argv
[idx
]->arg
;
11421 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11422 network
= argv
[idx
]->arg
;
11424 vty_out(vty
, "Unable to figure out Network\n");
11425 return CMD_WARNING
;
11428 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11429 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11431 #endif /* KEEP_OLD_VPN_COMMANDS */
11433 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11434 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11435 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11440 "Network in the BGP routing table to display\n"
11441 "Network in the BGP routing table to display\n"
11442 "Network in the BGP routing table to display\n"
11443 "Network in the BGP routing table to display\n"
11447 char *network
= NULL
;
11448 int prefix_check
= 0;
11450 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11451 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11452 network
= argv
[idx
]->arg
;
11453 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11454 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11455 network
= argv
[idx
]->arg
;
11458 vty_out(vty
, "Unable to figure out Network\n");
11459 return CMD_WARNING
;
11461 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11462 prefix_check
, BGP_PATH_SHOW_ALL
,
11463 use_json(argc
, argv
));
11466 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11467 safi_t safi
, enum bgp_show_adj_route_type type
,
11468 const char *rmap_name
, bool use_json
,
11471 struct bgp_table
*table
;
11472 struct bgp_adj_in
*ain
;
11473 struct bgp_adj_out
*adj
;
11474 unsigned long output_count
;
11475 unsigned long filtered_count
;
11476 struct bgp_node
*rn
;
11482 struct update_subgroup
*subgrp
;
11483 json_object
*json_scode
= NULL
;
11484 json_object
*json_ocode
= NULL
;
11485 json_object
*json_ar
= NULL
;
11486 struct peer_af
*paf
;
11487 bool route_filtered
;
11490 json_scode
= json_object_new_object();
11491 json_ocode
= json_object_new_object();
11492 json_ar
= json_object_new_object();
11494 json_object_string_add(json_scode
, "suppressed", "s");
11495 json_object_string_add(json_scode
, "damped", "d");
11496 json_object_string_add(json_scode
, "history", "h");
11497 json_object_string_add(json_scode
, "valid", "*");
11498 json_object_string_add(json_scode
, "best", ">");
11499 json_object_string_add(json_scode
, "multipath", "=");
11500 json_object_string_add(json_scode
, "internal", "i");
11501 json_object_string_add(json_scode
, "ribFailure", "r");
11502 json_object_string_add(json_scode
, "stale", "S");
11503 json_object_string_add(json_scode
, "removed", "R");
11505 json_object_string_add(json_ocode
, "igp", "i");
11506 json_object_string_add(json_ocode
, "egp", "e");
11507 json_object_string_add(json_ocode
, "incomplete", "?");
11514 json_object_string_add(json
, "alert", "no BGP");
11515 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11516 json_object_free(json
);
11518 vty_out(vty
, "%% No bgp\n");
11522 /* labeled-unicast routes live in the unicast table */
11523 if (safi
== SAFI_LABELED_UNICAST
)
11524 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11526 table
= bgp
->rib
[afi
][safi
];
11528 output_count
= filtered_count
= 0;
11529 subgrp
= peer_subgroup(peer
, afi
, safi
);
11531 if (type
== bgp_show_adj_route_advertised
&& subgrp
11532 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11534 json_object_int_add(json
, "bgpTableVersion",
11536 json_object_string_add(json
, "bgpLocalRouterId",
11537 inet_ntoa(bgp
->router_id
));
11538 json_object_int_add(json
, "defaultLocPrf",
11539 bgp
->default_local_pref
);
11540 json_object_int_add(json
, "localAS", bgp
->as
);
11541 json_object_object_add(json
, "bgpStatusCodes",
11543 json_object_object_add(json
, "bgpOriginCodes",
11545 json_object_string_add(
11546 json
, "bgpOriginatingDefaultNetwork",
11547 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11549 vty_out(vty
, "BGP table version is %" PRIu64
11550 ", local router ID is %s, vrf id ",
11551 table
->version
, inet_ntoa(bgp
->router_id
));
11552 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11553 vty_out(vty
, "%s", VRFID_NONE_STR
);
11555 vty_out(vty
, "%u", bgp
->vrf_id
);
11556 vty_out(vty
, "\n");
11557 vty_out(vty
, "Default local pref %u, ",
11558 bgp
->default_local_pref
);
11559 vty_out(vty
, "local AS %u\n", bgp
->as
);
11560 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11561 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11562 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11564 vty_out(vty
, "Originating default network %s\n\n",
11565 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11570 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11571 if (type
== bgp_show_adj_route_received
11572 || type
== bgp_show_adj_route_filtered
) {
11573 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11574 if (ain
->peer
!= peer
)
11579 json_object_int_add(
11580 json
, "bgpTableVersion",
11582 json_object_string_add(
11584 "bgpLocalRouterId",
11587 json_object_int_add(json
,
11589 bgp
->default_local_pref
);
11590 json_object_int_add(json
,
11591 "localAS", bgp
->as
);
11592 json_object_object_add(
11593 json
, "bgpStatusCodes",
11595 json_object_object_add(
11596 json
, "bgpOriginCodes",
11600 "BGP table version is 0, local router ID is %s, vrf id ",
11603 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11609 vty_out(vty
, "\n");
11611 "Default local pref %u, ",
11612 bgp
->default_local_pref
);
11613 vty_out(vty
, "local AS %u\n",
11616 BGP_SHOW_SCODE_HEADER
);
11618 BGP_SHOW_NCODE_HEADER
);
11620 BGP_SHOW_OCODE_HEADER
);
11626 vty_out(vty
, BGP_SHOW_HEADER
);
11631 route_filtered
= false;
11633 /* Filter prefix using distribute list,
11634 * filter list or prefix list
11636 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11637 safi
)) == FILTER_DENY
)
11638 route_filtered
= true;
11640 /* Filter prefix using route-map */
11641 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11642 afi
, safi
, rmap_name
, NULL
, 0,
11645 if (type
== bgp_show_adj_route_filtered
&&
11646 !route_filtered
&& ret
!= RMAP_DENY
) {
11647 bgp_attr_undup(&attr
, ain
->attr
);
11651 if (type
== bgp_show_adj_route_received
&&
11652 (route_filtered
|| ret
== RMAP_DENY
))
11655 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11656 use_json
, json_ar
);
11657 bgp_attr_undup(&attr
, ain
->attr
);
11660 } else if (type
== bgp_show_adj_route_advertised
) {
11661 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11662 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11663 if (paf
->peer
!= peer
|| !adj
->attr
)
11668 json_object_int_add(
11672 json_object_string_add(
11674 "bgpLocalRouterId",
11677 json_object_int_add(
11678 json
, "defaultLocPrf",
11679 bgp
->default_local_pref
11681 json_object_int_add(
11684 json_object_object_add(
11688 json_object_object_add(
11694 "BGP table version is %" PRIu64
11695 ", local router ID is %s, vrf id ",
11708 vty_out(vty
, "\n");
11710 "Default local pref %u, ",
11711 bgp
->default_local_pref
11717 BGP_SHOW_SCODE_HEADER
);
11719 BGP_SHOW_NCODE_HEADER
);
11721 BGP_SHOW_OCODE_HEADER
);
11733 ret
= bgp_output_modifier(
11734 peer
, &rn
->p
, &attr
, afi
, safi
,
11737 if (ret
!= RMAP_DENY
) {
11738 route_vty_out_tmp(vty
, &rn
->p
,
11747 bgp_attr_undup(&attr
, adj
->attr
);
11753 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11754 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11755 json_object_int_add(json
, "filteredPrefixCounter",
11758 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11759 json
, JSON_C_TO_STRING_PRETTY
));
11760 json_object_free(json
);
11761 } else if (output_count
> 0) {
11762 if (filtered_count
> 0)
11764 "\nTotal number of prefixes %ld (%ld filtered)\n",
11765 output_count
, filtered_count
);
11767 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11772 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11773 safi_t safi
, enum bgp_show_adj_route_type type
,
11774 const char *rmap_name
, bool use_json
)
11776 json_object
*json
= NULL
;
11779 json
= json_object_new_object();
11781 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11783 json_object_string_add(
11785 "No such neighbor or address family");
11786 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11787 json_object_free(json
);
11789 vty_out(vty
, "%% No such neighbor or address family\n");
11791 return CMD_WARNING
;
11794 if ((type
== bgp_show_adj_route_received
11795 || type
== bgp_show_adj_route_filtered
)
11796 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11797 PEER_FLAG_SOFT_RECONFIG
)) {
11799 json_object_string_add(
11801 "Inbound soft reconfiguration not enabled");
11802 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11803 json_object_free(json
);
11806 "%% Inbound soft reconfiguration not enabled\n");
11808 return CMD_WARNING
;
11811 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11813 return CMD_SUCCESS
;
11816 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11817 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11818 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11819 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11823 BGP_INSTANCE_HELP_STR
11825 BGP_SAFI_WITH_LABEL_HELP_STR
11826 "Detailed information on TCP and BGP neighbor connections\n"
11827 "Neighbor to display information about\n"
11828 "Neighbor to display information about\n"
11829 "Neighbor on BGP configured interface\n"
11830 "Display the routes advertised to a BGP neighbor\n"
11831 "Display the received routes from neighbor\n"
11832 "Display the filtered routes received from neighbor\n"
11833 "Route-map to modify the attributes\n"
11834 "Name of the route map\n"
11837 afi_t afi
= AFI_IP6
;
11838 safi_t safi
= SAFI_UNICAST
;
11839 char *rmap_name
= NULL
;
11840 char *peerstr
= NULL
;
11841 struct bgp
*bgp
= NULL
;
11843 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11845 bool uj
= use_json(argc
, argv
);
11850 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11853 return CMD_WARNING
;
11855 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11856 argv_find(argv
, argc
, "neighbors", &idx
);
11857 peerstr
= argv
[++idx
]->arg
;
11859 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11861 return CMD_WARNING
;
11863 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11864 type
= bgp_show_adj_route_advertised
;
11865 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11866 type
= bgp_show_adj_route_received
;
11867 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11868 type
= bgp_show_adj_route_filtered
;
11870 if (argv_find(argv
, argc
, "route-map", &idx
))
11871 rmap_name
= argv
[++idx
]->arg
;
11873 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11876 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11877 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11878 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11884 "Address Family modifier\n"
11885 "Detailed information on TCP and BGP neighbor connections\n"
11886 "Neighbor to display information about\n"
11887 "Neighbor to display information about\n"
11888 "Neighbor on BGP configured interface\n"
11889 "Display information received from a BGP neighbor\n"
11890 "Display the prefixlist filter\n"
11893 afi_t afi
= AFI_IP6
;
11894 safi_t safi
= SAFI_UNICAST
;
11895 char *peerstr
= NULL
;
11898 union sockunion su
;
11904 /* show [ip] bgp */
11905 if (argv_find(argv
, argc
, "ip", &idx
))
11907 /* [<ipv4|ipv6> [unicast]] */
11908 if (argv_find(argv
, argc
, "ipv4", &idx
))
11910 if (argv_find(argv
, argc
, "ipv6", &idx
))
11912 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11913 argv_find(argv
, argc
, "neighbors", &idx
);
11914 peerstr
= argv
[++idx
]->arg
;
11916 bool uj
= use_json(argc
, argv
);
11918 ret
= str2sockunion(peerstr
, &su
);
11920 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11923 vty_out(vty
, "{}\n");
11926 "%% Malformed address or name: %s\n",
11928 return CMD_WARNING
;
11931 peer
= peer_lookup(NULL
, &su
);
11934 vty_out(vty
, "{}\n");
11936 vty_out(vty
, "No peer\n");
11937 return CMD_WARNING
;
11941 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11942 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11945 vty_out(vty
, "Address Family: %s\n",
11946 get_afi_safi_str(afi
, safi
, false));
11947 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11950 vty_out(vty
, "{}\n");
11952 vty_out(vty
, "No functional output\n");
11955 return CMD_SUCCESS
;
11958 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11959 afi_t afi
, safi_t safi
,
11960 enum bgp_show_type type
, bool use_json
)
11962 /* labeled-unicast routes live in the unicast table */
11963 if (safi
== SAFI_LABELED_UNICAST
)
11964 safi
= SAFI_UNICAST
;
11966 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11968 json_object
*json_no
= NULL
;
11969 json_no
= json_object_new_object();
11970 json_object_string_add(
11971 json_no
, "warning",
11972 "No such neighbor or address family");
11973 vty_out(vty
, "%s\n",
11974 json_object_to_json_string(json_no
));
11975 json_object_free(json_no
);
11977 vty_out(vty
, "%% No such neighbor or address family\n");
11978 return CMD_WARNING
;
11981 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11984 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11985 show_ip_bgp_flowspec_routes_detailed_cmd
,
11986 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11990 BGP_INSTANCE_HELP_STR
11993 "Detailed information on flowspec entries\n"
11996 afi_t afi
= AFI_IP
;
11997 safi_t safi
= SAFI_UNICAST
;
11998 struct bgp
*bgp
= NULL
;
12000 bool uj
= use_json(argc
, argv
);
12005 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12008 return CMD_WARNING
;
12010 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
12013 DEFUN (show_ip_bgp_neighbor_routes
,
12014 show_ip_bgp_neighbor_routes_cmd
,
12015 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12016 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
12020 BGP_INSTANCE_HELP_STR
12022 BGP_SAFI_WITH_LABEL_HELP_STR
12023 "Detailed information on TCP and BGP neighbor connections\n"
12024 "Neighbor to display information about\n"
12025 "Neighbor to display information about\n"
12026 "Neighbor on BGP configured interface\n"
12027 "Display flap statistics of the routes learned from neighbor\n"
12028 "Display the dampened routes received from neighbor\n"
12029 "Display routes learned from neighbor\n"
12032 char *peerstr
= NULL
;
12033 struct bgp
*bgp
= NULL
;
12034 afi_t afi
= AFI_IP6
;
12035 safi_t safi
= SAFI_UNICAST
;
12037 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12039 bool uj
= use_json(argc
, argv
);
12044 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12047 return CMD_WARNING
;
12049 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12050 argv_find(argv
, argc
, "neighbors", &idx
);
12051 peerstr
= argv
[++idx
]->arg
;
12053 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12055 return CMD_WARNING
;
12057 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12058 sh_type
= bgp_show_type_flap_neighbor
;
12059 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12060 sh_type
= bgp_show_type_damp_neighbor
;
12061 else if (argv_find(argv
, argc
, "routes", &idx
))
12062 sh_type
= bgp_show_type_neighbor
;
12064 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12067 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12069 struct bgp_distance
{
12070 /* Distance value for the IP source prefix. */
12073 /* Name of the access-list to be matched. */
12077 DEFUN (show_bgp_afi_vpn_rd_route
,
12078 show_bgp_afi_vpn_rd_route_cmd
,
12079 "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]",
12083 "Address Family modifier\n"
12084 "Display information for a route distinguisher\n"
12085 "Route Distinguisher\n"
12086 "Network in the BGP routing table to display\n"
12087 "Network in the BGP routing table to display\n"
12091 struct prefix_rd prd
;
12092 afi_t afi
= AFI_MAX
;
12095 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12096 vty_out(vty
, "%% Malformed Address Family\n");
12097 return CMD_WARNING
;
12100 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12102 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12103 return CMD_WARNING
;
12106 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12107 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12110 static struct bgp_distance
*bgp_distance_new(void)
12112 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12115 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12117 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12120 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12121 const char *ip_str
, const char *access_list_str
)
12128 struct bgp_node
*rn
;
12129 struct bgp_distance
*bdistance
;
12131 afi
= bgp_node_afi(vty
);
12132 safi
= bgp_node_safi(vty
);
12134 ret
= str2prefix(ip_str
, &p
);
12136 vty_out(vty
, "Malformed prefix\n");
12137 return CMD_WARNING_CONFIG_FAILED
;
12140 distance
= atoi(distance_str
);
12142 /* Get BGP distance node. */
12143 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
12144 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12146 bgp_unlock_node(rn
);
12148 bdistance
= bgp_distance_new();
12149 bgp_node_set_bgp_distance_info(rn
, bdistance
);
12152 /* Set distance value. */
12153 bdistance
->distance
= distance
;
12155 /* Reset access-list configuration. */
12156 if (bdistance
->access_list
) {
12157 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12158 bdistance
->access_list
= NULL
;
12160 if (access_list_str
)
12161 bdistance
->access_list
=
12162 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12164 return CMD_SUCCESS
;
12167 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12168 const char *ip_str
, const char *access_list_str
)
12175 struct bgp_node
*rn
;
12176 struct bgp_distance
*bdistance
;
12178 afi
= bgp_node_afi(vty
);
12179 safi
= bgp_node_safi(vty
);
12181 ret
= str2prefix(ip_str
, &p
);
12183 vty_out(vty
, "Malformed prefix\n");
12184 return CMD_WARNING_CONFIG_FAILED
;
12187 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
12188 (struct prefix
*)&p
);
12190 vty_out(vty
, "Can't find specified prefix\n");
12191 return CMD_WARNING_CONFIG_FAILED
;
12194 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12195 distance
= atoi(distance_str
);
12197 if (bdistance
->distance
!= distance
) {
12198 vty_out(vty
, "Distance does not match configured\n");
12199 return CMD_WARNING_CONFIG_FAILED
;
12202 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12203 bgp_distance_free(bdistance
);
12205 bgp_node_set_bgp_path_info(rn
, NULL
);
12206 bgp_unlock_node(rn
);
12207 bgp_unlock_node(rn
);
12209 return CMD_SUCCESS
;
12212 /* Apply BGP information to distance method. */
12213 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
12214 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12216 struct bgp_node
*rn
;
12219 struct bgp_distance
*bdistance
;
12220 struct access_list
*alist
;
12221 struct bgp_static
*bgp_static
;
12226 peer
= pinfo
->peer
;
12228 if (pinfo
->attr
->distance
)
12229 return pinfo
->attr
->distance
;
12231 /* Check source address. */
12232 sockunion2hostprefix(&peer
->su
, &q
);
12233 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12235 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12236 bgp_unlock_node(rn
);
12238 if (bdistance
->access_list
) {
12239 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12241 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12242 return bdistance
->distance
;
12244 return bdistance
->distance
;
12247 /* Backdoor check. */
12248 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12250 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12251 bgp_unlock_node(rn
);
12253 if (bgp_static
->backdoor
) {
12254 if (bgp
->distance_local
[afi
][safi
])
12255 return bgp
->distance_local
[afi
][safi
];
12257 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12261 if (peer
->sort
== BGP_PEER_EBGP
) {
12262 if (bgp
->distance_ebgp
[afi
][safi
])
12263 return bgp
->distance_ebgp
[afi
][safi
];
12264 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12266 if (bgp
->distance_ibgp
[afi
][safi
])
12267 return bgp
->distance_ibgp
[afi
][safi
];
12268 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12272 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12273 * we should tell ZEBRA update the routes for a specific
12274 * AFI/SAFI to reflect changes in RIB.
12276 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12278 safi_t update_safi
)
12283 FOREACH_AFI_SAFI (afi
, safi
) {
12284 if (!bgp_fibupd_safi(safi
))
12287 if (afi
!= update_afi
&& safi
!= update_safi
)
12290 if (BGP_DEBUG(zebra
, ZEBRA
))
12292 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12293 __func__
, afi
, safi
);
12294 bgp_zebra_announce_table(bgp
, afi
, safi
);
12298 DEFUN (bgp_distance
,
12300 "distance bgp (1-255) (1-255) (1-255)",
12301 "Define an administrative distance\n"
12303 "Distance for routes external to the AS\n"
12304 "Distance for routes internal to the AS\n"
12305 "Distance for local routes\n")
12307 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12308 int idx_number
= 2;
12309 int idx_number_2
= 3;
12310 int idx_number_3
= 4;
12311 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12312 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12313 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12317 afi
= bgp_node_afi(vty
);
12318 safi
= bgp_node_safi(vty
);
12320 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12321 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12322 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12323 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12324 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12325 bgp
->distance_local
[afi
][safi
] = distance_local
;
12326 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12328 return CMD_SUCCESS
;
12331 DEFUN (no_bgp_distance
,
12332 no_bgp_distance_cmd
,
12333 "no distance bgp [(1-255) (1-255) (1-255)]",
12335 "Define an administrative distance\n"
12337 "Distance for routes external to the AS\n"
12338 "Distance for routes internal to the AS\n"
12339 "Distance for local routes\n")
12341 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12345 afi
= bgp_node_afi(vty
);
12346 safi
= bgp_node_safi(vty
);
12348 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12349 || bgp
->distance_ibgp
[afi
][safi
] != 0
12350 || bgp
->distance_local
[afi
][safi
] != 0) {
12351 bgp
->distance_ebgp
[afi
][safi
] = 0;
12352 bgp
->distance_ibgp
[afi
][safi
] = 0;
12353 bgp
->distance_local
[afi
][safi
] = 0;
12354 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12356 return CMD_SUCCESS
;
12360 DEFUN (bgp_distance_source
,
12361 bgp_distance_source_cmd
,
12362 "distance (1-255) A.B.C.D/M",
12363 "Define an administrative distance\n"
12364 "Administrative distance\n"
12365 "IP source prefix\n")
12367 int idx_number
= 1;
12368 int idx_ipv4_prefixlen
= 2;
12369 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12370 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12371 return CMD_SUCCESS
;
12374 DEFUN (no_bgp_distance_source
,
12375 no_bgp_distance_source_cmd
,
12376 "no distance (1-255) A.B.C.D/M",
12378 "Define an administrative distance\n"
12379 "Administrative distance\n"
12380 "IP source prefix\n")
12382 int idx_number
= 2;
12383 int idx_ipv4_prefixlen
= 3;
12384 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12385 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12386 return CMD_SUCCESS
;
12389 DEFUN (bgp_distance_source_access_list
,
12390 bgp_distance_source_access_list_cmd
,
12391 "distance (1-255) A.B.C.D/M WORD",
12392 "Define an administrative distance\n"
12393 "Administrative distance\n"
12394 "IP source prefix\n"
12395 "Access list name\n")
12397 int idx_number
= 1;
12398 int idx_ipv4_prefixlen
= 2;
12400 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12401 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12402 return CMD_SUCCESS
;
12405 DEFUN (no_bgp_distance_source_access_list
,
12406 no_bgp_distance_source_access_list_cmd
,
12407 "no distance (1-255) A.B.C.D/M WORD",
12409 "Define an administrative distance\n"
12410 "Administrative distance\n"
12411 "IP source prefix\n"
12412 "Access list name\n")
12414 int idx_number
= 2;
12415 int idx_ipv4_prefixlen
= 3;
12417 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12418 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12419 return CMD_SUCCESS
;
12422 DEFUN (ipv6_bgp_distance_source
,
12423 ipv6_bgp_distance_source_cmd
,
12424 "distance (1-255) X:X::X:X/M",
12425 "Define an administrative distance\n"
12426 "Administrative distance\n"
12427 "IP source prefix\n")
12429 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12430 return CMD_SUCCESS
;
12433 DEFUN (no_ipv6_bgp_distance_source
,
12434 no_ipv6_bgp_distance_source_cmd
,
12435 "no distance (1-255) X:X::X:X/M",
12437 "Define an administrative distance\n"
12438 "Administrative distance\n"
12439 "IP source prefix\n")
12441 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12442 return CMD_SUCCESS
;
12445 DEFUN (ipv6_bgp_distance_source_access_list
,
12446 ipv6_bgp_distance_source_access_list_cmd
,
12447 "distance (1-255) X:X::X:X/M WORD",
12448 "Define an administrative distance\n"
12449 "Administrative distance\n"
12450 "IP source prefix\n"
12451 "Access list name\n")
12453 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12454 return CMD_SUCCESS
;
12457 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12458 no_ipv6_bgp_distance_source_access_list_cmd
,
12459 "no distance (1-255) X:X::X:X/M WORD",
12461 "Define an administrative distance\n"
12462 "Administrative distance\n"
12463 "IP source prefix\n"
12464 "Access list name\n")
12466 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12467 return CMD_SUCCESS
;
12470 DEFUN (bgp_damp_set
,
12472 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12473 "BGP Specific commands\n"
12474 "Enable route-flap dampening\n"
12475 "Half-life time for the penalty\n"
12476 "Value to start reusing a route\n"
12477 "Value to start suppressing a route\n"
12478 "Maximum duration to suppress a stable route\n")
12480 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12481 int idx_half_life
= 2;
12483 int idx_suppress
= 4;
12484 int idx_max_suppress
= 5;
12485 int half
= DEFAULT_HALF_LIFE
* 60;
12486 int reuse
= DEFAULT_REUSE
;
12487 int suppress
= DEFAULT_SUPPRESS
;
12488 int max
= 4 * half
;
12491 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12492 reuse
= atoi(argv
[idx_reuse
]->arg
);
12493 suppress
= atoi(argv
[idx_suppress
]->arg
);
12494 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12495 } else if (argc
== 3) {
12496 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12501 * These can't be 0 but our SA doesn't understand the
12502 * way our cli is constructed
12506 if (suppress
< reuse
) {
12508 "Suppress value cannot be less than reuse value \n");
12512 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12513 reuse
, suppress
, max
);
12516 DEFUN (bgp_damp_unset
,
12517 bgp_damp_unset_cmd
,
12518 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12520 "BGP Specific commands\n"
12521 "Enable route-flap dampening\n"
12522 "Half-life time for the penalty\n"
12523 "Value to start reusing a route\n"
12524 "Value to start suppressing a route\n"
12525 "Maximum duration to suppress a stable route\n")
12527 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12528 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12531 /* Display specified route of BGP table. */
12532 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12533 const char *ip_str
, afi_t afi
, safi_t safi
,
12534 struct prefix_rd
*prd
, int prefix_check
)
12537 struct prefix match
;
12538 struct bgp_node
*rn
;
12539 struct bgp_node
*rm
;
12540 struct bgp_path_info
*pi
;
12541 struct bgp_path_info
*pi_temp
;
12543 struct bgp_table
*table
;
12545 /* BGP structure lookup. */
12547 bgp
= bgp_lookup_by_name(view_name
);
12549 vty_out(vty
, "%% Can't find BGP instance %s\n",
12551 return CMD_WARNING
;
12554 bgp
= bgp_get_default();
12556 vty_out(vty
, "%% No BGP process is configured\n");
12557 return CMD_WARNING
;
12561 /* Check IP address argument. */
12562 ret
= str2prefix(ip_str
, &match
);
12564 vty_out(vty
, "%% address is malformed\n");
12565 return CMD_WARNING
;
12568 match
.family
= afi2family(afi
);
12570 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12571 || (safi
== SAFI_EVPN
)) {
12572 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12573 rn
= bgp_route_next(rn
)) {
12574 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12576 table
= bgp_node_get_bgp_table_info(rn
);
12579 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12583 || rm
->p
.prefixlen
== match
.prefixlen
) {
12584 pi
= bgp_node_get_bgp_path_info(rm
);
12586 if (pi
->extra
&& pi
->extra
->damp_info
) {
12587 pi_temp
= pi
->next
;
12588 bgp_damp_info_free(
12589 pi
->extra
->damp_info
,
12597 bgp_unlock_node(rm
);
12600 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12603 || rn
->p
.prefixlen
== match
.prefixlen
) {
12604 pi
= bgp_node_get_bgp_path_info(rn
);
12606 if (pi
->extra
&& pi
->extra
->damp_info
) {
12607 pi_temp
= pi
->next
;
12608 bgp_damp_info_free(
12609 pi
->extra
->damp_info
,
12617 bgp_unlock_node(rn
);
12621 return CMD_SUCCESS
;
12624 DEFUN (clear_ip_bgp_dampening
,
12625 clear_ip_bgp_dampening_cmd
,
12626 "clear ip bgp dampening",
12630 "Clear route flap dampening information\n")
12632 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12633 return CMD_SUCCESS
;
12636 DEFUN (clear_ip_bgp_dampening_prefix
,
12637 clear_ip_bgp_dampening_prefix_cmd
,
12638 "clear ip bgp dampening A.B.C.D/M",
12642 "Clear route flap dampening information\n"
12645 int idx_ipv4_prefixlen
= 4;
12646 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12647 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12650 DEFUN (clear_ip_bgp_dampening_address
,
12651 clear_ip_bgp_dampening_address_cmd
,
12652 "clear ip bgp dampening A.B.C.D",
12656 "Clear route flap dampening information\n"
12657 "Network to clear damping information\n")
12660 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12661 SAFI_UNICAST
, NULL
, 0);
12664 DEFUN (clear_ip_bgp_dampening_address_mask
,
12665 clear_ip_bgp_dampening_address_mask_cmd
,
12666 "clear ip bgp dampening A.B.C.D A.B.C.D",
12670 "Clear route flap dampening information\n"
12671 "Network to clear damping information\n"
12675 int idx_ipv4_2
= 5;
12677 char prefix_str
[BUFSIZ
];
12679 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12682 vty_out(vty
, "%% Inconsistent address and mask\n");
12683 return CMD_WARNING
;
12686 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12690 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12692 struct vty
*vty
= arg
;
12693 struct peer
*peer
= bucket
->data
;
12694 char buf
[SU_ADDRSTRLEN
];
12696 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12697 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12700 DEFUN (show_bgp_peerhash
,
12701 show_bgp_peerhash_cmd
,
12702 "show bgp peerhash",
12705 "Display information about the BGP peerhash\n")
12707 struct list
*instances
= bm
->bgp
;
12708 struct listnode
*node
;
12711 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12712 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12713 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12717 return CMD_SUCCESS
;
12720 /* also used for encap safi */
12721 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12722 afi_t afi
, safi_t safi
)
12724 struct bgp_node
*prn
;
12725 struct bgp_node
*rn
;
12726 struct bgp_table
*table
;
12728 struct prefix_rd
*prd
;
12729 struct bgp_static
*bgp_static
;
12730 mpls_label_t label
;
12731 char buf
[SU_ADDRSTRLEN
];
12732 char rdbuf
[RD_ADDRSTRLEN
];
12734 /* Network configuration. */
12735 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12736 prn
= bgp_route_next(prn
)) {
12737 table
= bgp_node_get_bgp_table_info(prn
);
12741 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12742 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12743 if (bgp_static
== NULL
)
12747 prd
= (struct prefix_rd
*)&prn
->p
;
12749 /* "network" configuration display. */
12750 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12751 label
= decode_label(&bgp_static
->label
);
12753 vty_out(vty
, " network %s/%d rd %s",
12754 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12756 p
->prefixlen
, rdbuf
);
12757 if (safi
== SAFI_MPLS_VPN
)
12758 vty_out(vty
, " label %u", label
);
12760 if (bgp_static
->rmap
.name
)
12761 vty_out(vty
, " route-map %s",
12762 bgp_static
->rmap
.name
);
12764 if (bgp_static
->backdoor
)
12765 vty_out(vty
, " backdoor");
12767 vty_out(vty
, "\n");
12772 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12773 afi_t afi
, safi_t safi
)
12775 struct bgp_node
*prn
;
12776 struct bgp_node
*rn
;
12777 struct bgp_table
*table
;
12779 struct prefix_rd
*prd
;
12780 struct bgp_static
*bgp_static
;
12781 char buf
[PREFIX_STRLEN
* 2];
12782 char buf2
[SU_ADDRSTRLEN
];
12783 char rdbuf
[RD_ADDRSTRLEN
];
12785 /* Network configuration. */
12786 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12787 prn
= bgp_route_next(prn
)) {
12788 table
= bgp_node_get_bgp_table_info(prn
);
12792 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12793 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12794 if (bgp_static
== NULL
)
12797 char *macrouter
= NULL
;
12800 if (bgp_static
->router_mac
)
12801 macrouter
= prefix_mac2str(
12802 bgp_static
->router_mac
, NULL
, 0);
12803 if (bgp_static
->eth_s_id
)
12804 esi
= esi2str(bgp_static
->eth_s_id
);
12806 prd
= (struct prefix_rd
*)&prn
->p
;
12808 /* "network" configuration display. */
12809 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12810 if (p
->u
.prefix_evpn
.route_type
== 5) {
12811 char local_buf
[PREFIX_STRLEN
];
12812 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12813 struct prefix_evpn
*)p
)
12817 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12818 local_buf
, PREFIX_STRLEN
);
12819 sprintf(buf
, "%s/%u", local_buf
,
12820 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12822 prefix2str(p
, buf
, sizeof(buf
));
12825 if (bgp_static
->gatewayIp
.family
== AF_INET
12826 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12827 inet_ntop(bgp_static
->gatewayIp
.family
,
12828 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12831 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12833 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12834 decode_label(&bgp_static
->label
), esi
, buf2
,
12837 XFREE(MTYPE_TMP
, macrouter
);
12838 XFREE(MTYPE_TMP
, esi
);
12843 /* Configuration of static route announcement and aggregate
12845 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12848 struct bgp_node
*rn
;
12850 struct bgp_static
*bgp_static
;
12851 struct bgp_aggregate
*bgp_aggregate
;
12852 char buf
[SU_ADDRSTRLEN
];
12854 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12855 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12859 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12860 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12864 /* Network configuration. */
12865 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12866 rn
= bgp_route_next(rn
)) {
12867 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12868 if (bgp_static
== NULL
)
12873 vty_out(vty
, " network %s/%d",
12874 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12877 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12878 vty_out(vty
, " label-index %u",
12879 bgp_static
->label_index
);
12881 if (bgp_static
->rmap
.name
)
12882 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12884 if (bgp_static
->backdoor
)
12885 vty_out(vty
, " backdoor");
12887 vty_out(vty
, "\n");
12890 /* Aggregate-address configuration. */
12891 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12892 rn
= bgp_route_next(rn
)) {
12893 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12894 if (bgp_aggregate
== NULL
)
12899 vty_out(vty
, " aggregate-address %s/%d",
12900 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12903 if (bgp_aggregate
->as_set
)
12904 vty_out(vty
, " as-set");
12906 if (bgp_aggregate
->summary_only
)
12907 vty_out(vty
, " summary-only");
12909 if (bgp_aggregate
->rmap
.name
)
12910 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12912 vty_out(vty
, "\n");
12916 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12919 struct bgp_node
*rn
;
12920 struct bgp_distance
*bdistance
;
12922 /* Distance configuration. */
12923 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12924 && bgp
->distance_local
[afi
][safi
]
12925 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12926 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12927 || bgp
->distance_local
[afi
][safi
]
12928 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12929 vty_out(vty
, " distance bgp %d %d %d\n",
12930 bgp
->distance_ebgp
[afi
][safi
],
12931 bgp
->distance_ibgp
[afi
][safi
],
12932 bgp
->distance_local
[afi
][safi
]);
12935 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12936 rn
= bgp_route_next(rn
)) {
12937 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12938 if (bdistance
!= NULL
) {
12939 char buf
[PREFIX_STRLEN
];
12941 vty_out(vty
, " distance %d %s %s\n",
12942 bdistance
->distance
,
12943 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12944 bdistance
->access_list
? bdistance
->access_list
12950 /* Allocate routing table structure and install commands. */
12951 void bgp_route_init(void)
12956 /* Init BGP distance table. */
12957 FOREACH_AFI_SAFI (afi
, safi
)
12958 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12960 /* IPv4 BGP commands. */
12961 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12962 install_element(BGP_NODE
, &bgp_network_cmd
);
12963 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12965 install_element(BGP_NODE
, &aggregate_address_cmd
);
12966 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12967 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12968 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12970 /* IPv4 unicast configuration. */
12971 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12972 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12973 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12975 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12976 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12977 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12978 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12980 /* IPv4 multicast configuration. */
12981 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12982 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12983 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12984 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12985 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12986 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12987 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12989 /* IPv4 labeled-unicast configuration. */
12990 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12991 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12992 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12993 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12994 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12996 install_element(VIEW_NODE
,
12997 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12998 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12999 install_element(VIEW_NODE
,
13000 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13001 #ifdef KEEP_OLD_VPN_COMMANDS
13002 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13003 #endif /* KEEP_OLD_VPN_COMMANDS */
13004 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13005 install_element(VIEW_NODE
,
13006 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13008 /* BGP dampening clear commands */
13009 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13010 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13012 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13013 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13016 install_element(ENABLE_NODE
,
13017 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13018 #ifdef KEEP_OLD_VPN_COMMANDS
13019 install_element(ENABLE_NODE
,
13020 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13021 #endif /* KEEP_OLD_VPN_COMMANDS */
13023 /* New config IPv6 BGP commands. */
13024 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13025 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13026 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13028 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13029 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13031 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13033 install_element(BGP_NODE
, &bgp_distance_cmd
);
13034 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13035 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13036 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13037 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13038 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13039 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13040 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13041 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13042 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13043 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13044 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13045 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13046 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13047 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13048 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13049 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13050 install_element(BGP_IPV4M_NODE
,
13051 &no_bgp_distance_source_access_list_cmd
);
13052 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13053 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13054 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13055 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13056 install_element(BGP_IPV6_NODE
,
13057 &ipv6_bgp_distance_source_access_list_cmd
);
13058 install_element(BGP_IPV6_NODE
,
13059 &no_ipv6_bgp_distance_source_access_list_cmd
);
13060 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13061 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13062 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13063 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13064 install_element(BGP_IPV6M_NODE
,
13065 &ipv6_bgp_distance_source_access_list_cmd
);
13066 install_element(BGP_IPV6M_NODE
,
13067 &no_ipv6_bgp_distance_source_access_list_cmd
);
13069 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13070 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13071 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13072 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13074 /* IPv4 Multicast Mode */
13075 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13076 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13078 /* Large Communities */
13079 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13080 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13082 /* show bgp ipv4 flowspec detailed */
13083 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13085 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13088 void bgp_route_finish(void)
13093 FOREACH_AFI_SAFI (afi
, safi
) {
13094 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13095 bgp_distance_table
[afi
][safi
] = NULL
;