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
));
2765 if (thread_info
== NULL
) {
2766 if (BGP_DEBUG(update
, UPDATE_OUT
))
2767 zlog_debug("%s : error allocating thread info",
2772 thread_info
->afi
= afi
;
2773 thread_info
->safi
= safi
;
2774 thread_info
->bgp
= bgp
;
2776 /* If there are more routes to be processed, start the
2779 thread_add_timer(bm
->master
, bgp_route_select_timer_expire
, thread_info
,
2780 BGP_ROUTE_SELECT_DELAY
,
2781 &bgp
->gr_info
[afi
][safi
].t_route_select
);
2782 if (bgp
->gr_info
[afi
][safi
].t_route_select
== NULL
) {
2783 if (BGP_DEBUG(update
, UPDATE_OUT
))
2784 zlog_debug("%s : error starting selection thread for %s",
2785 __func__
, get_afi_safi_str(afi
,
2792 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2794 struct bgp_process_queue
*pqnode
= data
;
2795 struct bgp
*bgp
= pqnode
->bgp
;
2796 struct bgp_table
*table
;
2797 struct bgp_node
*rn
;
2800 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2801 bgp_process_main_one(bgp
, NULL
, 0, 0);
2802 /* should always have dedicated wq call */
2803 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2807 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2808 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2809 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2810 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2811 table
= bgp_node_table(rn
);
2812 /* note, new RNs may be added as part of processing */
2813 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2815 bgp_unlock_node(rn
);
2816 bgp_table_unlock(table
);
2822 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2824 struct bgp_process_queue
*pqnode
= data
;
2826 bgp_unlock(pqnode
->bgp
);
2828 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2831 void bgp_process_queue_init(void)
2833 if (!bm
->process_main_queue
)
2834 bm
->process_main_queue
=
2835 work_queue_new(bm
->master
, "process_main_queue");
2837 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2838 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2839 bm
->process_main_queue
->spec
.max_retries
= 0;
2840 bm
->process_main_queue
->spec
.hold
= 50;
2841 /* Use a higher yield value of 50ms for main queue processing */
2842 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2845 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2847 struct bgp_process_queue
*pqnode
;
2849 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2850 sizeof(struct bgp_process_queue
));
2852 /* unlocked in bgp_processq_del */
2853 pqnode
->bgp
= bgp_lock(bgp
);
2854 STAILQ_INIT(&pqnode
->pqueue
);
2859 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2861 #define ARBITRARY_PROCESS_QLEN 10000
2862 struct work_queue
*wq
= bm
->process_main_queue
;
2863 struct bgp_process_queue
*pqnode
;
2864 int pqnode_reuse
= 0;
2866 /* already scheduled for processing? */
2867 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2870 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2873 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
2874 if (BGP_DEBUG(update
, UPDATE_OUT
))
2875 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
2883 /* Add route nodes to an existing work queue item until reaching the
2884 limit only if is from the same BGP view and it's not an EOIU marker
2886 if (work_queue_item_count(wq
)) {
2887 struct work_queue_item
*item
= work_queue_last_item(wq
);
2888 pqnode
= item
->data
;
2890 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2891 || pqnode
->bgp
!= bgp
2892 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2893 pqnode
= bgp_processq_alloc(bgp
);
2897 pqnode
= bgp_processq_alloc(bgp
);
2898 /* all unlocked in bgp_process_wq */
2899 bgp_table_lock(bgp_node_table(rn
));
2901 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2904 /* can't be enqueued twice */
2905 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2906 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2910 work_queue_add(wq
, pqnode
);
2915 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2917 struct bgp_process_queue
*pqnode
;
2919 if (bm
->process_main_queue
== NULL
)
2922 pqnode
= bgp_processq_alloc(bgp
);
2924 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2925 work_queue_add(bm
->process_main_queue
, pqnode
);
2928 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2932 peer
= THREAD_ARG(thread
);
2933 peer
->t_pmax_restart
= NULL
;
2935 if (bgp_debug_neighbor_events(peer
))
2937 "%s Maximum-prefix restart timer expired, restore peering",
2940 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2941 zlog_debug("%s: %s peer_clear failed",
2942 __PRETTY_FUNCTION__
, peer
->host
);
2947 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2951 iana_safi_t pkt_safi
;
2953 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2956 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2957 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2958 PEER_STATUS_PREFIX_LIMIT
)
2963 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2964 " exceed, limit %" PRIu32
,
2965 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2966 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2967 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2969 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2970 PEER_FLAG_MAX_PREFIX_WARNING
))
2973 /* Convert AFI, SAFI to values for packet. */
2974 pkt_afi
= afi_int2iana(afi
);
2975 pkt_safi
= safi_int2iana(safi
);
2979 ndata
[0] = (pkt_afi
>> 8);
2981 ndata
[2] = pkt_safi
;
2982 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2983 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2984 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2985 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2987 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2988 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2989 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2993 /* Dynamic peers will just close their connection. */
2994 if (peer_dynamic_neighbor(peer
))
2997 /* restart timer start */
2998 if (peer
->pmax_restart
[afi
][safi
]) {
2999 peer
->v_pmax_restart
=
3000 peer
->pmax_restart
[afi
][safi
] * 60;
3002 if (bgp_debug_neighbor_events(peer
))
3004 "%s Maximum-prefix restart timer started for %d secs",
3005 peer
->host
, peer
->v_pmax_restart
);
3007 BGP_TIMER_ON(peer
->t_pmax_restart
,
3008 bgp_maximum_prefix_restart_timer
,
3009 peer
->v_pmax_restart
);
3014 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3015 PEER_STATUS_PREFIX_LIMIT
);
3017 if (peer
->pcount
[afi
][safi
]
3018 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
3019 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
3020 PEER_STATUS_PREFIX_THRESHOLD
)
3025 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
3027 get_afi_safi_str(afi
, safi
, false), peer
->host
,
3028 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
3029 SET_FLAG(peer
->af_sflags
[afi
][safi
],
3030 PEER_STATUS_PREFIX_THRESHOLD
);
3032 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
3033 PEER_STATUS_PREFIX_THRESHOLD
);
3037 /* Unconditionally remove the route from the RIB, without taking
3038 * damping into consideration (eg, because the session went down)
3040 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3041 struct peer
*peer
, afi_t afi
, safi_t safi
)
3044 struct bgp
*bgp
= NULL
;
3045 bool delete_route
= false;
3047 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
3049 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3050 bgp_path_info_delete(rn
, pi
); /* keep historical info */
3052 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3055 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3056 delete_route
= true;
3058 if (bgp_node_set_defer_flag(rn
, true) < 0)
3059 delete_route
= true;
3061 if (CHECK_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
)) {
3062 UNSET_FLAG(rn
->flags
, BGP_NODE_SELECT_DEFER
);
3063 bgp
= pi
->peer
->bgp
;
3064 if ((rn
->rt_node
) &&
3065 (bgp
->gr_info
[afi
][safi
]
3068 bgp
->gr_info
[afi
][safi
]
3077 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
3078 bgp_process(peer
->bgp
, rn
, afi
, safi
);
3081 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
3082 struct peer
*peer
, afi_t afi
, safi_t safi
,
3083 struct prefix_rd
*prd
)
3085 /* apply dampening, if result is suppressed, we'll be retaining
3086 * the bgp_path_info in the RIB for historical reference.
3088 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3089 && peer
->sort
== BGP_PEER_EBGP
)
3090 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
3091 == BGP_DAMP_SUPPRESSED
) {
3092 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
3098 if (safi
== SAFI_MPLS_VPN
) {
3099 struct bgp_node
*prn
= NULL
;
3100 struct bgp_table
*table
= NULL
;
3102 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
3103 (struct prefix
*)prd
);
3104 if (bgp_node_has_bgp_path_info_data(prn
)) {
3105 table
= bgp_node_get_bgp_table_info(prn
);
3107 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3108 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
3110 bgp_unlock_node(prn
);
3112 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
3113 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3115 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
3116 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
3122 /* If this is an EVPN route, process for un-import. */
3123 if (safi
== SAFI_EVPN
)
3124 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
3126 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3129 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
3130 struct peer
*peer
, struct attr
*attr
,
3131 struct bgp_node
*rn
)
3133 struct bgp_path_info
*new;
3135 /* Make new BGP info. */
3136 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
3138 new->instance
= instance
;
3139 new->sub_type
= sub_type
;
3142 new->uptime
= bgp_clock();
3147 static void overlay_index_update(struct attr
*attr
,
3148 struct eth_segment_id
*eth_s_id
,
3149 union gw_addr
*gw_ip
)
3154 if (eth_s_id
== NULL
) {
3155 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
3156 sizeof(struct eth_segment_id
));
3158 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
3159 sizeof(struct eth_segment_id
));
3161 if (gw_ip
== NULL
) {
3162 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
3164 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
3165 sizeof(union gw_addr
));
3169 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
3170 struct eth_segment_id
*eth_s_id
,
3171 union gw_addr
*gw_ip
)
3173 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
3174 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
3176 struct eth_segment_id esi
;
3180 if (afi
!= AFI_L2VPN
)
3183 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
3184 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
3186 if (gw_ip
== NULL
) {
3187 memset(&temp
, 0, sizeof(temp
));
3188 path_gw_ip_remote
= &temp
.ip
;
3190 path_gw_ip_remote
= gw_ip
;
3192 if (eth_s_id
== NULL
) {
3193 memset(&temp
, 0, sizeof(temp
));
3194 path_eth_s_id_remote
= &temp
.esi
;
3196 path_eth_s_id_remote
= eth_s_id
;
3198 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
3201 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
3202 sizeof(struct eth_segment_id
));
3205 /* Check if received nexthop is valid or not. */
3206 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
3207 uint8_t type
, uint8_t stype
,
3208 struct attr
*attr
, struct bgp_node
*rn
)
3212 /* Only validated for unicast and multicast currently. */
3213 /* Also valid for EVPN where the nexthop is an IP address. */
3214 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
3217 /* If NEXT_HOP is present, validate it. */
3218 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
3219 if (attr
->nexthop
.s_addr
== 0
3220 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
3221 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3226 /* If MP_NEXTHOP is present, validate it. */
3227 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3228 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3229 * it is not an IPv6 link-local address.
3231 if (attr
->mp_nexthop_len
) {
3232 switch (attr
->mp_nexthop_len
) {
3233 case BGP_ATTR_NHLEN_IPV4
:
3234 case BGP_ATTR_NHLEN_VPNV4
:
3235 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
3236 || IPV4_CLASS_DE(ntohl(
3237 attr
->mp_nexthop_global_in
.s_addr
))
3238 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3242 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3243 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3244 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3245 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3246 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3247 || IN6_IS_ADDR_MULTICAST(
3248 &attr
->mp_nexthop_global
)
3249 || bgp_nexthop_self(bgp
, afi
, type
, stype
,
3262 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3263 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3264 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3265 uint32_t num_labels
, int soft_reconfig
,
3266 struct bgp_route_evpn
*evpn
)
3269 int aspath_loop_count
= 0;
3270 struct bgp_node
*rn
;
3272 struct attr new_attr
;
3273 struct attr
*attr_new
;
3274 struct bgp_path_info
*pi
;
3275 struct bgp_path_info
*new;
3276 struct bgp_path_info_extra
*extra
;
3278 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3280 int do_loop_check
= 1;
3281 int has_valid_label
= 0;
3283 uint8_t pi_type
= 0;
3284 uint8_t pi_sub_type
= 0;
3287 int vnc_implicit_withdraw
= 0;
3291 memset(&new_attr
, 0, sizeof(struct attr
));
3292 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3293 new_attr
.label
= MPLS_INVALID_LABEL
;
3296 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3297 /* TODO: Check to see if we can get rid of "is_valid_label" */
3298 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3299 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3301 has_valid_label
= bgp_is_valid_label(label
);
3303 /* When peer's soft reconfiguration enabled. Record input packet in
3306 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3307 && peer
!= bgp
->peer_self
)
3308 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3310 /* Check previously received route. */
3311 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3312 if (pi
->peer
== peer
&& pi
->type
== type
3313 && pi
->sub_type
== sub_type
3314 && pi
->addpath_rx_id
== addpath_id
)
3317 /* AS path local-as loop check. */
3318 if (peer
->change_local_as
) {
3319 if (peer
->allowas_in
[afi
][safi
])
3320 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3321 else if (!CHECK_FLAG(peer
->flags
,
3322 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3323 aspath_loop_count
= 1;
3325 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3326 > aspath_loop_count
) {
3327 peer
->stat_pfx_aspath_loop
++;
3328 reason
= "as-path contains our own AS;";
3333 /* If the peer is configured for "allowas-in origin" and the last ASN in
3335 * as-path is our ASN then we do not need to call aspath_loop_check
3337 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3338 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3341 /* AS path loop check. */
3342 if (do_loop_check
) {
3343 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3344 > peer
->allowas_in
[afi
][safi
]
3345 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3346 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3347 > peer
->allowas_in
[afi
][safi
])) {
3348 peer
->stat_pfx_aspath_loop
++;
3349 reason
= "as-path contains our own AS;";
3354 /* Route reflector originator ID check. */
3355 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3356 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3357 peer
->stat_pfx_originator_loop
++;
3358 reason
= "originator is us;";
3362 /* Route reflector cluster ID check. */
3363 if (bgp_cluster_filter(peer
, attr
)) {
3364 peer
->stat_pfx_cluster_loop
++;
3365 reason
= "reflected from the same cluster;";
3369 /* Apply incoming filter. */
3370 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3371 peer
->stat_pfx_filter
++;
3376 /* RFC 8212 to prevent route leaks.
3377 * This specification intends to improve this situation by requiring the
3378 * explicit configuration of both BGP Import and Export Policies for any
3379 * External BGP (EBGP) session such as customers, peers, or
3380 * confederation boundaries for all enabled address families. Through
3381 * codification of the aforementioned requirement, operators will
3382 * benefit from consistent behavior across different BGP
3385 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3386 if (!bgp_inbound_policy_exists(peer
,
3387 &peer
->filter
[afi
][safi
])) {
3388 reason
= "inbound policy missing";
3392 /* draft-ietf-idr-deprecate-as-set-confed-set
3393 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3394 * Eventually, This document (if approved) updates RFC 4271
3395 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3396 * and obsoletes RFC 6472.
3398 if (peer
->bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
)
3399 if (aspath_check_as_sets(attr
->aspath
)) {
3401 "as-path contains AS_SET or AS_CONFED_SET type;";
3407 /* Apply incoming route-map.
3408 * NB: new_attr may now contain newly allocated values from route-map
3410 * commands, so we need bgp_attr_flush in the error paths, until we
3412 * the attr (which takes over the memory references) */
3413 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3414 label
, num_labels
, rn
) == RMAP_DENY
) {
3415 peer
->stat_pfx_filter
++;
3416 reason
= "route-map;";
3417 bgp_attr_flush(&new_attr
);
3421 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3422 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3423 /* remove from RIB previous entry */
3424 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3427 if (peer
->sort
== BGP_PEER_EBGP
) {
3429 /* If we receive the graceful-shutdown community from an eBGP
3430 * peer we must lower local-preference */
3431 if (new_attr
.community
3432 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3433 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3434 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3436 /* If graceful-shutdown is configured then add the GSHUT
3437 * community to all paths received from eBGP peers */
3438 } else if (bgp_flag_check(peer
->bgp
,
3439 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3440 bgp_attr_add_gshut_community(&new_attr
);
3446 pi_sub_type
= pi
->sub_type
;
3449 /* next hop check. */
3450 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3451 && bgp_update_martian_nexthop(bgp
, afi
, safi
, pi_type
,
3452 pi_sub_type
, &new_attr
, rn
)) {
3453 peer
->stat_pfx_nh_invalid
++;
3454 reason
= "martian or self next-hop;";
3455 bgp_attr_flush(&new_attr
);
3459 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3460 peer
->stat_pfx_nh_invalid
++;
3461 reason
= "self mac;";
3465 attr_new
= bgp_attr_intern(&new_attr
);
3467 /* If the update is implicit withdraw. */
3469 pi
->uptime
= bgp_clock();
3470 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3472 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3474 /* Same attribute comes in. */
3475 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3476 && attrhash_cmp(pi
->attr
, attr_new
)
3477 && (!has_valid_label
3478 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3479 num_labels
* sizeof(mpls_label_t
))
3481 && (overlay_index_equal(
3482 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3483 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3484 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3485 BGP_CONFIG_DAMPENING
)
3486 && peer
->sort
== BGP_PEER_EBGP
3487 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3488 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3489 bgp_debug_rdpfxpath2str(
3490 afi
, safi
, prd
, p
, label
,
3491 num_labels
, addpath_id
? 1 : 0,
3492 addpath_id
, pfx_buf
,
3494 zlog_debug("%s rcvd %s", peer
->host
,
3498 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3499 != BGP_DAMP_SUPPRESSED
) {
3500 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3502 bgp_process(bgp
, rn
, afi
, safi
);
3504 } else /* Duplicate - odd */
3506 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3507 if (!peer
->rcvd_attr_printed
) {
3509 "%s rcvd UPDATE w/ attr: %s",
3511 peer
->rcvd_attr_str
);
3512 peer
->rcvd_attr_printed
= 1;
3515 bgp_debug_rdpfxpath2str(
3516 afi
, safi
, prd
, p
, label
,
3517 num_labels
, addpath_id
? 1 : 0,
3518 addpath_id
, pfx_buf
,
3521 "%s rcvd %s...duplicate ignored",
3522 peer
->host
, pfx_buf
);
3525 /* graceful restart STALE flag unset. */
3526 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3527 bgp_path_info_unset_flag(
3528 rn
, pi
, BGP_PATH_STALE
);
3529 bgp_node_set_defer_flag(rn
, false);
3530 bgp_process(bgp
, rn
, afi
, safi
);
3534 bgp_unlock_node(rn
);
3535 bgp_attr_unintern(&attr_new
);
3540 /* Withdraw/Announce before we fully processed the withdraw */
3541 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3542 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3543 bgp_debug_rdpfxpath2str(
3544 afi
, safi
, prd
, p
, label
, num_labels
,
3545 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3548 "%s rcvd %s, flapped quicker than processing",
3549 peer
->host
, pfx_buf
);
3552 bgp_path_info_restore(rn
, pi
);
3555 /* Received Logging. */
3556 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3557 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3558 num_labels
, addpath_id
? 1 : 0,
3559 addpath_id
, pfx_buf
,
3561 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3564 /* graceful restart STALE flag unset. */
3565 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3566 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3567 bgp_node_set_defer_flag(rn
, false);
3570 /* The attribute is changed. */
3571 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3573 /* implicit withdraw, decrement aggregate and pcount here.
3574 * only if update is accepted, they'll increment below.
3576 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3578 /* Update bgp route dampening information. */
3579 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3580 && peer
->sort
== BGP_PEER_EBGP
) {
3581 /* This is implicit withdraw so we should update
3584 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3585 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3588 if (safi
== SAFI_MPLS_VPN
) {
3589 struct bgp_node
*prn
= NULL
;
3590 struct bgp_table
*table
= NULL
;
3592 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3593 (struct prefix
*)prd
);
3594 if (bgp_node_has_bgp_path_info_data(prn
)) {
3595 table
= bgp_node_get_bgp_table_info(prn
);
3597 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3598 bgp
, prd
, table
, p
, pi
);
3600 bgp_unlock_node(prn
);
3602 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3603 && (safi
== SAFI_UNICAST
)) {
3604 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3606 * Implicit withdraw case.
3608 ++vnc_implicit_withdraw
;
3609 vnc_import_bgp_del_route(bgp
, p
, pi
);
3610 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3615 /* Special handling for EVPN update of an existing route. If the
3616 * extended community attribute has changed, we need to
3618 * the route using its existing extended community. It will be
3619 * subsequently processed for import with the new extended
3622 if (safi
== SAFI_EVPN
&& !same_attr
) {
3624 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3626 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3629 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3630 attr_new
->ecommunity
);
3632 if (bgp_debug_update(peer
, p
, NULL
, 1))
3634 "Change in EXT-COMM, existing %s new %s",
3636 pi
->attr
->ecommunity
),
3638 attr_new
->ecommunity
));
3639 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3645 /* Update to new attribute. */
3646 bgp_attr_unintern(&pi
->attr
);
3647 pi
->attr
= attr_new
;
3649 /* Update MPLS label */
3650 if (has_valid_label
) {
3651 extra
= bgp_path_info_extra_get(pi
);
3652 if (extra
->label
!= label
) {
3653 memcpy(&extra
->label
, label
,
3654 num_labels
* sizeof(mpls_label_t
));
3655 extra
->num_labels
= num_labels
;
3657 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3658 bgp_set_valid_label(&extra
->label
[0]);
3662 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3663 && (safi
== SAFI_UNICAST
)) {
3664 if (vnc_implicit_withdraw
) {
3666 * Add back the route with its new attributes
3668 * The route is still selected, until the route
3670 * queued by bgp_process actually runs. We have
3672 * update to the VNC side immediately to avoid
3674 * configuration changes (e.g., route-map
3676 * trigger re-importation of the entire RIB.
3678 vnc_import_bgp_add_route(bgp
, p
, pi
);
3679 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3683 /* Update Overlay Index */
3684 if (afi
== AFI_L2VPN
) {
3685 overlay_index_update(
3686 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3687 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3690 /* Update bgp route dampening information. */
3691 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3692 && peer
->sort
== BGP_PEER_EBGP
) {
3693 /* Now we do normal update dampening. */
3694 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3695 if (ret
== BGP_DAMP_SUPPRESSED
) {
3696 bgp_unlock_node(rn
);
3701 /* Nexthop reachability check - for unicast and
3702 * labeled-unicast.. */
3703 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3704 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3705 || (safi
== SAFI_EVPN
&&
3706 bgp_evpn_is_prefix_nht_supported(p
))) {
3707 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3708 && peer
->ttl
== BGP_DEFAULT_TTL
3709 && !CHECK_FLAG(peer
->flags
,
3710 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3712 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3717 struct bgp
*bgp_nexthop
= bgp
;
3719 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3720 bgp_nexthop
= pi
->extra
->bgp_orig
;
3722 nh_afi
= BGP_ATTR_NH_AFI(afi
, pi
->attr
);
3724 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, nh_afi
,
3725 pi
, NULL
, connected
)
3726 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3727 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3729 if (BGP_DEBUG(nht
, NHT
)) {
3730 char buf1
[INET6_ADDRSTRLEN
];
3732 (const void *)&attr_new
3734 buf1
, INET6_ADDRSTRLEN
);
3735 zlog_debug("%s(%s): NH unresolved",
3736 __FUNCTION__
, buf1
);
3738 bgp_path_info_unset_flag(rn
, pi
,
3742 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3745 if (safi
== SAFI_MPLS_VPN
) {
3746 struct bgp_node
*prn
= NULL
;
3747 struct bgp_table
*table
= NULL
;
3749 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3750 (struct prefix
*)prd
);
3751 if (bgp_node_has_bgp_path_info_data(prn
)) {
3752 table
= bgp_node_get_bgp_table_info(prn
);
3754 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3755 bgp
, prd
, table
, p
, pi
);
3757 bgp_unlock_node(prn
);
3761 /* If this is an EVPN route and some attribute has changed,
3763 * route for import. If the extended community has changed, we
3765 * have done the un-import earlier and the import would result
3767 * route getting injected into appropriate L2 VNIs. If it is
3769 * some other attribute change, the import will result in
3771 * the attributes for the route in the VNI(s).
3773 if (safi
== SAFI_EVPN
&& !same_attr
&&
3774 CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
3775 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3777 /* Process change. */
3778 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3780 bgp_process(bgp
, rn
, afi
, safi
);
3781 bgp_unlock_node(rn
);
3783 if (SAFI_UNICAST
== safi
3784 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3785 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3787 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3789 if ((SAFI_MPLS_VPN
== safi
)
3790 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3792 vpn_leak_to_vrf_update(bgp
, pi
);
3796 if (SAFI_MPLS_VPN
== safi
) {
3797 mpls_label_t label_decoded
= decode_label(label
);
3799 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3800 type
, sub_type
, &label_decoded
);
3802 if (SAFI_ENCAP
== safi
) {
3803 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3804 type
, sub_type
, NULL
);
3809 } // End of implicit withdraw
3811 /* Received Logging. */
3812 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3813 if (!peer
->rcvd_attr_printed
) {
3814 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3815 peer
->rcvd_attr_str
);
3816 peer
->rcvd_attr_printed
= 1;
3819 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3820 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3822 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3825 /* Make new BGP info. */
3826 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3828 /* Update MPLS label */
3829 if (has_valid_label
) {
3830 extra
= bgp_path_info_extra_get(new);
3831 if (extra
->label
!= label
) {
3832 memcpy(&extra
->label
, label
,
3833 num_labels
* sizeof(mpls_label_t
));
3834 extra
->num_labels
= num_labels
;
3836 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3837 bgp_set_valid_label(&extra
->label
[0]);
3840 /* Update Overlay Index */
3841 if (afi
== AFI_L2VPN
) {
3842 overlay_index_update(new->attr
,
3843 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3844 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3846 /* Nexthop reachability check. */
3847 if (((afi
== AFI_IP
|| afi
== AFI_IP6
)
3848 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
))
3849 || (safi
== SAFI_EVPN
&& bgp_evpn_is_prefix_nht_supported(p
))) {
3850 if (safi
!= SAFI_EVPN
&& peer
->sort
== BGP_PEER_EBGP
3851 && peer
->ttl
== BGP_DEFAULT_TTL
3852 && !CHECK_FLAG(peer
->flags
,
3853 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3854 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3859 nh_afi
= BGP_ATTR_NH_AFI(afi
, new->attr
);
3861 if (bgp_find_or_add_nexthop(bgp
, bgp
, nh_afi
, new, NULL
,
3863 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3864 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3866 if (BGP_DEBUG(nht
, NHT
)) {
3867 char buf1
[INET6_ADDRSTRLEN
];
3869 (const void *)&attr_new
->nexthop
,
3870 buf1
, INET6_ADDRSTRLEN
);
3871 zlog_debug("%s(%s): NH unresolved",
3872 __FUNCTION__
, buf1
);
3874 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3877 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3880 new->addpath_rx_id
= addpath_id
;
3882 /* Increment prefix */
3883 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3885 /* Register new BGP information. */
3886 bgp_path_info_add(rn
, new);
3888 /* route_node_get lock */
3889 bgp_unlock_node(rn
);
3892 if (safi
== SAFI_MPLS_VPN
) {
3893 struct bgp_node
*prn
= NULL
;
3894 struct bgp_table
*table
= NULL
;
3896 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3897 if (bgp_node_has_bgp_path_info_data(prn
)) {
3898 table
= bgp_node_get_bgp_table_info(prn
);
3900 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3901 bgp
, prd
, table
, p
, new);
3903 bgp_unlock_node(prn
);
3907 /* If maximum prefix count is configured and current prefix
3909 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3912 /* If this is an EVPN route, process for import. */
3913 if (safi
== SAFI_EVPN
&& CHECK_FLAG(new->flags
, BGP_PATH_VALID
))
3914 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3916 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3918 /* Process change. */
3919 bgp_process(bgp
, rn
, afi
, safi
);
3921 if (SAFI_UNICAST
== safi
3922 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3923 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3924 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3926 if ((SAFI_MPLS_VPN
== safi
)
3927 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3929 vpn_leak_to_vrf_update(bgp
, new);
3932 if (SAFI_MPLS_VPN
== safi
) {
3933 mpls_label_t label_decoded
= decode_label(label
);
3935 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3936 sub_type
, &label_decoded
);
3938 if (SAFI_ENCAP
== safi
) {
3939 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3946 /* This BGP update is filtered. Log the reason then update BGP
3949 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3951 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3952 if (!peer
->rcvd_attr_printed
) {
3953 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3954 peer
->rcvd_attr_str
);
3955 peer
->rcvd_attr_printed
= 1;
3958 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3959 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3961 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3962 peer
->host
, pfx_buf
, reason
);
3966 /* If this is an EVPN route, un-import it as it is now filtered.
3968 if (safi
== SAFI_EVPN
)
3969 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3971 if (SAFI_UNICAST
== safi
3972 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3973 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3975 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3977 if ((SAFI_MPLS_VPN
== safi
)
3978 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3980 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3983 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3986 bgp_unlock_node(rn
);
3990 * Filtered update is treated as an implicit withdrawal (see
3992 * a few lines above)
3994 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3995 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4003 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
4004 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
4005 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
4006 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
4009 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
4010 struct bgp_node
*rn
;
4011 struct bgp_path_info
*pi
;
4014 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
4015 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
4023 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4025 /* If peer is soft reconfiguration enabled. Record input packet for
4026 * further calculation.
4028 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4029 * routes that are filtered. This tanks out Quagga RS pretty badly due
4031 * the iteration over all RS clients.
4032 * Since we need to remove the entry from adj_in anyway, do that first
4034 * if there was no entry, we don't need to do anything more.
4036 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
4037 && peer
!= bgp
->peer_self
)
4038 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
4039 peer
->stat_pfx_dup_withdraw
++;
4041 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4042 bgp_debug_rdpfxpath2str(
4043 afi
, safi
, prd
, p
, label
, num_labels
,
4044 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4047 "%s withdrawing route %s not in adj-in",
4048 peer
->host
, pfx_buf
);
4050 bgp_unlock_node(rn
);
4054 /* Lookup withdrawn route. */
4055 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4056 if (pi
->peer
== peer
&& pi
->type
== type
4057 && pi
->sub_type
== sub_type
4058 && pi
->addpath_rx_id
== addpath_id
)
4062 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4063 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4064 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4066 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
4070 /* Withdraw specified route from routing table. */
4071 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
4072 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
4073 if (SAFI_UNICAST
== safi
4074 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4075 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4076 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4078 if ((SAFI_MPLS_VPN
== safi
)
4079 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4081 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4083 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
4084 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
4085 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
4087 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
4090 /* Unlock bgp_node_get() lock. */
4091 bgp_unlock_node(rn
);
4096 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
4099 struct update_subgroup
*subgrp
;
4100 subgrp
= peer_subgroup(peer
, afi
, safi
);
4101 subgroup_default_originate(subgrp
, withdraw
);
4106 * bgp_stop_announce_route_timer
4108 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
4110 if (!paf
->t_announce_route
)
4113 THREAD_TIMER_OFF(paf
->t_announce_route
);
4117 * bgp_announce_route_timer_expired
4119 * Callback that is invoked when the route announcement timer for a
4122 static int bgp_announce_route_timer_expired(struct thread
*t
)
4124 struct peer_af
*paf
;
4127 paf
= THREAD_ARG(t
);
4130 if (peer
->status
!= Established
)
4133 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
4136 peer_af_announce_route(paf
, 1);
4141 * bgp_announce_route
4143 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4145 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4147 struct peer_af
*paf
;
4148 struct update_subgroup
*subgrp
;
4150 paf
= peer_af_find(peer
, afi
, safi
);
4153 subgrp
= PAF_SUBGRP(paf
);
4156 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4157 * or a refresh has already been triggered.
4159 if (!subgrp
|| paf
->t_announce_route
)
4163 * Start a timer to stagger/delay the announce. This serves
4164 * two purposes - announcement can potentially be combined for
4165 * multiple peers and the announcement doesn't happen in the
4168 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
4169 (subgrp
->peer_count
== 1)
4170 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4171 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
4172 &paf
->t_announce_route
);
4176 * Announce routes from all AF tables to a peer.
4178 * This should ONLY be called when there is a need to refresh the
4179 * routes to the peer based on a policy change for this peer alone
4180 * or a route refresh request received from the peer.
4181 * The operation will result in splitting the peer from its existing
4182 * subgroups and putting it in new subgroups.
4184 void bgp_announce_route_all(struct peer
*peer
)
4189 FOREACH_AFI_SAFI (afi
, safi
)
4190 bgp_announce_route(peer
, afi
, safi
);
4193 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4194 struct bgp_table
*table
,
4195 struct prefix_rd
*prd
)
4198 struct bgp_node
*rn
;
4199 struct bgp_adj_in
*ain
;
4202 table
= peer
->bgp
->rib
[afi
][safi
];
4204 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4205 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
4206 if (ain
->peer
!= peer
)
4209 struct bgp_path_info
*pi
;
4210 uint32_t num_labels
= 0;
4211 mpls_label_t
*label_pnt
= NULL
;
4212 struct bgp_route_evpn evpn
;
4214 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4216 if (pi
->peer
== peer
)
4219 if (pi
&& pi
->extra
)
4220 num_labels
= pi
->extra
->num_labels
;
4222 label_pnt
= &pi
->extra
->label
[0];
4224 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
4227 memset(&evpn
, 0, sizeof(evpn
));
4229 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
4230 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
4231 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
4232 num_labels
, 1, &evpn
);
4235 bgp_unlock_node(rn
);
4241 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4243 struct bgp_node
*rn
;
4244 struct bgp_table
*table
;
4246 if (peer
->status
!= Established
)
4249 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
4250 && (safi
!= SAFI_EVPN
))
4251 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
4253 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4254 rn
= bgp_route_next(rn
)) {
4255 table
= bgp_node_get_bgp_table_info(rn
);
4256 if (table
!= NULL
) {
4257 struct prefix_rd prd
;
4259 prd
.family
= AF_UNSPEC
;
4261 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
4263 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
4270 struct bgp_clear_node_queue
{
4271 struct bgp_node
*rn
;
4274 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
4276 struct bgp_clear_node_queue
*cnq
= data
;
4277 struct bgp_node
*rn
= cnq
->rn
;
4278 struct peer
*peer
= wq
->spec
.data
;
4279 struct bgp_path_info
*pi
;
4281 afi_t afi
= bgp_node_table(rn
)->afi
;
4282 safi_t safi
= bgp_node_table(rn
)->safi
;
4287 /* It is possible that we have multiple paths for a prefix from a peer
4288 * if that peer is using AddPath.
4290 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4291 if (pi
->peer
!= peer
)
4294 /* graceful restart STALE flag set. */
4295 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4296 && peer
->nsf
[afi
][safi
]
4297 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4298 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4299 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4301 /* If this is an EVPN route, process for
4303 if (safi
== SAFI_EVPN
)
4304 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4306 /* Handle withdraw for VRF route-leaking and L3VPN */
4307 if (SAFI_UNICAST
== safi
4308 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4309 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4310 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4313 if (SAFI_MPLS_VPN
== safi
&&
4314 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4315 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4318 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4324 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4326 struct bgp_clear_node_queue
*cnq
= data
;
4327 struct bgp_node
*rn
= cnq
->rn
;
4328 struct bgp_table
*table
= bgp_node_table(rn
);
4330 bgp_unlock_node(rn
);
4331 bgp_table_unlock(table
);
4332 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4335 static void bgp_clear_node_complete(struct work_queue
*wq
)
4337 struct peer
*peer
= wq
->spec
.data
;
4339 /* Tickle FSM to start moving again */
4340 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4342 peer_unlock(peer
); /* bgp_clear_route */
4345 static void bgp_clear_node_queue_init(struct peer
*peer
)
4347 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4349 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4350 #undef CLEAR_QUEUE_NAME_LEN
4352 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4353 peer
->clear_node_queue
->spec
.hold
= 10;
4354 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4355 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4356 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4357 peer
->clear_node_queue
->spec
.max_retries
= 0;
4359 /* we only 'lock' this peer reference when the queue is actually active
4361 peer
->clear_node_queue
->spec
.data
= peer
;
4364 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4365 struct bgp_table
*table
)
4367 struct bgp_node
*rn
;
4368 int force
= bm
->process_main_queue
? 0 : 1;
4371 table
= peer
->bgp
->rib
[afi
][safi
];
4373 /* If still no table => afi/safi isn't configured at all or smth. */
4377 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4378 struct bgp_path_info
*pi
, *next
;
4379 struct bgp_adj_in
*ain
;
4380 struct bgp_adj_in
*ain_next
;
4382 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4383 * queued for every clearing peer, regardless of whether it is
4384 * relevant to the peer at hand.
4386 * Overview: There are 3 different indices which need to be
4387 * scrubbed, potentially, when a peer is removed:
4389 * 1 peer's routes visible via the RIB (ie accepted routes)
4390 * 2 peer's routes visible by the (optional) peer's adj-in index
4391 * 3 other routes visible by the peer's adj-out index
4393 * 3 there is no hurry in scrubbing, once the struct peer is
4394 * removed from bgp->peer, we could just GC such deleted peer's
4395 * adj-outs at our leisure.
4397 * 1 and 2 must be 'scrubbed' in some way, at least made
4398 * invisible via RIB index before peer session is allowed to be
4399 * brought back up. So one needs to know when such a 'search' is
4404 * - there'd be a single global queue or a single RIB walker
4405 * - rather than tracking which route_nodes still need to be
4406 * examined on a peer basis, we'd track which peers still
4409 * Given that our per-peer prefix-counts now should be reliable,
4410 * this may actually be achievable. It doesn't seem to be a huge
4411 * problem at this time,
4413 * It is possible that we have multiple paths for a prefix from
4415 * if that peer is using AddPath.
4419 ain_next
= ain
->next
;
4421 if (ain
->peer
== peer
) {
4422 bgp_adj_in_remove(rn
, ain
);
4423 bgp_unlock_node(rn
);
4429 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4431 if (pi
->peer
!= peer
)
4435 bgp_path_info_reap(rn
, pi
);
4437 struct bgp_clear_node_queue
*cnq
;
4439 /* both unlocked in bgp_clear_node_queue_del */
4440 bgp_table_lock(bgp_node_table(rn
));
4443 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4444 sizeof(struct bgp_clear_node_queue
));
4446 work_queue_add(peer
->clear_node_queue
, cnq
);
4454 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4456 struct bgp_node
*rn
;
4457 struct bgp_table
*table
;
4459 if (peer
->clear_node_queue
== NULL
)
4460 bgp_clear_node_queue_init(peer
);
4462 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4463 * Idle until it receives a Clearing_Completed event. This protects
4464 * against peers which flap faster than we can we clear, which could
4467 * a) race with routes from the new session being installed before
4468 * clear_route_node visits the node (to delete the route of that
4470 * b) resource exhaustion, clear_route_node likely leads to an entry
4471 * on the process_main queue. Fast-flapping could cause that queue
4475 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4476 * the unlock will happen upon work-queue completion; other wise, the
4477 * unlock happens at the end of this function.
4479 if (!peer
->clear_node_queue
->thread
)
4482 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4483 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4485 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4486 rn
= bgp_route_next(rn
)) {
4487 table
= bgp_node_get_bgp_table_info(rn
);
4491 bgp_clear_route_table(peer
, afi
, safi
, table
);
4494 /* unlock if no nodes got added to the clear-node-queue. */
4495 if (!peer
->clear_node_queue
->thread
)
4499 void bgp_clear_route_all(struct peer
*peer
)
4504 FOREACH_AFI_SAFI (afi
, safi
)
4505 bgp_clear_route(peer
, afi
, safi
);
4508 rfapiProcessPeerDown(peer
);
4512 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4514 struct bgp_table
*table
;
4515 struct bgp_node
*rn
;
4516 struct bgp_adj_in
*ain
;
4517 struct bgp_adj_in
*ain_next
;
4519 table
= peer
->bgp
->rib
[afi
][safi
];
4521 /* It is possible that we have multiple paths for a prefix from a peer
4522 * if that peer is using AddPath.
4524 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4528 ain_next
= ain
->next
;
4530 if (ain
->peer
== peer
) {
4531 bgp_adj_in_remove(rn
, ain
);
4532 bgp_unlock_node(rn
);
4540 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4542 struct bgp_node
*rn
;
4543 struct bgp_path_info
*pi
;
4544 struct bgp_table
*table
;
4546 if (safi
== SAFI_MPLS_VPN
) {
4547 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4548 rn
= bgp_route_next(rn
)) {
4549 struct bgp_node
*rm
;
4551 /* look for neighbor in tables */
4552 table
= bgp_node_get_bgp_table_info(rn
);
4556 for (rm
= bgp_table_top(table
); rm
;
4557 rm
= bgp_route_next(rm
))
4558 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4560 if (pi
->peer
!= peer
)
4562 if (!CHECK_FLAG(pi
->flags
,
4566 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4571 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4572 rn
= bgp_route_next(rn
))
4573 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4575 if (pi
->peer
!= peer
)
4577 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4579 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4585 int bgp_outbound_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_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4592 || FILTER_LIST_OUT_NAME(filter
)
4593 || DISTRIBUTE_OUT_NAME(filter
)))
4598 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4600 if (peer
->sort
== BGP_PEER_IBGP
)
4603 if (peer
->sort
== BGP_PEER_EBGP
4604 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4605 || FILTER_LIST_IN_NAME(filter
)
4606 || DISTRIBUTE_IN_NAME(filter
)))
4611 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4614 struct bgp_node
*rn
;
4615 struct bgp_path_info
*pi
;
4616 struct bgp_path_info
*next
;
4618 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4619 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4622 /* Unimport EVPN routes from VRFs */
4623 if (safi
== SAFI_EVPN
)
4624 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4628 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4629 && pi
->type
== ZEBRA_ROUTE_BGP
4630 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4631 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4632 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4634 if (bgp_fibupd_safi(safi
))
4635 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4637 bgp_path_info_reap(rn
, pi
);
4642 /* Delete all kernel routes. */
4643 void bgp_cleanup_routes(struct bgp
*bgp
)
4646 struct bgp_node
*rn
;
4647 struct bgp_table
*table
;
4649 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4650 if (afi
== AFI_L2VPN
)
4652 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4655 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4657 if (afi
!= AFI_L2VPN
) {
4659 safi
= SAFI_MPLS_VPN
;
4660 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4661 rn
= bgp_route_next(rn
)) {
4662 table
= bgp_node_get_bgp_table_info(rn
);
4663 if (table
!= NULL
) {
4664 bgp_cleanup_table(bgp
, table
, safi
);
4665 bgp_table_finish(&table
);
4666 bgp_node_set_bgp_table_info(rn
, NULL
);
4667 bgp_unlock_node(rn
);
4671 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4672 rn
= bgp_route_next(rn
)) {
4673 table
= bgp_node_get_bgp_table_info(rn
);
4674 if (table
!= NULL
) {
4675 bgp_cleanup_table(bgp
, table
, safi
);
4676 bgp_table_finish(&table
);
4677 bgp_node_set_bgp_table_info(rn
, NULL
);
4678 bgp_unlock_node(rn
);
4683 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4684 rn
= bgp_route_next(rn
)) {
4685 table
= bgp_node_get_bgp_table_info(rn
);
4686 if (table
!= NULL
) {
4687 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4688 bgp_table_finish(&table
);
4689 bgp_node_set_bgp_table_info(rn
, NULL
);
4690 bgp_unlock_node(rn
);
4695 void bgp_reset(void)
4698 bgp_zclient_reset();
4699 access_list_reset();
4700 prefix_list_reset();
4703 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4705 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4706 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4707 PEER_CAP_ADDPATH_AF_TX_RCV
));
4710 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4712 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4713 struct bgp_nlri
*packet
)
4722 int addpath_encoded
;
4723 uint32_t addpath_id
;
4726 lim
= pnt
+ packet
->length
;
4728 safi
= packet
->safi
;
4730 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4732 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4733 syntactic validity. If the field is syntactically incorrect,
4734 then the Error Subcode is set to Invalid Network Field. */
4735 for (; pnt
< lim
; pnt
+= psize
) {
4736 /* Clear prefix structure. */
4737 memset(&p
, 0, sizeof(struct prefix
));
4739 if (addpath_encoded
) {
4741 /* When packet overflow occurs return immediately. */
4742 if (pnt
+ BGP_ADDPATH_ID_LEN
>= lim
)
4743 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4745 memcpy(&addpath_id
, pnt
, BGP_ADDPATH_ID_LEN
);
4746 addpath_id
= ntohl(addpath_id
);
4747 pnt
+= BGP_ADDPATH_ID_LEN
;
4750 /* Fetch prefix length. */
4751 p
.prefixlen
= *pnt
++;
4752 /* afi/safi validity already verified by caller,
4753 * bgp_update_receive */
4754 p
.family
= afi2family(afi
);
4756 /* Prefix length check. */
4757 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4760 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4761 peer
->host
, p
.prefixlen
, packet
->afi
);
4762 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4765 /* Packet size overflow check. */
4766 psize
= PSIZE(p
.prefixlen
);
4768 /* When packet overflow occur return immediately. */
4769 if (pnt
+ psize
> lim
) {
4772 "%s [Error] Update packet error (prefix length %d overflows packet)",
4773 peer
->host
, p
.prefixlen
);
4774 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4777 /* Defensive coding, double-check the psize fits in a struct
4779 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4782 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4783 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4784 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4787 /* Fetch prefix from NLRI packet. */
4788 memcpy(p
.u
.val
, pnt
, psize
);
4790 /* Check address. */
4791 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4792 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4793 /* From RFC4271 Section 6.3:
4795 * If a prefix in the NLRI field is semantically
4797 * (e.g., an unexpected multicast IP address),
4799 * be logged locally, and the prefix SHOULD be
4804 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4805 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4810 /* Check address. */
4811 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4812 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4817 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4819 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4824 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4829 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4831 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4838 /* Normal process. */
4840 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4841 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4842 NULL
, NULL
, 0, 0, NULL
);
4844 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4845 safi
, ZEBRA_ROUTE_BGP
,
4846 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4849 /* Do not send BGP notification twice when maximum-prefix count
4851 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4852 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4854 /* Address family configuration mismatch. */
4856 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4859 /* Packet length consistency check. */
4863 "%s [Error] Update packet error (prefix length mismatch with total length)",
4865 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4868 return BGP_NLRI_PARSE_OK
;
4871 static struct bgp_static
*bgp_static_new(void)
4873 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4876 static void bgp_static_free(struct bgp_static
*bgp_static
)
4878 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4879 route_map_counter_decrement(bgp_static
->rmap
.map
);
4881 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4882 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4885 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4886 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4888 struct bgp_node
*rn
;
4889 struct bgp_path_info
*pi
;
4890 struct bgp_path_info
*new;
4891 struct bgp_path_info rmap_path
;
4893 struct attr
*attr_new
;
4894 route_map_result_t ret
;
4896 int vnc_implicit_withdraw
= 0;
4903 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4905 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4907 attr
.nexthop
= bgp_static
->igpnexthop
;
4908 attr
.med
= bgp_static
->igpmetric
;
4909 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4911 if (bgp_static
->atomic
)
4912 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4914 /* Store label index, if required. */
4915 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4916 attr
.label_index
= bgp_static
->label_index
;
4917 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4920 /* Apply route-map. */
4921 if (bgp_static
->rmap
.name
) {
4922 struct attr attr_tmp
= attr
;
4924 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4925 rmap_path
.peer
= bgp
->peer_self
;
4926 rmap_path
.attr
= &attr_tmp
;
4928 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4930 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4933 bgp
->peer_self
->rmap_type
= 0;
4935 if (ret
== RMAP_DENYMATCH
) {
4936 /* Free uninterned attribute. */
4937 bgp_attr_flush(&attr_tmp
);
4939 /* Unintern original. */
4940 aspath_unintern(&attr
.aspath
);
4941 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4945 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4946 bgp_attr_add_gshut_community(&attr_tmp
);
4948 attr_new
= bgp_attr_intern(&attr_tmp
);
4951 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4952 bgp_attr_add_gshut_community(&attr
);
4954 attr_new
= bgp_attr_intern(&attr
);
4957 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4958 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4959 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4963 if (attrhash_cmp(pi
->attr
, attr_new
)
4964 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4965 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4966 bgp_unlock_node(rn
);
4967 bgp_attr_unintern(&attr_new
);
4968 aspath_unintern(&attr
.aspath
);
4971 /* The attribute is changed. */
4972 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4974 /* Rewrite BGP route information. */
4975 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4976 bgp_path_info_restore(rn
, pi
);
4978 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4980 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4981 && (safi
== SAFI_UNICAST
)) {
4982 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4984 * Implicit withdraw case.
4985 * We have to do this before pi is
4988 ++vnc_implicit_withdraw
;
4989 vnc_import_bgp_del_route(bgp
, p
, pi
);
4990 vnc_import_bgp_exterior_del_route(
4995 bgp_attr_unintern(&pi
->attr
);
4996 pi
->attr
= attr_new
;
4997 pi
->uptime
= bgp_clock();
4999 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
5000 && (safi
== SAFI_UNICAST
)) {
5001 if (vnc_implicit_withdraw
) {
5002 vnc_import_bgp_add_route(bgp
, p
, pi
);
5003 vnc_import_bgp_exterior_add_route(
5009 /* Nexthop reachability check. */
5010 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5011 && (safi
== SAFI_UNICAST
5012 || safi
== SAFI_LABELED_UNICAST
)) {
5014 struct bgp
*bgp_nexthop
= bgp
;
5016 if (pi
->extra
&& pi
->extra
->bgp_orig
)
5017 bgp_nexthop
= pi
->extra
->bgp_orig
;
5019 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
5021 bgp_path_info_set_flag(rn
, pi
,
5024 if (BGP_DEBUG(nht
, NHT
)) {
5025 char buf1
[INET6_ADDRSTRLEN
];
5026 inet_ntop(p
->family
,
5030 "%s(%s): Route not in table, not advertising",
5031 __FUNCTION__
, buf1
);
5033 bgp_path_info_unset_flag(
5034 rn
, pi
, BGP_PATH_VALID
);
5037 /* Delete the NHT structure if any, if we're
5039 * enabling/disabling import check. We
5040 * deregister the route
5041 * from NHT to avoid overloading NHT and the
5042 * process interaction
5044 bgp_unlink_nexthop(pi
);
5045 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
5047 /* Process change. */
5048 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5049 bgp_process(bgp
, rn
, afi
, safi
);
5051 if (SAFI_UNICAST
== safi
5052 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5054 == BGP_INSTANCE_TYPE_DEFAULT
)) {
5055 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
5059 bgp_unlock_node(rn
);
5060 aspath_unintern(&attr
.aspath
);
5065 /* Make new BGP info. */
5066 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5068 /* Nexthop reachability check. */
5069 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
5070 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
5071 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
5072 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5074 if (BGP_DEBUG(nht
, NHT
)) {
5075 char buf1
[INET6_ADDRSTRLEN
];
5076 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
5079 "%s(%s): Route not in table, not advertising",
5080 __FUNCTION__
, buf1
);
5082 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
5085 /* Delete the NHT structure if any, if we're toggling between
5086 * enabling/disabling import check. We deregister the route
5087 * from NHT to avoid overloading NHT and the process interaction
5089 bgp_unlink_nexthop(new);
5091 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
5094 /* Aggregate address increment. */
5095 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5097 /* Register new BGP information. */
5098 bgp_path_info_add(rn
, new);
5100 /* route_node_get lock */
5101 bgp_unlock_node(rn
);
5103 /* Process change. */
5104 bgp_process(bgp
, rn
, afi
, safi
);
5106 if (SAFI_UNICAST
== safi
5107 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5108 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5109 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
5112 /* Unintern original. */
5113 aspath_unintern(&attr
.aspath
);
5116 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5119 struct bgp_node
*rn
;
5120 struct bgp_path_info
*pi
;
5122 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
5124 /* Check selected route and self inserted route. */
5125 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5126 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5127 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5130 /* Withdraw static BGP route from routing table. */
5132 if (SAFI_UNICAST
== safi
5133 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
5134 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
5135 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
5137 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5138 bgp_unlink_nexthop(pi
);
5139 bgp_path_info_delete(rn
, pi
);
5140 bgp_process(bgp
, rn
, afi
, safi
);
5143 /* Unlock bgp_node_lookup. */
5144 bgp_unlock_node(rn
);
5148 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5150 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
5151 afi_t afi
, safi_t safi
,
5152 struct prefix_rd
*prd
)
5154 struct bgp_node
*rn
;
5155 struct bgp_path_info
*pi
;
5157 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
5159 /* Check selected route and self inserted route. */
5160 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5161 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5162 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5165 /* Withdraw static BGP route from routing table. */
5168 rfapiProcessWithdraw(
5169 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
5170 1); /* Kill, since it is an administrative change */
5172 if (SAFI_MPLS_VPN
== safi
5173 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5174 vpn_leak_to_vrf_withdraw(bgp
, pi
);
5176 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5177 bgp_path_info_delete(rn
, pi
);
5178 bgp_process(bgp
, rn
, afi
, safi
);
5181 /* Unlock bgp_node_lookup. */
5182 bgp_unlock_node(rn
);
5185 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
5186 struct bgp_static
*bgp_static
, afi_t afi
,
5189 struct bgp_node
*rn
;
5190 struct bgp_path_info
*new;
5191 struct attr
*attr_new
;
5192 struct attr attr
= {0};
5193 struct bgp_path_info
*pi
;
5195 mpls_label_t label
= 0;
5197 uint32_t num_labels
= 0;
5202 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
5204 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
5207 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
5209 attr
.nexthop
= bgp_static
->igpnexthop
;
5210 attr
.med
= bgp_static
->igpmetric
;
5211 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5213 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
5214 || (safi
== SAFI_ENCAP
)) {
5215 if (afi
== AFI_IP
) {
5216 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
5217 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
5220 if (afi
== AFI_L2VPN
) {
5221 if (bgp_static
->gatewayIp
.family
== AF_INET
)
5223 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
5224 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
5225 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
5226 sizeof(struct in6_addr
));
5227 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
5228 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
5229 struct bgp_encap_type_vxlan bet
;
5230 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
5231 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
5232 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
5234 if (bgp_static
->router_mac
) {
5235 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
5238 /* Apply route-map. */
5239 if (bgp_static
->rmap
.name
) {
5240 struct attr attr_tmp
= attr
;
5241 struct bgp_path_info rmap_path
;
5242 route_map_result_t ret
;
5244 rmap_path
.peer
= bgp
->peer_self
;
5245 rmap_path
.attr
= &attr_tmp
;
5247 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
5249 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
5252 bgp
->peer_self
->rmap_type
= 0;
5254 if (ret
== RMAP_DENYMATCH
) {
5255 /* Free uninterned attribute. */
5256 bgp_attr_flush(&attr_tmp
);
5258 /* Unintern original. */
5259 aspath_unintern(&attr
.aspath
);
5260 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
5265 attr_new
= bgp_attr_intern(&attr_tmp
);
5267 attr_new
= bgp_attr_intern(&attr
);
5270 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5271 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5272 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5276 memset(&add
, 0, sizeof(union gw_addr
));
5277 if (attrhash_cmp(pi
->attr
, attr_new
)
5278 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
5279 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
5280 bgp_unlock_node(rn
);
5281 bgp_attr_unintern(&attr_new
);
5282 aspath_unintern(&attr
.aspath
);
5285 /* The attribute is changed. */
5286 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5288 /* Rewrite BGP route information. */
5289 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5290 bgp_path_info_restore(rn
, pi
);
5292 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5293 bgp_attr_unintern(&pi
->attr
);
5294 pi
->attr
= attr_new
;
5295 pi
->uptime
= bgp_clock();
5298 label
= decode_label(&pi
->extra
->label
[0]);
5301 /* Process change. */
5302 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5303 bgp_process(bgp
, rn
, afi
, safi
);
5305 if (SAFI_MPLS_VPN
== safi
5306 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5307 vpn_leak_to_vrf_update(bgp
, pi
);
5310 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5311 pi
->attr
, afi
, safi
, pi
->type
,
5312 pi
->sub_type
, &label
);
5314 bgp_unlock_node(rn
);
5315 aspath_unintern(&attr
.aspath
);
5321 /* Make new BGP info. */
5322 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5324 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5325 new->extra
= bgp_path_info_extra_new();
5327 new->extra
->label
[0] = bgp_static
->label
;
5328 new->extra
->num_labels
= num_labels
;
5331 label
= decode_label(&bgp_static
->label
);
5334 /* Aggregate address increment. */
5335 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5337 /* Register new BGP information. */
5338 bgp_path_info_add(rn
, new);
5339 /* route_node_get lock */
5340 bgp_unlock_node(rn
);
5342 /* Process change. */
5343 bgp_process(bgp
, rn
, afi
, safi
);
5345 if (SAFI_MPLS_VPN
== safi
5346 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5347 vpn_leak_to_vrf_update(bgp
, new);
5350 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5351 safi
, new->type
, new->sub_type
, &label
);
5354 /* Unintern original. */
5355 aspath_unintern(&attr
.aspath
);
5358 /* Configure static BGP network. When user don't run zebra, static
5359 route should be installed as valid. */
5360 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5361 const char *ip_str
, afi_t afi
, safi_t safi
,
5362 const char *rmap
, int backdoor
, uint32_t label_index
)
5364 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5367 struct bgp_static
*bgp_static
;
5368 struct bgp_node
*rn
;
5369 uint8_t need_update
= 0;
5371 /* Convert IP prefix string to struct prefix. */
5372 ret
= str2prefix(ip_str
, &p
);
5374 vty_out(vty
, "%% Malformed prefix\n");
5375 return CMD_WARNING_CONFIG_FAILED
;
5377 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5378 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5379 return CMD_WARNING_CONFIG_FAILED
;
5386 /* Set BGP static route configuration. */
5387 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5390 vty_out(vty
, "%% Can't find static route specified\n");
5391 return CMD_WARNING_CONFIG_FAILED
;
5394 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5396 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5397 && (label_index
!= bgp_static
->label_index
)) {
5399 "%% label-index doesn't match static route\n");
5400 return CMD_WARNING_CONFIG_FAILED
;
5403 if ((rmap
&& bgp_static
->rmap
.name
)
5404 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5406 "%% route-map name doesn't match static route\n");
5407 return CMD_WARNING_CONFIG_FAILED
;
5410 /* Update BGP RIB. */
5411 if (!bgp_static
->backdoor
)
5412 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5414 /* Clear configuration. */
5415 bgp_static_free(bgp_static
);
5416 bgp_node_set_bgp_static_info(rn
, NULL
);
5417 bgp_unlock_node(rn
);
5418 bgp_unlock_node(rn
);
5421 /* Set BGP static route configuration. */
5422 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5424 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5426 /* Configuration change. */
5427 /* Label index cannot be changed. */
5428 if (bgp_static
->label_index
!= label_index
) {
5429 vty_out(vty
, "%% cannot change label-index\n");
5430 return CMD_WARNING_CONFIG_FAILED
;
5433 /* Check previous routes are installed into BGP. */
5434 if (bgp_static
->valid
5435 && bgp_static
->backdoor
!= backdoor
)
5438 bgp_static
->backdoor
= backdoor
;
5441 XFREE(MTYPE_ROUTE_MAP_NAME
,
5442 bgp_static
->rmap
.name
);
5443 route_map_counter_decrement(
5444 bgp_static
->rmap
.map
);
5445 bgp_static
->rmap
.name
=
5446 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5447 bgp_static
->rmap
.map
=
5448 route_map_lookup_by_name(rmap
);
5449 route_map_counter_increment(
5450 bgp_static
->rmap
.map
);
5452 XFREE(MTYPE_ROUTE_MAP_NAME
,
5453 bgp_static
->rmap
.name
);
5454 route_map_counter_decrement(
5455 bgp_static
->rmap
.map
);
5456 bgp_static
->rmap
.name
= NULL
;
5457 bgp_static
->rmap
.map
= NULL
;
5458 bgp_static
->valid
= 0;
5460 bgp_unlock_node(rn
);
5462 /* New configuration. */
5463 bgp_static
= bgp_static_new();
5464 bgp_static
->backdoor
= backdoor
;
5465 bgp_static
->valid
= 0;
5466 bgp_static
->igpmetric
= 0;
5467 bgp_static
->igpnexthop
.s_addr
= 0;
5468 bgp_static
->label_index
= label_index
;
5471 XFREE(MTYPE_ROUTE_MAP_NAME
,
5472 bgp_static
->rmap
.name
);
5473 route_map_counter_decrement(
5474 bgp_static
->rmap
.map
);
5475 bgp_static
->rmap
.name
=
5476 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5477 bgp_static
->rmap
.map
=
5478 route_map_lookup_by_name(rmap
);
5479 route_map_counter_increment(
5480 bgp_static
->rmap
.map
);
5482 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5485 bgp_static
->valid
= 1;
5487 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5489 if (!bgp_static
->backdoor
)
5490 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5496 void bgp_static_add(struct bgp
*bgp
)
5500 struct bgp_node
*rn
;
5501 struct bgp_node
*rm
;
5502 struct bgp_table
*table
;
5503 struct bgp_static
*bgp_static
;
5505 FOREACH_AFI_SAFI (afi
, safi
)
5506 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5507 rn
= bgp_route_next(rn
)) {
5508 if (!bgp_node_has_bgp_path_info_data(rn
))
5511 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5512 || (safi
== SAFI_EVPN
)) {
5513 table
= bgp_node_get_bgp_table_info(rn
);
5515 for (rm
= bgp_table_top(table
); rm
;
5516 rm
= bgp_route_next(rm
)) {
5518 bgp_node_get_bgp_static_info(
5520 bgp_static_update_safi(bgp
, &rm
->p
,
5527 bgp_node_get_bgp_static_info(rn
), afi
,
5533 /* Called from bgp_delete(). Delete all static routes from the BGP
5535 void bgp_static_delete(struct bgp
*bgp
)
5539 struct bgp_node
*rn
;
5540 struct bgp_node
*rm
;
5541 struct bgp_table
*table
;
5542 struct bgp_static
*bgp_static
;
5544 FOREACH_AFI_SAFI (afi
, safi
)
5545 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5546 rn
= bgp_route_next(rn
)) {
5547 if (!bgp_node_has_bgp_path_info_data(rn
))
5550 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5551 || (safi
== SAFI_EVPN
)) {
5552 table
= bgp_node_get_bgp_table_info(rn
);
5554 for (rm
= bgp_table_top(table
); rm
;
5555 rm
= bgp_route_next(rm
)) {
5557 bgp_node_get_bgp_static_info(
5562 bgp_static_withdraw_safi(
5563 bgp
, &rm
->p
, AFI_IP
, safi
,
5564 (struct prefix_rd
*)&rn
->p
);
5565 bgp_static_free(bgp_static
);
5566 bgp_node_set_bgp_static_info(rn
, NULL
);
5567 bgp_unlock_node(rn
);
5570 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5571 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5572 bgp_static_free(bgp_static
);
5573 bgp_node_set_bgp_static_info(rn
, NULL
);
5574 bgp_unlock_node(rn
);
5579 void bgp_static_redo_import_check(struct bgp
*bgp
)
5583 struct bgp_node
*rn
;
5584 struct bgp_node
*rm
;
5585 struct bgp_table
*table
;
5586 struct bgp_static
*bgp_static
;
5588 /* Use this flag to force reprocessing of the route */
5589 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5590 FOREACH_AFI_SAFI (afi
, safi
) {
5591 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5592 rn
= bgp_route_next(rn
)) {
5593 if (!bgp_node_has_bgp_path_info_data(rn
))
5596 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5597 || (safi
== SAFI_EVPN
)) {
5598 table
= bgp_node_get_bgp_table_info(rn
);
5600 for (rm
= bgp_table_top(table
); rm
;
5601 rm
= bgp_route_next(rm
)) {
5603 bgp_node_get_bgp_static_info(
5605 bgp_static_update_safi(bgp
, &rm
->p
,
5610 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5611 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5616 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5619 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5622 struct bgp_table
*table
;
5623 struct bgp_node
*rn
;
5624 struct bgp_path_info
*pi
;
5626 /* Do not install the aggregate route if BGP is in the
5627 * process of termination.
5629 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5630 (bgp
->peer_self
== NULL
))
5633 table
= bgp
->rib
[afi
][safi
];
5634 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5635 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5636 if (pi
->peer
== bgp
->peer_self
5637 && ((pi
->type
== ZEBRA_ROUTE_BGP
5638 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5639 || (pi
->type
!= ZEBRA_ROUTE_BGP
5641 == BGP_ROUTE_REDISTRIBUTE
))) {
5642 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5644 bgp_unlink_nexthop(pi
);
5645 bgp_path_info_delete(rn
, pi
);
5646 bgp_process(bgp
, rn
, afi
, safi
);
5653 * Purge all networks and redistributed routes from routing table.
5654 * Invoked upon the instance going down.
5656 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5661 FOREACH_AFI_SAFI (afi
, safi
)
5662 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5667 * Currently this is used to set static routes for VPN and ENCAP.
5668 * I think it can probably be factored with bgp_static_set.
5670 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5671 const char *ip_str
, const char *rd_str
,
5672 const char *label_str
, const char *rmap_str
,
5673 int evpn_type
, const char *esi
, const char *gwip
,
5674 const char *ethtag
, const char *routermac
)
5676 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5679 struct prefix_rd prd
;
5680 struct bgp_node
*prn
;
5681 struct bgp_node
*rn
;
5682 struct bgp_table
*table
;
5683 struct bgp_static
*bgp_static
;
5684 mpls_label_t label
= MPLS_INVALID_LABEL
;
5685 struct prefix gw_ip
;
5687 /* validate ip prefix */
5688 ret
= str2prefix(ip_str
, &p
);
5690 vty_out(vty
, "%% Malformed prefix\n");
5691 return CMD_WARNING_CONFIG_FAILED
;
5694 if ((afi
== AFI_L2VPN
)
5695 && (bgp_build_evpn_prefix(evpn_type
,
5696 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5697 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5698 return CMD_WARNING_CONFIG_FAILED
;
5701 ret
= str2prefix_rd(rd_str
, &prd
);
5703 vty_out(vty
, "%% Malformed rd\n");
5704 return CMD_WARNING_CONFIG_FAILED
;
5708 unsigned long label_val
;
5709 label_val
= strtoul(label_str
, NULL
, 10);
5710 encode_label(label_val
, &label
);
5713 if (safi
== SAFI_EVPN
) {
5714 if (esi
&& str2esi(esi
, NULL
) == 0) {
5715 vty_out(vty
, "%% Malformed ESI\n");
5716 return CMD_WARNING_CONFIG_FAILED
;
5718 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5719 vty_out(vty
, "%% Malformed Router MAC\n");
5720 return CMD_WARNING_CONFIG_FAILED
;
5723 memset(&gw_ip
, 0, sizeof(struct prefix
));
5724 ret
= str2prefix(gwip
, &gw_ip
);
5726 vty_out(vty
, "%% Malformed GatewayIp\n");
5727 return CMD_WARNING_CONFIG_FAILED
;
5729 if ((gw_ip
.family
== AF_INET
5730 && is_evpn_prefix_ipaddr_v6(
5731 (struct prefix_evpn
*)&p
))
5732 || (gw_ip
.family
== AF_INET6
5733 && is_evpn_prefix_ipaddr_v4(
5734 (struct prefix_evpn
*)&p
))) {
5736 "%% GatewayIp family differs with IP prefix\n");
5737 return CMD_WARNING_CONFIG_FAILED
;
5741 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5742 if (!bgp_node_has_bgp_path_info_data(prn
))
5743 bgp_node_set_bgp_table_info(prn
,
5744 bgp_table_init(bgp
, afi
, safi
));
5745 table
= bgp_node_get_bgp_table_info(prn
);
5747 rn
= bgp_node_get(table
, &p
);
5749 if (bgp_node_has_bgp_path_info_data(rn
)) {
5750 vty_out(vty
, "%% Same network configuration exists\n");
5751 bgp_unlock_node(rn
);
5753 /* New configuration. */
5754 bgp_static
= bgp_static_new();
5755 bgp_static
->backdoor
= 0;
5756 bgp_static
->valid
= 0;
5757 bgp_static
->igpmetric
= 0;
5758 bgp_static
->igpnexthop
.s_addr
= 0;
5759 bgp_static
->label
= label
;
5760 bgp_static
->prd
= prd
;
5763 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5764 route_map_counter_decrement(bgp_static
->rmap
.map
);
5765 bgp_static
->rmap
.name
=
5766 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5767 bgp_static
->rmap
.map
=
5768 route_map_lookup_by_name(rmap_str
);
5769 route_map_counter_increment(bgp_static
->rmap
.map
);
5772 if (safi
== SAFI_EVPN
) {
5774 bgp_static
->eth_s_id
=
5776 sizeof(struct eth_segment_id
));
5777 str2esi(esi
, bgp_static
->eth_s_id
);
5780 bgp_static
->router_mac
=
5781 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5782 (void)prefix_str2mac(routermac
,
5783 bgp_static
->router_mac
);
5786 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5788 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5790 bgp_static
->valid
= 1;
5791 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5797 /* Configure static BGP network. */
5798 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5799 const char *ip_str
, const char *rd_str
,
5800 const char *label_str
, int evpn_type
, const char *esi
,
5801 const char *gwip
, const char *ethtag
)
5803 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5806 struct prefix_rd prd
;
5807 struct bgp_node
*prn
;
5808 struct bgp_node
*rn
;
5809 struct bgp_table
*table
;
5810 struct bgp_static
*bgp_static
;
5811 mpls_label_t label
= MPLS_INVALID_LABEL
;
5813 /* Convert IP prefix string to struct prefix. */
5814 ret
= str2prefix(ip_str
, &p
);
5816 vty_out(vty
, "%% Malformed prefix\n");
5817 return CMD_WARNING_CONFIG_FAILED
;
5820 if ((afi
== AFI_L2VPN
)
5821 && (bgp_build_evpn_prefix(evpn_type
,
5822 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5823 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5824 return CMD_WARNING_CONFIG_FAILED
;
5826 ret
= str2prefix_rd(rd_str
, &prd
);
5828 vty_out(vty
, "%% Malformed rd\n");
5829 return CMD_WARNING_CONFIG_FAILED
;
5833 unsigned long label_val
;
5834 label_val
= strtoul(label_str
, NULL
, 10);
5835 encode_label(label_val
, &label
);
5838 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5839 if (!bgp_node_has_bgp_path_info_data(prn
))
5840 bgp_node_set_bgp_table_info(prn
,
5841 bgp_table_init(bgp
, afi
, safi
));
5843 bgp_unlock_node(prn
);
5844 table
= bgp_node_get_bgp_table_info(prn
);
5846 rn
= bgp_node_lookup(table
, &p
);
5849 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5851 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5852 bgp_static_free(bgp_static
);
5853 bgp_node_set_bgp_static_info(rn
, NULL
);
5854 bgp_unlock_node(rn
);
5855 bgp_unlock_node(rn
);
5857 vty_out(vty
, "%% Can't find the route\n");
5862 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5863 const char *rmap_name
)
5865 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5866 struct bgp_rmap
*rmap
;
5868 rmap
= &bgp
->table_map
[afi
][safi
];
5870 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5871 route_map_counter_decrement(rmap
->map
);
5872 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5873 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5874 route_map_counter_increment(rmap
->map
);
5876 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5877 route_map_counter_decrement(rmap
->map
);
5882 if (bgp_fibupd_safi(safi
))
5883 bgp_zebra_announce_table(bgp
, afi
, safi
);
5888 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5889 const char *rmap_name
)
5891 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5892 struct bgp_rmap
*rmap
;
5894 rmap
= &bgp
->table_map
[afi
][safi
];
5895 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5896 route_map_counter_decrement(rmap
->map
);
5900 if (bgp_fibupd_safi(safi
))
5901 bgp_zebra_announce_table(bgp
, afi
, safi
);
5906 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5909 if (bgp
->table_map
[afi
][safi
].name
) {
5910 vty_out(vty
, " table-map %s\n",
5911 bgp
->table_map
[afi
][safi
].name
);
5915 DEFUN (bgp_table_map
,
5918 "BGP table to RIB route download filter\n"
5919 "Name of the route map\n")
5922 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5923 argv
[idx_word
]->arg
);
5925 DEFUN (no_bgp_table_map
,
5926 no_bgp_table_map_cmd
,
5927 "no table-map WORD",
5929 "BGP table to RIB route download filter\n"
5930 "Name of the route map\n")
5933 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5934 argv
[idx_word
]->arg
);
5940 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5941 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5942 backdoor$backdoor}]",
5944 "Specify a network to announce via BGP\n"
5949 "Route-map to modify the attributes\n"
5950 "Name of the route map\n"
5951 "Label index to associate with the prefix\n"
5952 "Label index value\n"
5953 "Specify a BGP backdoor route\n")
5955 char addr_prefix_str
[BUFSIZ
];
5960 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5963 vty_out(vty
, "%% Inconsistent address and mask\n");
5964 return CMD_WARNING_CONFIG_FAILED
;
5968 return bgp_static_set(
5969 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5970 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5971 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5974 DEFPY(ipv6_bgp_network
,
5975 ipv6_bgp_network_cmd
,
5976 "[no] network X:X::X:X/M$prefix \
5977 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5979 "Specify a network to announce via BGP\n"
5981 "Route-map to modify the attributes\n"
5982 "Name of the route map\n"
5983 "Label index to associate with the prefix\n"
5984 "Label index value\n")
5986 return bgp_static_set(
5987 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5988 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5991 static struct bgp_aggregate
*bgp_aggregate_new(void)
5993 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5996 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5998 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5999 route_map_counter_decrement(aggregate
->rmap
.map
);
6000 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
6003 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
6004 struct aspath
*aspath
,
6005 struct community
*comm
,
6006 struct ecommunity
*ecomm
,
6007 struct lcommunity
*lcomm
)
6009 static struct aspath
*ae
= NULL
;
6012 ae
= aspath_empty();
6017 if (origin
!= pi
->attr
->origin
)
6020 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
6023 if (!community_cmp(pi
->attr
->community
, comm
))
6026 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
6029 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
6032 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
6038 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
6039 struct prefix
*p
, uint8_t origin
,
6040 struct aspath
*aspath
,
6041 struct community
*community
,
6042 struct ecommunity
*ecommunity
,
6043 struct lcommunity
*lcommunity
,
6044 uint8_t atomic_aggregate
,
6045 struct bgp_aggregate
*aggregate
)
6047 struct bgp_node
*rn
;
6048 struct bgp_table
*table
;
6049 struct bgp_path_info
*pi
, *orig
, *new;
6052 table
= bgp
->rib
[afi
][safi
];
6054 rn
= bgp_node_get(table
, p
);
6056 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6057 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
6058 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6061 if (aggregate
->count
> 0) {
6063 * If the aggregate information has not changed
6064 * no need to re-install it again.
6066 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
6067 ecommunity
, lcommunity
)) {
6068 bgp_unlock_node(rn
);
6071 aspath_free(aspath
);
6073 community_free(&community
);
6075 ecommunity_free(&ecommunity
);
6077 lcommunity_free(&lcommunity
);
6083 * Mark the old as unusable
6086 bgp_path_info_delete(rn
, pi
);
6088 attr
= bgp_attr_aggregate_intern(
6089 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
6090 aggregate
, atomic_aggregate
, p
);
6093 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
6097 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
6098 bgp
->peer_self
, attr
, rn
);
6100 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6102 bgp_path_info_add(rn
, new);
6103 bgp_process(bgp
, rn
, afi
, safi
);
6105 for (pi
= orig
; pi
; pi
= pi
->next
)
6106 if (pi
->peer
== bgp
->peer_self
6107 && pi
->type
== ZEBRA_ROUTE_BGP
6108 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6111 /* Withdraw static BGP route from routing table. */
6113 bgp_path_info_delete(rn
, pi
);
6114 bgp_process(bgp
, rn
, afi
, safi
);
6118 bgp_unlock_node(rn
);
6121 /* Update an aggregate as routes are added/removed from the BGP table */
6122 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
6123 afi_t afi
, safi_t safi
,
6124 struct bgp_aggregate
*aggregate
)
6126 struct bgp_table
*table
;
6127 struct bgp_node
*top
;
6128 struct bgp_node
*rn
;
6130 struct aspath
*aspath
= NULL
;
6131 struct community
*community
= NULL
;
6132 struct ecommunity
*ecommunity
= NULL
;
6133 struct lcommunity
*lcommunity
= NULL
;
6134 struct bgp_path_info
*pi
;
6135 unsigned long match
= 0;
6136 uint8_t atomic_aggregate
= 0;
6138 /* If the bgp instance is being deleted or self peer is deleted
6139 * then do not create aggregate route
6141 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
6142 (bgp
->peer_self
== NULL
))
6145 /* ORIGIN attribute: If at least one route among routes that are
6146 aggregated has ORIGIN with the value INCOMPLETE, then the
6147 aggregated route must have the ORIGIN attribute with the value
6148 INCOMPLETE. Otherwise, if at least one route among routes that
6149 are aggregated has ORIGIN with the value EGP, then the aggregated
6150 route must have the origin attribute with the value EGP. In all
6151 other case the value of the ORIGIN attribute of the aggregated
6152 route is INTERNAL. */
6153 origin
= BGP_ORIGIN_IGP
;
6155 table
= bgp
->rib
[afi
][safi
];
6157 top
= bgp_node_get(table
, p
);
6158 for (rn
= bgp_node_get(table
, p
); rn
;
6159 rn
= bgp_route_next_until(rn
, top
)) {
6160 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6165 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6166 if (BGP_PATH_HOLDDOWN(pi
))
6170 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
6171 atomic_aggregate
= 1;
6173 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6177 * summary-only aggregate route suppress
6178 * aggregated route announcements.
6180 if (aggregate
->summary_only
) {
6181 (bgp_path_info_extra_get(pi
))->suppress
++;
6182 bgp_path_info_set_flag(rn
, pi
,
6183 BGP_PATH_ATTR_CHANGED
);
6190 * If at least one route among routes that are
6191 * aggregated has ORIGIN with the value INCOMPLETE,
6192 * then the aggregated route MUST have the ORIGIN
6193 * attribute with the value INCOMPLETE. Otherwise, if
6194 * at least one route among routes that are aggregated
6195 * has ORIGIN with the value EGP, then the aggregated
6196 * route MUST have the ORIGIN attribute with the value
6199 switch (pi
->attr
->origin
) {
6200 case BGP_ORIGIN_INCOMPLETE
:
6201 aggregate
->incomplete_origin_count
++;
6203 case BGP_ORIGIN_EGP
:
6204 aggregate
->egp_origin_count
++;
6212 if (!aggregate
->as_set
)
6216 * as-set aggregate route generate origin, as path,
6217 * and community aggregation.
6219 /* Compute aggregate route's as-path.
6221 bgp_compute_aggregate_aspath_hash(aggregate
,
6224 /* Compute aggregate route's community.
6226 if (pi
->attr
->community
)
6227 bgp_compute_aggregate_community_hash(
6229 pi
->attr
->community
);
6231 /* Compute aggregate route's extended community.
6233 if (pi
->attr
->ecommunity
)
6234 bgp_compute_aggregate_ecommunity_hash(
6236 pi
->attr
->ecommunity
);
6238 /* Compute aggregate route's large community.
6240 if (pi
->attr
->lcommunity
)
6241 bgp_compute_aggregate_lcommunity_hash(
6243 pi
->attr
->lcommunity
);
6246 bgp_process(bgp
, rn
, afi
, safi
);
6248 if (aggregate
->as_set
) {
6249 bgp_compute_aggregate_aspath_val(aggregate
);
6250 bgp_compute_aggregate_community_val(aggregate
);
6251 bgp_compute_aggregate_ecommunity_val(aggregate
);
6252 bgp_compute_aggregate_lcommunity_val(aggregate
);
6256 bgp_unlock_node(top
);
6259 if (aggregate
->incomplete_origin_count
> 0)
6260 origin
= BGP_ORIGIN_INCOMPLETE
;
6261 else if (aggregate
->egp_origin_count
> 0)
6262 origin
= BGP_ORIGIN_EGP
;
6264 if (aggregate
->as_set
) {
6265 if (aggregate
->aspath
)
6266 /* Retrieve aggregate route's as-path.
6268 aspath
= aspath_dup(aggregate
->aspath
);
6270 if (aggregate
->community
)
6271 /* Retrieve aggregate route's community.
6273 community
= community_dup(aggregate
->community
);
6275 if (aggregate
->ecommunity
)
6276 /* Retrieve aggregate route's ecommunity.
6278 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6280 if (aggregate
->lcommunity
)
6281 /* Retrieve aggregate route's lcommunity.
6283 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6286 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6287 ecommunity
, lcommunity
, atomic_aggregate
,
6291 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6292 safi_t safi
, struct bgp_aggregate
*aggregate
)
6294 struct bgp_table
*table
;
6295 struct bgp_node
*top
;
6296 struct bgp_node
*rn
;
6297 struct bgp_path_info
*pi
;
6298 unsigned long match
;
6300 table
= bgp
->rib
[afi
][safi
];
6302 /* If routes exists below this node, generate aggregate routes. */
6303 top
= bgp_node_get(table
, p
);
6304 for (rn
= bgp_node_get(table
, p
); rn
;
6305 rn
= bgp_route_next_until(rn
, top
)) {
6306 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6310 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6311 if (BGP_PATH_HOLDDOWN(pi
))
6314 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6317 if (aggregate
->summary_only
&& pi
->extra
) {
6318 pi
->extra
->suppress
--;
6320 if (pi
->extra
->suppress
== 0) {
6321 bgp_path_info_set_flag(
6322 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6328 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6329 aggregate
->incomplete_origin_count
--;
6330 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6331 aggregate
->egp_origin_count
--;
6333 if (aggregate
->as_set
) {
6334 /* Remove as-path from aggregate.
6336 bgp_remove_aspath_from_aggregate_hash(
6340 if (pi
->attr
->community
)
6341 /* Remove community from aggregate.
6343 bgp_remove_comm_from_aggregate_hash(
6345 pi
->attr
->community
);
6347 if (pi
->attr
->ecommunity
)
6348 /* Remove ecommunity from aggregate.
6350 bgp_remove_ecomm_from_aggregate_hash(
6352 pi
->attr
->ecommunity
);
6354 if (pi
->attr
->lcommunity
)
6355 /* Remove lcommunity from aggregate.
6357 bgp_remove_lcomm_from_aggregate_hash(
6359 pi
->attr
->lcommunity
);
6364 /* If this node was suppressed, process the change. */
6366 bgp_process(bgp
, rn
, afi
, safi
);
6368 if (aggregate
->as_set
) {
6369 aspath_free(aggregate
->aspath
);
6370 aggregate
->aspath
= NULL
;
6371 if (aggregate
->community
)
6372 community_free(&aggregate
->community
);
6373 if (aggregate
->ecommunity
)
6374 ecommunity_free(&aggregate
->ecommunity
);
6375 if (aggregate
->lcommunity
)
6376 lcommunity_free(&aggregate
->lcommunity
);
6379 bgp_unlock_node(top
);
6382 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6383 struct bgp_path_info
*pinew
, afi_t afi
,
6385 struct bgp_aggregate
*aggregate
)
6388 struct aspath
*aspath
= NULL
;
6389 uint8_t atomic_aggregate
= 0;
6390 struct community
*community
= NULL
;
6391 struct ecommunity
*ecommunity
= NULL
;
6392 struct lcommunity
*lcommunity
= NULL
;
6394 /* ORIGIN attribute: If at least one route among routes that are
6395 * aggregated has ORIGIN with the value INCOMPLETE, then the
6396 * aggregated route must have the ORIGIN attribute with the value
6397 * INCOMPLETE. Otherwise, if at least one route among routes that
6398 * are aggregated has ORIGIN with the value EGP, then the aggregated
6399 * route must have the origin attribute with the value EGP. In all
6400 * other case the value of the ORIGIN attribute of the aggregated
6401 * route is INTERNAL.
6403 origin
= BGP_ORIGIN_IGP
;
6407 if (aggregate
->summary_only
)
6408 (bgp_path_info_extra_get(pinew
))->suppress
++;
6410 switch (pinew
->attr
->origin
) {
6411 case BGP_ORIGIN_INCOMPLETE
:
6412 aggregate
->incomplete_origin_count
++;
6414 case BGP_ORIGIN_EGP
:
6415 aggregate
->egp_origin_count
++;
6423 if (aggregate
->incomplete_origin_count
> 0)
6424 origin
= BGP_ORIGIN_INCOMPLETE
;
6425 else if (aggregate
->egp_origin_count
> 0)
6426 origin
= BGP_ORIGIN_EGP
;
6428 if (aggregate
->as_set
) {
6429 /* Compute aggregate route's as-path.
6431 bgp_compute_aggregate_aspath(aggregate
,
6432 pinew
->attr
->aspath
);
6434 /* Compute aggregate route's community.
6436 if (pinew
->attr
->community
)
6437 bgp_compute_aggregate_community(
6439 pinew
->attr
->community
);
6441 /* Compute aggregate route's extended community.
6443 if (pinew
->attr
->ecommunity
)
6444 bgp_compute_aggregate_ecommunity(
6446 pinew
->attr
->ecommunity
);
6448 /* Compute aggregate route's large community.
6450 if (pinew
->attr
->lcommunity
)
6451 bgp_compute_aggregate_lcommunity(
6453 pinew
->attr
->lcommunity
);
6455 /* Retrieve aggregate route's as-path.
6457 if (aggregate
->aspath
)
6458 aspath
= aspath_dup(aggregate
->aspath
);
6460 /* Retrieve aggregate route's community.
6462 if (aggregate
->community
)
6463 community
= community_dup(aggregate
->community
);
6465 /* Retrieve aggregate route's ecommunity.
6467 if (aggregate
->ecommunity
)
6468 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6470 /* Retrieve aggregate route's lcommunity.
6472 if (aggregate
->lcommunity
)
6473 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6476 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6477 aspath
, community
, ecommunity
,
6478 lcommunity
, atomic_aggregate
, aggregate
);
6481 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6483 struct bgp_path_info
*pi
,
6484 struct bgp_aggregate
*aggregate
,
6485 struct prefix
*aggr_p
)
6488 struct aspath
*aspath
= NULL
;
6489 uint8_t atomic_aggregate
= 0;
6490 struct community
*community
= NULL
;
6491 struct ecommunity
*ecommunity
= NULL
;
6492 struct lcommunity
*lcommunity
= NULL
;
6493 unsigned long match
= 0;
6495 if (BGP_PATH_HOLDDOWN(pi
))
6498 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6501 if (aggregate
->summary_only
6503 && pi
->extra
->suppress
> 0) {
6504 pi
->extra
->suppress
--;
6506 if (pi
->extra
->suppress
== 0) {
6507 bgp_path_info_set_flag(pi
->net
, pi
,
6508 BGP_PATH_ATTR_CHANGED
);
6513 if (aggregate
->count
> 0)
6516 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6517 aggregate
->incomplete_origin_count
--;
6518 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6519 aggregate
->egp_origin_count
--;
6521 if (aggregate
->as_set
) {
6522 /* Remove as-path from aggregate.
6524 bgp_remove_aspath_from_aggregate(aggregate
,
6527 if (pi
->attr
->community
)
6528 /* Remove community from aggregate.
6530 bgp_remove_community_from_aggregate(
6532 pi
->attr
->community
);
6534 if (pi
->attr
->ecommunity
)
6535 /* Remove ecommunity from aggregate.
6537 bgp_remove_ecommunity_from_aggregate(
6539 pi
->attr
->ecommunity
);
6541 if (pi
->attr
->lcommunity
)
6542 /* Remove lcommunity from aggregate.
6544 bgp_remove_lcommunity_from_aggregate(
6546 pi
->attr
->lcommunity
);
6549 /* If this node was suppressed, process the change. */
6551 bgp_process(bgp
, pi
->net
, afi
, safi
);
6553 origin
= BGP_ORIGIN_IGP
;
6554 if (aggregate
->incomplete_origin_count
> 0)
6555 origin
= BGP_ORIGIN_INCOMPLETE
;
6556 else if (aggregate
->egp_origin_count
> 0)
6557 origin
= BGP_ORIGIN_EGP
;
6559 if (aggregate
->as_set
) {
6560 /* Retrieve aggregate route's as-path.
6562 if (aggregate
->aspath
)
6563 aspath
= aspath_dup(aggregate
->aspath
);
6565 /* Retrieve aggregate route's community.
6567 if (aggregate
->community
)
6568 community
= community_dup(aggregate
->community
);
6570 /* Retrieve aggregate route's ecommunity.
6572 if (aggregate
->ecommunity
)
6573 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6575 /* Retrieve aggregate route's lcommunity.
6577 if (aggregate
->lcommunity
)
6578 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6581 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6582 aspath
, community
, ecommunity
,
6583 lcommunity
, atomic_aggregate
, aggregate
);
6586 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6587 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6589 struct bgp_node
*child
;
6590 struct bgp_node
*rn
;
6591 struct bgp_aggregate
*aggregate
;
6592 struct bgp_table
*table
;
6594 table
= bgp
->aggregate
[afi
][safi
];
6596 /* No aggregates configured. */
6597 if (bgp_table_top_nolock(table
) == NULL
)
6600 if (p
->prefixlen
== 0)
6603 if (BGP_PATH_HOLDDOWN(pi
))
6606 child
= bgp_node_get(table
, p
);
6608 /* Aggregate address configuration check. */
6609 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6610 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6611 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6612 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6616 bgp_unlock_node(child
);
6619 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6620 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6622 struct bgp_node
*child
;
6623 struct bgp_node
*rn
;
6624 struct bgp_aggregate
*aggregate
;
6625 struct bgp_table
*table
;
6627 table
= bgp
->aggregate
[afi
][safi
];
6629 /* No aggregates configured. */
6630 if (bgp_table_top_nolock(table
) == NULL
)
6633 if (p
->prefixlen
== 0)
6636 child
= bgp_node_get(table
, p
);
6638 /* Aggregate address configuration check. */
6639 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6640 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6641 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6642 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6643 del
, aggregate
, &rn
->p
);
6646 bgp_unlock_node(child
);
6649 /* Aggregate route attribute. */
6650 #define AGGREGATE_SUMMARY_ONLY 1
6651 #define AGGREGATE_AS_SET 1
6652 #define AGGREGATE_AS_UNSET 0
6654 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6655 afi_t afi
, safi_t safi
)
6657 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6660 struct bgp_node
*rn
;
6661 struct bgp_aggregate
*aggregate
;
6663 /* Convert string to prefix structure. */
6664 ret
= str2prefix(prefix_str
, &p
);
6666 vty_out(vty
, "Malformed prefix\n");
6667 return CMD_WARNING_CONFIG_FAILED
;
6671 /* Old configuration check. */
6672 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6675 "%% There is no aggregate-address configuration.\n");
6676 return CMD_WARNING_CONFIG_FAILED
;
6679 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6680 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6681 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6682 NULL
, NULL
, 0, aggregate
);
6684 /* Unlock aggregate address configuration. */
6685 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6687 if (aggregate
->community
)
6688 community_free(&aggregate
->community
);
6690 if (aggregate
->community_hash
) {
6691 /* Delete all communities in the hash.
6693 hash_clean(aggregate
->community_hash
,
6694 bgp_aggr_community_remove
);
6695 /* Free up the community_hash.
6697 hash_free(aggregate
->community_hash
);
6700 if (aggregate
->ecommunity
)
6701 ecommunity_free(&aggregate
->ecommunity
);
6703 if (aggregate
->ecommunity_hash
) {
6704 /* Delete all ecommunities in the hash.
6706 hash_clean(aggregate
->ecommunity_hash
,
6707 bgp_aggr_ecommunity_remove
);
6708 /* Free up the ecommunity_hash.
6710 hash_free(aggregate
->ecommunity_hash
);
6713 if (aggregate
->lcommunity
)
6714 lcommunity_free(&aggregate
->lcommunity
);
6716 if (aggregate
->lcommunity_hash
) {
6717 /* Delete all lcommunities in the hash.
6719 hash_clean(aggregate
->lcommunity_hash
,
6720 bgp_aggr_lcommunity_remove
);
6721 /* Free up the lcommunity_hash.
6723 hash_free(aggregate
->lcommunity_hash
);
6726 if (aggregate
->aspath
)
6727 aspath_free(aggregate
->aspath
);
6729 if (aggregate
->aspath_hash
) {
6730 /* Delete all as-paths in the hash.
6732 hash_clean(aggregate
->aspath_hash
,
6733 bgp_aggr_aspath_remove
);
6734 /* Free up the aspath_hash.
6736 hash_free(aggregate
->aspath_hash
);
6739 bgp_aggregate_free(aggregate
);
6740 bgp_unlock_node(rn
);
6741 bgp_unlock_node(rn
);
6746 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6747 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6750 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6753 struct bgp_node
*rn
;
6754 struct bgp_aggregate
*aggregate
;
6755 uint8_t as_set_new
= as_set
;
6757 /* Convert string to prefix structure. */
6758 ret
= str2prefix(prefix_str
, &p
);
6760 vty_out(vty
, "Malformed prefix\n");
6761 return CMD_WARNING_CONFIG_FAILED
;
6765 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6766 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6767 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6769 return CMD_WARNING_CONFIG_FAILED
;
6772 /* Old configuration check. */
6773 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6774 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6777 vty_out(vty
, "There is already same aggregate network.\n");
6778 /* try to remove the old entry */
6779 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6781 vty_out(vty
, "Error deleting aggregate.\n");
6782 bgp_unlock_node(rn
);
6783 return CMD_WARNING_CONFIG_FAILED
;
6787 /* Make aggregate address structure. */
6788 aggregate
= bgp_aggregate_new();
6789 aggregate
->summary_only
= summary_only
;
6791 /* Network operators MUST NOT locally generate any new
6792 * announcements containing AS_SET or AS_CONFED_SET. If they have
6793 * announced routes with AS_SET or AS_CONFED_SET in them, then they
6794 * SHOULD withdraw those routes and re-announce routes for the
6795 * aggregate or component prefixes (i.e., the more-specific routes
6796 * subsumed by the previously aggregated route) without AS_SET
6797 * or AS_CONFED_SET in the updates.
6799 if (bgp
->reject_as_sets
== BGP_REJECT_AS_SETS_ENABLED
) {
6800 if (as_set
== AGGREGATE_AS_SET
) {
6801 as_set_new
= AGGREGATE_AS_UNSET
;
6803 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.\n",
6806 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
6810 aggregate
->as_set
= as_set_new
;
6811 aggregate
->safi
= safi
;
6814 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6815 route_map_counter_decrement(aggregate
->rmap
.map
);
6816 aggregate
->rmap
.name
=
6817 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6818 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6819 route_map_counter_increment(aggregate
->rmap
.map
);
6821 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6823 /* Aggregate address insert into BGP routing table. */
6824 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6829 DEFUN (aggregate_address
,
6830 aggregate_address_cmd
,
6831 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6832 "Configure BGP aggregate entries\n"
6833 "Aggregate prefix\n"
6834 "Generate AS set path information\n"
6835 "Filter more specific routes from updates\n"
6836 "Filter more specific routes from updates\n"
6837 "Generate AS set path information\n"
6838 "Apply route map to aggregate network\n"
6839 "Name of route map\n")
6842 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6843 char *prefix
= argv
[idx
]->arg
;
6845 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6846 : AGGREGATE_AS_UNSET
;
6848 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6849 ? AGGREGATE_SUMMARY_ONLY
6853 argv_find(argv
, argc
, "WORD", &idx
);
6855 rmap
= argv
[idx
]->arg
;
6857 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6858 rmap
, summary_only
, as_set
);
6861 DEFUN (aggregate_address_mask
,
6862 aggregate_address_mask_cmd
,
6863 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6864 "Configure BGP aggregate entries\n"
6865 "Aggregate address\n"
6867 "Generate AS set path information\n"
6868 "Filter more specific routes from updates\n"
6869 "Filter more specific routes from updates\n"
6870 "Generate AS set path information\n"
6871 "Apply route map to aggregate network\n"
6872 "Name of route map\n")
6875 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6876 char *prefix
= argv
[idx
]->arg
;
6877 char *mask
= argv
[idx
+ 1]->arg
;
6880 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6881 : AGGREGATE_AS_UNSET
;
6883 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6884 ? AGGREGATE_SUMMARY_ONLY
6887 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6889 rmap
= argv
[idx
]->arg
;
6891 char prefix_str
[BUFSIZ
];
6892 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6895 vty_out(vty
, "%% Inconsistent address and mask\n");
6896 return CMD_WARNING_CONFIG_FAILED
;
6899 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6900 rmap
, summary_only
, as_set
);
6903 DEFUN (no_aggregate_address
,
6904 no_aggregate_address_cmd
,
6905 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6907 "Configure BGP aggregate entries\n"
6908 "Aggregate prefix\n"
6909 "Generate AS set path information\n"
6910 "Filter more specific routes from updates\n"
6911 "Filter more specific routes from updates\n"
6912 "Generate AS set path information\n"
6913 "Apply route map to aggregate network\n"
6914 "Name of route map\n")
6917 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6918 char *prefix
= argv
[idx
]->arg
;
6919 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6922 DEFUN (no_aggregate_address_mask
,
6923 no_aggregate_address_mask_cmd
,
6924 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6926 "Configure BGP aggregate entries\n"
6927 "Aggregate address\n"
6929 "Generate AS set path information\n"
6930 "Filter more specific routes from updates\n"
6931 "Filter more specific routes from updates\n"
6932 "Generate AS set path information\n"
6933 "Apply route map to aggregate network\n"
6934 "Name of route map\n")
6937 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6938 char *prefix
= argv
[idx
]->arg
;
6939 char *mask
= argv
[idx
+ 1]->arg
;
6941 char prefix_str
[BUFSIZ
];
6942 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6945 vty_out(vty
, "%% Inconsistent address and mask\n");
6946 return CMD_WARNING_CONFIG_FAILED
;
6949 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6952 DEFUN (ipv6_aggregate_address
,
6953 ipv6_aggregate_address_cmd
,
6954 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6955 "Configure BGP aggregate entries\n"
6956 "Aggregate prefix\n"
6957 "Generate AS set path information\n"
6958 "Filter more specific routes from updates\n"
6959 "Filter more specific routes from updates\n"
6960 "Generate AS set path information\n"
6961 "Apply route map to aggregate network\n"
6962 "Name of route map\n")
6965 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6966 char *prefix
= argv
[idx
]->arg
;
6969 int as_set
= argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
6970 : AGGREGATE_AS_UNSET
;
6973 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6974 ? AGGREGATE_SUMMARY_ONLY
6977 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6979 rmap
= argv
[idx
]->arg
;
6981 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6985 DEFUN (no_ipv6_aggregate_address
,
6986 no_ipv6_aggregate_address_cmd
,
6987 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6989 "Configure BGP aggregate entries\n"
6990 "Aggregate prefix\n"
6991 "Generate AS set path information\n"
6992 "Filter more specific routes from updates\n"
6993 "Filter more specific routes from updates\n"
6994 "Generate AS set path information\n"
6995 "Apply route map to aggregate network\n"
6996 "Name of route map\n")
6999 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
7000 char *prefix
= argv
[idx
]->arg
;
7001 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
7004 /* Redistribute route treatment. */
7005 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
7006 const union g_addr
*nexthop
, ifindex_t ifindex
,
7007 enum nexthop_types_t nhtype
, uint32_t metric
,
7008 uint8_t type
, unsigned short instance
,
7011 struct bgp_path_info
*new;
7012 struct bgp_path_info
*bpi
;
7013 struct bgp_path_info rmap_path
;
7014 struct bgp_node
*bn
;
7016 struct attr
*new_attr
;
7018 route_map_result_t ret
;
7019 struct bgp_redist
*red
;
7021 /* Make default attribute. */
7022 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
7024 * This must not be NULL to satisfy Coverity SA
7026 assert(attr
.aspath
);
7029 case NEXTHOP_TYPE_IFINDEX
:
7031 case NEXTHOP_TYPE_IPV4
:
7032 case NEXTHOP_TYPE_IPV4_IFINDEX
:
7033 attr
.nexthop
= nexthop
->ipv4
;
7035 case NEXTHOP_TYPE_IPV6
:
7036 case NEXTHOP_TYPE_IPV6_IFINDEX
:
7037 attr
.mp_nexthop_global
= nexthop
->ipv6
;
7038 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7040 case NEXTHOP_TYPE_BLACKHOLE
:
7041 switch (p
->family
) {
7043 attr
.nexthop
.s_addr
= INADDR_ANY
;
7046 memset(&attr
.mp_nexthop_global
, 0,
7047 sizeof(attr
.mp_nexthop_global
));
7048 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
7053 attr
.nh_ifindex
= ifindex
;
7056 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
7059 afi
= family2afi(p
->family
);
7061 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7063 struct attr attr_new
;
7065 /* Copy attribute for modification. */
7068 if (red
->redist_metric_flag
)
7069 attr_new
.med
= red
->redist_metric
;
7071 /* Apply route-map. */
7072 if (red
->rmap
.name
) {
7073 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
7074 rmap_path
.peer
= bgp
->peer_self
;
7075 rmap_path
.attr
= &attr_new
;
7077 SET_FLAG(bgp
->peer_self
->rmap_type
,
7078 PEER_RMAP_TYPE_REDISTRIBUTE
);
7080 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
7083 bgp
->peer_self
->rmap_type
= 0;
7085 if (ret
== RMAP_DENYMATCH
) {
7086 /* Free uninterned attribute. */
7087 bgp_attr_flush(&attr_new
);
7089 /* Unintern original. */
7090 aspath_unintern(&attr
.aspath
);
7091 bgp_redistribute_delete(bgp
, p
, type
, instance
);
7096 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
7097 bgp_attr_add_gshut_community(&attr_new
);
7099 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7100 SAFI_UNICAST
, p
, NULL
);
7102 new_attr
= bgp_attr_intern(&attr_new
);
7104 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
7106 if (bpi
->peer
== bgp
->peer_self
7107 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
7111 /* Ensure the (source route) type is updated. */
7113 if (attrhash_cmp(bpi
->attr
, new_attr
)
7114 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
7115 bgp_attr_unintern(&new_attr
);
7116 aspath_unintern(&attr
.aspath
);
7117 bgp_unlock_node(bn
);
7120 /* The attribute is changed. */
7121 bgp_path_info_set_flag(bn
, bpi
,
7122 BGP_PATH_ATTR_CHANGED
);
7124 /* Rewrite BGP route information. */
7125 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
7126 bgp_path_info_restore(bn
, bpi
);
7128 bgp_aggregate_decrement(
7129 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
7130 bgp_attr_unintern(&bpi
->attr
);
7131 bpi
->attr
= new_attr
;
7132 bpi
->uptime
= bgp_clock();
7134 /* Process change. */
7135 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
7137 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7138 bgp_unlock_node(bn
);
7139 aspath_unintern(&attr
.aspath
);
7141 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7143 == BGP_INSTANCE_TYPE_DEFAULT
)) {
7145 vpn_leak_from_vrf_update(
7146 bgp_get_default(), bgp
, bpi
);
7152 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
7153 bgp
->peer_self
, new_attr
, bn
);
7154 SET_FLAG(new->flags
, BGP_PATH_VALID
);
7156 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
7157 bgp_path_info_add(bn
, new);
7158 bgp_unlock_node(bn
);
7159 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
7161 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7162 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7164 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
7168 /* Unintern original. */
7169 aspath_unintern(&attr
.aspath
);
7172 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
7173 unsigned short instance
)
7176 struct bgp_node
*rn
;
7177 struct bgp_path_info
*pi
;
7178 struct bgp_redist
*red
;
7180 afi
= family2afi(p
->family
);
7182 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
7184 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
7185 SAFI_UNICAST
, p
, NULL
);
7187 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7188 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
7192 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7193 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7195 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7198 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
7199 bgp_path_info_delete(rn
, pi
);
7200 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7202 bgp_unlock_node(rn
);
7206 /* Withdraw specified route type's route. */
7207 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
7208 unsigned short instance
)
7210 struct bgp_node
*rn
;
7211 struct bgp_path_info
*pi
;
7212 struct bgp_table
*table
;
7214 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
7216 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7217 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
7218 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
7219 && pi
->instance
== instance
)
7223 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
7224 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
7226 vpn_leak_from_vrf_withdraw(bgp_get_default(),
7229 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
7231 bgp_path_info_delete(rn
, pi
);
7232 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
7237 /* Static function to display route. */
7238 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
7245 if (p
->family
== AF_INET
) {
7249 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7252 json_object_string_add(json
, "prefix",
7253 inet_ntop(p
->family
,
7256 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7257 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7258 json_object_string_add(json
, "network", buf2
);
7260 } else if (p
->family
== AF_ETHERNET
) {
7261 prefix2str(p
, buf
, PREFIX_STRLEN
);
7262 len
= vty_out(vty
, "%s", buf
);
7263 } else if (p
->family
== AF_EVPN
) {
7267 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
7270 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
7271 } else if (p
->family
== AF_FLOWSPEC
) {
7272 route_vty_out_flowspec(vty
, p
, NULL
,
7274 NLRI_STRING_FORMAT_JSON_SIMPLE
:
7275 NLRI_STRING_FORMAT_MIN
, json
);
7280 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
7283 json_object_string_add(json
, "prefix",
7284 inet_ntop(p
->family
,
7287 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
7288 prefix2str(p
, buf2
, PREFIX_STRLEN
);
7289 json_object_string_add(json
, "network", buf2
);
7296 vty_out(vty
, "\n%*s", 20, " ");
7298 vty_out(vty
, "%*s", len
, " ");
7302 enum bgp_display_type
{
7306 /* Print the short form route status for a bgp_path_info */
7307 static void route_vty_short_status_out(struct vty
*vty
,
7308 struct bgp_path_info
*path
,
7309 json_object
*json_path
)
7313 /* Route status display. */
7314 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7315 json_object_boolean_true_add(json_path
, "removed");
7317 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7318 json_object_boolean_true_add(json_path
, "stale");
7320 if (path
->extra
&& path
->extra
->suppress
)
7321 json_object_boolean_true_add(json_path
, "suppressed");
7323 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7324 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7325 json_object_boolean_true_add(json_path
, "valid");
7328 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7329 json_object_boolean_true_add(json_path
, "history");
7331 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7332 json_object_boolean_true_add(json_path
, "damped");
7334 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7335 json_object_boolean_true_add(json_path
, "bestpath");
7337 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7338 json_object_boolean_true_add(json_path
, "multipath");
7340 /* Internal route. */
7341 if ((path
->peer
->as
)
7342 && (path
->peer
->as
== path
->peer
->local_as
))
7343 json_object_string_add(json_path
, "pathFrom",
7346 json_object_string_add(json_path
, "pathFrom",
7352 /* Route status display. */
7353 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7355 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7357 else if (path
->extra
&& path
->extra
->suppress
)
7359 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7360 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7366 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7368 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7370 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7372 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7377 /* Internal route. */
7378 if (path
->peer
&& (path
->peer
->as
)
7379 && (path
->peer
->as
== path
->peer
->local_as
))
7385 static char *bgp_nexthop_hostname(struct peer
*peer
, struct attr
*attr
)
7387 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)
7388 && !(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))
7389 return peer
->hostname
;
7393 /* called from terminal list command */
7394 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7395 struct bgp_path_info
*path
, int display
, safi_t safi
,
7396 json_object
*json_paths
)
7398 struct attr
*attr
= path
->attr
;
7399 json_object
*json_path
= NULL
;
7400 json_object
*json_nexthops
= NULL
;
7401 json_object
*json_nexthop_global
= NULL
;
7402 json_object
*json_nexthop_ll
= NULL
;
7403 json_object
*json_ext_community
= NULL
;
7404 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7406 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7407 bool nexthop_othervrf
= false;
7408 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7409 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7410 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
7413 json_path
= json_object_new_object();
7415 /* short status lead text */
7416 route_vty_short_status_out(vty
, path
, json_path
);
7419 /* print prefix and mask */
7421 route_vty_out_route(p
, vty
, json_path
);
7423 vty_out(vty
, "%*s", 17, " ");
7425 route_vty_out_route(p
, vty
, json_path
);
7429 * If vrf id of nexthop is different from that of prefix,
7430 * set up printable string to append
7432 if (path
->extra
&& path
->extra
->bgp_orig
) {
7433 const char *self
= "";
7438 nexthop_othervrf
= true;
7439 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7441 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7442 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7443 "@%s%s", VRFID_NONE_STR
, self
);
7445 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7446 path
->extra
->bgp_orig
->vrf_id
, self
);
7448 if (path
->extra
->bgp_orig
->inst_type
7449 != BGP_INSTANCE_TYPE_DEFAULT
)
7451 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7453 const char *self
= "";
7458 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7462 * For ENCAP and EVPN routes, nexthop address family is not
7463 * neccessarily the same as the prefix address family.
7464 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7465 * EVPN routes are also exchanged with a MP nexthop. Currently,
7467 * is only IPv4, the value will be present in either
7469 * attr->mp_nexthop_global_in
7471 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7474 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7478 sprintf(nexthop
, "%s",
7479 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7483 sprintf(nexthop
, "%s",
7484 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7488 sprintf(nexthop
, "?");
7493 json_nexthop_global
= json_object_new_object();
7495 json_object_string_add(json_nexthop_global
, "ip",
7498 if (nexthop_hostname
)
7499 json_object_string_add(json_nexthop_global
,
7503 json_object_string_add(json_nexthop_global
, "afi",
7504 (af
== AF_INET
) ? "ipv4"
7506 json_object_boolean_true_add(json_nexthop_global
,
7509 vty_out(vty
, "%s%s",
7510 nexthop_hostname
? nexthop_hostname
: nexthop
,
7512 } else if (safi
== SAFI_EVPN
) {
7514 json_nexthop_global
= json_object_new_object();
7516 json_object_string_add(json_nexthop_global
, "ip",
7517 inet_ntoa(attr
->nexthop
));
7519 if (nexthop_hostname
)
7520 json_object_string_add(json_nexthop_global
,
7524 json_object_string_add(json_nexthop_global
, "afi",
7526 json_object_boolean_true_add(json_nexthop_global
,
7529 vty_out(vty
, "%-16s%s",
7530 nexthop_hostname
? nexthop_hostname
7531 : inet_ntoa(attr
->nexthop
),
7533 } else if (safi
== SAFI_FLOWSPEC
) {
7534 if (attr
->nexthop
.s_addr
!= 0) {
7536 json_nexthop_global
= json_object_new_object();
7538 json_object_string_add(json_nexthop_global
,
7540 json_object_string_add(
7541 json_nexthop_global
, "ip",
7542 inet_ntoa(attr
->nexthop
));
7544 if (nexthop_hostname
)
7545 json_object_string_add(
7546 json_nexthop_global
, "hostname",
7549 json_object_boolean_true_add(
7550 json_nexthop_global
,
7553 vty_out(vty
, "%-16s",
7556 : inet_ntoa(attr
->nexthop
));
7559 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7561 json_nexthop_global
= json_object_new_object();
7563 json_object_string_add(json_nexthop_global
, "ip",
7564 inet_ntoa(attr
->nexthop
));
7566 if (nexthop_hostname
)
7567 json_object_string_add(json_nexthop_global
,
7571 json_object_string_add(json_nexthop_global
, "afi",
7573 json_object_boolean_true_add(json_nexthop_global
,
7578 snprintf(buf
, sizeof(buf
), "%s%s",
7579 nexthop_hostname
? nexthop_hostname
7580 : inet_ntoa(attr
->nexthop
),
7582 vty_out(vty
, "%-16s", buf
);
7587 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7592 json_nexthop_global
= json_object_new_object();
7593 json_object_string_add(
7594 json_nexthop_global
, "ip",
7595 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
7598 if (nexthop_hostname
)
7599 json_object_string_add(json_nexthop_global
,
7603 json_object_string_add(json_nexthop_global
, "afi",
7605 json_object_string_add(json_nexthop_global
, "scope",
7608 /* We display both LL & GL if both have been
7610 if ((attr
->mp_nexthop_len
7611 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7612 || (path
->peer
->conf_if
)) {
7613 json_nexthop_ll
= json_object_new_object();
7614 json_object_string_add(
7615 json_nexthop_ll
, "ip",
7617 &attr
->mp_nexthop_local
, buf
,
7620 if (nexthop_hostname
)
7621 json_object_string_add(
7622 json_nexthop_ll
, "hostname",
7625 json_object_string_add(json_nexthop_ll
, "afi",
7627 json_object_string_add(json_nexthop_ll
, "scope",
7630 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7631 &attr
->mp_nexthop_local
)
7633 && !attr
->mp_nexthop_prefer_global
)
7634 json_object_boolean_true_add(
7635 json_nexthop_ll
, "used");
7637 json_object_boolean_true_add(
7638 json_nexthop_global
, "used");
7640 json_object_boolean_true_add(
7641 json_nexthop_global
, "used");
7643 /* Display LL if LL/Global both in table unless
7644 * prefer-global is set */
7645 if (((attr
->mp_nexthop_len
7646 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7647 && !attr
->mp_nexthop_prefer_global
)
7648 || (path
->peer
->conf_if
)) {
7649 if (path
->peer
->conf_if
) {
7650 len
= vty_out(vty
, "%s",
7651 path
->peer
->conf_if
);
7652 len
= 16 - len
; /* len of IPv6
7658 vty_out(vty
, "\n%*s", 36, " ");
7660 vty_out(vty
, "%*s", len
, " ");
7668 &attr
->mp_nexthop_local
,
7674 vty_out(vty
, "\n%*s", 36, " ");
7676 vty_out(vty
, "%*s", len
, " ");
7685 &attr
->mp_nexthop_global
,
7691 vty_out(vty
, "\n%*s", 36, " ");
7693 vty_out(vty
, "%*s", len
, " ");
7699 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7703 * Adding "metric" field to match with corresponding
7704 * CLI. "med" will be deprecated in future.
7706 json_object_int_add(json_path
, "med", attr
->med
);
7707 json_object_int_add(json_path
, "metric", attr
->med
);
7709 vty_out(vty
, "%10u", attr
->med
);
7710 else if (!json_paths
)
7714 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7718 * Adding "locPrf" field to match with corresponding
7719 * CLI. "localPref" will be deprecated in future.
7721 json_object_int_add(json_path
, "localpref",
7723 json_object_int_add(json_path
, "locPrf",
7726 vty_out(vty
, "%7u", attr
->local_pref
);
7727 else if (!json_paths
)
7731 json_object_int_add(json_path
, "weight", attr
->weight
);
7733 vty_out(vty
, "%7u ", attr
->weight
);
7737 json_object_string_add(
7738 json_path
, "peerId",
7739 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7747 * Adding "path" field to match with corresponding
7748 * CLI. "aspath" will be deprecated in future.
7750 json_object_string_add(json_path
, "aspath",
7752 json_object_string_add(json_path
, "path",
7755 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7760 json_object_string_add(json_path
, "origin",
7761 bgp_origin_long_str
[attr
->origin
]);
7763 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7766 if (safi
== SAFI_EVPN
&&
7767 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7768 json_ext_community
= json_object_new_object();
7769 json_object_string_add(json_ext_community
,
7771 attr
->ecommunity
->str
);
7772 json_object_object_add(json_path
,
7773 "extendedCommunity",
7774 json_ext_community
);
7778 json_object_boolean_true_add(json_path
,
7779 "announceNexthopSelf");
7780 if (nexthop_othervrf
) {
7781 json_object_string_add(json_path
, "nhVrfName",
7784 json_object_int_add(json_path
, "nhVrfId",
7785 ((nexthop_vrfid
== VRF_UNKNOWN
)
7787 : (int)nexthop_vrfid
));
7792 if (json_nexthop_global
|| json_nexthop_ll
) {
7793 json_nexthops
= json_object_new_array();
7795 if (json_nexthop_global
)
7796 json_object_array_add(json_nexthops
,
7797 json_nexthop_global
);
7799 if (json_nexthop_ll
)
7800 json_object_array_add(json_nexthops
,
7803 json_object_object_add(json_path
, "nexthops",
7807 json_object_array_add(json_paths
, json_path
);
7811 if (safi
== SAFI_EVPN
&&
7812 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7813 vty_out(vty
, "%*s", 20, " ");
7814 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7818 /* prints an additional line, indented, with VNC info, if
7820 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7821 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7826 /* called from terminal list command */
7827 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7828 safi_t safi
, bool use_json
, json_object
*json_ar
)
7830 json_object
*json_status
= NULL
;
7831 json_object
*json_net
= NULL
;
7834 /* Route status display. */
7836 json_status
= json_object_new_object();
7837 json_net
= json_object_new_object();
7844 /* print prefix and mask */
7846 if (safi
== SAFI_EVPN
)
7847 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7848 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7849 json_object_string_add(
7850 json_net
, "addrPrefix",
7851 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7853 json_object_int_add(json_net
, "prefixLen",
7855 prefix2str(p
, buff
, PREFIX_STRLEN
);
7856 json_object_string_add(json_net
, "network", buff
);
7859 route_vty_out_route(p
, vty
, NULL
);
7861 /* Print attribute */
7864 if (p
->family
== AF_INET
7865 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7866 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7867 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7868 json_object_string_add(
7869 json_net
, "nextHop",
7871 attr
->mp_nexthop_global_in
));
7873 json_object_string_add(
7874 json_net
, "nextHop",
7875 inet_ntoa(attr
->nexthop
));
7876 } else if (p
->family
== AF_INET6
7877 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7880 json_object_string_add(
7881 json_net
, "nextHopGlobal",
7883 &attr
->mp_nexthop_global
, buf
,
7885 } else if (p
->family
== AF_EVPN
&&
7886 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7887 json_object_string_add(json_net
,
7888 "nextHop", inet_ntoa(
7889 attr
->mp_nexthop_global_in
));
7892 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7893 json_object_int_add(json_net
, "metric",
7896 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7899 * Adding "locPrf" field to match with
7900 * corresponding CLI. "localPref" will be
7901 * deprecated in future.
7903 json_object_int_add(json_net
, "localPref",
7905 json_object_int_add(json_net
, "locPrf",
7909 json_object_int_add(json_net
, "weight", attr
->weight
);
7915 * Adding "path" field to match with
7916 * corresponding CLI. "localPref" will be
7917 * deprecated in future.
7919 json_object_string_add(json_net
, "asPath",
7921 json_object_string_add(json_net
, "path",
7926 json_object_string_add(json_net
, "bgpOriginCode",
7927 bgp_origin_str
[attr
->origin
]);
7929 if (p
->family
== AF_INET
7930 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7931 || safi
== SAFI_EVPN
7932 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7933 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7934 || safi
== SAFI_EVPN
)
7935 vty_out(vty
, "%-16s",
7937 attr
->mp_nexthop_global_in
));
7939 vty_out(vty
, "%-16s",
7940 inet_ntoa(attr
->nexthop
));
7941 } else if (p
->family
== AF_INET6
7942 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7949 &attr
->mp_nexthop_global
, buf
,
7953 vty_out(vty
, "\n%*s", 36, " ");
7955 vty_out(vty
, "%*s", len
, " ");
7958 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7959 vty_out(vty
, "%10u", attr
->med
);
7963 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7964 vty_out(vty
, "%7u", attr
->local_pref
);
7968 vty_out(vty
, "%7u ", attr
->weight
);
7972 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7975 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7979 json_object_boolean_true_add(json_status
, "*");
7980 json_object_boolean_true_add(json_status
, ">");
7981 json_object_object_add(json_net
, "appliedStatusSymbols",
7984 prefix2str(p
, buff
, PREFIX_STRLEN
);
7985 json_object_object_add(json_ar
, buff
, json_net
);
7990 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7991 struct bgp_path_info
*path
, int display
, safi_t safi
,
7994 json_object
*json_out
= NULL
;
7996 mpls_label_t label
= MPLS_INVALID_LABEL
;
8002 json_out
= json_object_new_object();
8004 /* short status lead text */
8005 route_vty_short_status_out(vty
, path
, json_out
);
8007 /* print prefix and mask */
8010 route_vty_out_route(p
, vty
, NULL
);
8012 vty_out(vty
, "%*s", 17, " ");
8015 /* Print attribute */
8017 if (((p
->family
== AF_INET
)
8018 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8019 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8020 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8021 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8022 || safi
== SAFI_EVPN
) {
8024 json_object_string_add(
8025 json_out
, "mpNexthopGlobalIn",
8026 inet_ntoa(attr
->mp_nexthop_global_in
));
8028 vty_out(vty
, "%-16s",
8029 inet_ntoa(attr
->mp_nexthop_global_in
));
8032 json_object_string_add(
8033 json_out
, "nexthop",
8034 inet_ntoa(attr
->nexthop
));
8036 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
8038 } else if (((p
->family
== AF_INET6
)
8039 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
8040 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
8041 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8044 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
8046 json_object_string_add(
8047 json_out
, "mpNexthopGlobalIn",
8049 &attr
->mp_nexthop_global
,
8050 buf_a
, sizeof(buf_a
)));
8054 &attr
->mp_nexthop_global
,
8055 buf_a
, sizeof(buf_a
)));
8056 } else if (attr
->mp_nexthop_len
8057 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8058 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
8059 &attr
->mp_nexthop_global
,
8060 &attr
->mp_nexthop_local
);
8062 json_object_string_add(json_out
,
8063 "mpNexthopGlobalLocal",
8066 vty_out(vty
, "%s", buf_a
);
8070 label
= decode_label(&path
->extra
->label
[0]);
8072 if (bgp_is_valid_label(&label
)) {
8074 json_object_int_add(json_out
, "notag", label
);
8075 json_object_array_add(json
, json_out
);
8077 vty_out(vty
, "notag/%d", label
);
8083 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
8084 struct bgp_path_info
*path
, int display
,
8085 json_object
*json_paths
)
8088 char buf
[BUFSIZ
] = {0};
8089 json_object
*json_path
= NULL
;
8090 json_object
*json_nexthop
= NULL
;
8091 json_object
*json_overlay
= NULL
;
8097 json_path
= json_object_new_object();
8098 json_overlay
= json_object_new_object();
8099 json_nexthop
= json_object_new_object();
8102 /* short status lead text */
8103 route_vty_short_status_out(vty
, path
, json_path
);
8105 /* print prefix and mask */
8107 route_vty_out_route(p
, vty
, json_path
);
8109 vty_out(vty
, "%*s", 17, " ");
8111 /* Print attribute */
8114 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
8118 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
8120 vty_out(vty
, "%-16s", buf
);
8122 json_object_string_add(json_nexthop
, "ip", buf
);
8124 json_object_string_add(json_nexthop
, "afi", "ipv4");
8126 json_object_object_add(json_path
, "nexthop",
8131 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
8132 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
8134 vty_out(vty
, "%s(%s)", buf
, buf1
);
8136 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
8138 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
8141 json_object_string_add(json_nexthop
, "afi", "ipv6");
8143 json_object_object_add(json_path
, "nexthop",
8151 json_object_string_add(json_nexthop
, "Error",
8152 "Unsupported address-family");
8156 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
8159 vty_out(vty
, "%s", str
);
8161 json_object_string_add(json_overlay
, "esi", str
);
8163 XFREE(MTYPE_TMP
, str
);
8165 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
8166 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
8168 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
8169 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
8174 vty_out(vty
, "/%s", buf
);
8176 json_object_string_add(json_overlay
, "gw", buf
);
8178 if (attr
->ecommunity
) {
8180 struct ecommunity_val
*routermac
= ecommunity_lookup(
8181 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
8182 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
8185 mac
= ecom_mac2str((char *)routermac
->val
);
8188 vty_out(vty
, "/%s", (char *)mac
);
8190 json_object_string_add(json_overlay
, "rmac",
8193 XFREE(MTYPE_TMP
, mac
);
8200 json_object_object_add(json_path
, "overlay", json_overlay
);
8202 json_object_array_add(json_paths
, json_path
);
8206 /* dampening route */
8207 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8208 struct bgp_path_info
*path
, int display
, afi_t afi
,
8209 safi_t safi
, bool use_json
, json_object
*json
)
8213 char timebuf
[BGP_UPTIME_LEN
];
8215 /* short status lead text */
8216 route_vty_short_status_out(vty
, path
, json
);
8218 /* print prefix and mask */
8221 route_vty_out_route(p
, vty
, NULL
);
8223 vty_out(vty
, "%*s", 17, " ");
8226 len
= vty_out(vty
, "%s", path
->peer
->host
);
8230 vty_out(vty
, "\n%*s", 34, " ");
8233 json_object_int_add(json
, "peerHost", len
);
8235 vty_out(vty
, "%*s", len
, " ");
8239 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
, afi
,
8240 safi
, use_json
, json
);
8243 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8244 BGP_UPTIME_LEN
, afi
, safi
,
8247 /* Print attribute */
8253 json_object_string_add(json
, "asPath",
8256 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8261 json_object_string_add(json
, "origin",
8262 bgp_origin_str
[attr
->origin
]);
8264 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8271 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
8272 struct bgp_path_info
*path
, int display
, afi_t afi
,
8273 safi_t safi
, bool use_json
, json_object
*json
)
8276 struct bgp_damp_info
*bdi
;
8277 char timebuf
[BGP_UPTIME_LEN
];
8283 bdi
= path
->extra
->damp_info
;
8285 /* short status lead text */
8286 route_vty_short_status_out(vty
, path
, json
);
8288 /* print prefix and mask */
8291 route_vty_out_route(p
, vty
, NULL
);
8293 vty_out(vty
, "%*s", 17, " ");
8296 len
= vty_out(vty
, "%s", path
->peer
->host
);
8300 vty_out(vty
, "\n%*s", 33, " ");
8303 json_object_int_add(json
, "peerHost", len
);
8305 vty_out(vty
, "%*s", len
, " ");
8308 len
= vty_out(vty
, "%d", bdi
->flap
);
8315 json_object_int_add(json
, "bdiFlap", len
);
8317 vty_out(vty
, "%*s", len
, " ");
8321 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8324 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8325 BGP_UPTIME_LEN
, 0, NULL
));
8327 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8328 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8330 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8331 BGP_UPTIME_LEN
, afi
, safi
,
8335 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8336 BGP_UPTIME_LEN
, afi
,
8337 safi
, use_json
, json
));
8340 vty_out(vty
, "%*s ", 8, " ");
8343 /* Print attribute */
8349 json_object_string_add(json
, "asPath",
8352 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8357 json_object_string_add(json
, "origin",
8358 bgp_origin_str
[attr
->origin
]);
8360 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8366 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8367 int *first
, const char *header
,
8368 json_object
*json_adv_to
)
8370 char buf1
[INET6_ADDRSTRLEN
];
8371 json_object
*json_peer
= NULL
;
8374 /* 'advertised-to' is a dictionary of peers we have advertised
8376 * prefix too. The key is the peer's IP or swpX, the value is
8378 * hostname if we know it and "" if not.
8380 json_peer
= json_object_new_object();
8383 json_object_string_add(json_peer
, "hostname",
8387 json_object_object_add(json_adv_to
, peer
->conf_if
,
8390 json_object_object_add(
8392 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8396 vty_out(vty
, "%s", header
);
8401 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8403 vty_out(vty
, " %s(%s)", peer
->hostname
,
8406 vty_out(vty
, " %s(%s)", peer
->hostname
,
8407 sockunion2str(&peer
->su
, buf1
,
8411 vty_out(vty
, " %s", peer
->conf_if
);
8414 sockunion2str(&peer
->su
, buf1
,
8420 static void route_vty_out_tx_ids(struct vty
*vty
,
8421 struct bgp_addpath_info_data
*d
)
8425 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8426 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8427 d
->addpath_tx_id
[i
],
8428 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8432 static const char *bgp_path_selection_reason2str(
8433 enum bgp_path_selection_reason reason
)
8436 case bgp_path_selection_none
:
8437 return "Nothing to Select";
8439 case bgp_path_selection_first
:
8440 return "First path received";
8442 case bgp_path_selection_evpn_sticky_mac
:
8443 return "EVPN Sticky Mac";
8445 case bgp_path_selection_evpn_seq
:
8446 return "EVPN sequence number";
8448 case bgp_path_selection_evpn_lower_ip
:
8449 return "EVPN lower IP";
8451 case bgp_path_selection_weight
:
8454 case bgp_path_selection_local_pref
:
8455 return "Local Pref";
8457 case bgp_path_selection_local_route
:
8458 return "Local Route";
8460 case bgp_path_selection_confed_as_path
:
8461 return "Confederation based AS Path";
8463 case bgp_path_selection_as_path
:
8466 case bgp_path_selection_origin
:
8469 case bgp_path_selection_med
:
8472 case bgp_path_selection_peer
:
8475 case bgp_path_selection_confed
:
8476 return "Confed Peer Type";
8478 case bgp_path_selection_igp_metric
:
8479 return "IGP Metric";
8481 case bgp_path_selection_older
:
8482 return "Older Path";
8484 case bgp_path_selection_router_id
:
8487 case bgp_path_selection_cluster_length
:
8488 return "Cluser length";
8490 case bgp_path_selection_stale
:
8491 return "Path Staleness";
8493 case bgp_path_selection_local_configured
:
8494 return "Locally configured route";
8496 case bgp_path_selection_neighbor_ip
:
8497 return "Neighbor IP";
8499 case bgp_path_selection_default
:
8500 return "Nothing left to compare";
8503 return "Invalid (internal error)";
8506 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8507 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8508 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8510 char buf
[INET6_ADDRSTRLEN
];
8512 char buf2
[EVPN_ROUTE_STRLEN
];
8513 struct attr
*attr
= path
->attr
;
8514 int sockunion_vty_out(struct vty
*, union sockunion
*);
8516 json_object
*json_bestpath
= NULL
;
8517 json_object
*json_cluster_list
= NULL
;
8518 json_object
*json_cluster_list_list
= NULL
;
8519 json_object
*json_ext_community
= NULL
;
8520 json_object
*json_last_update
= NULL
;
8521 json_object
*json_pmsi
= NULL
;
8522 json_object
*json_nexthop_global
= NULL
;
8523 json_object
*json_nexthop_ll
= NULL
;
8524 json_object
*json_nexthops
= NULL
;
8525 json_object
*json_path
= NULL
;
8526 json_object
*json_peer
= NULL
;
8527 json_object
*json_string
= NULL
;
8528 json_object
*json_adv_to
= NULL
;
8530 struct listnode
*node
, *nnode
;
8532 int addpath_capable
;
8534 unsigned int first_as
;
8536 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8538 char *nexthop_hostname
= bgp_nexthop_hostname(path
->peer
, attr
);
8541 json_path
= json_object_new_object();
8542 json_peer
= json_object_new_object();
8543 json_nexthop_global
= json_object_new_object();
8551 if (path
->extra
&& path
->extra
->num_labels
) {
8552 bgp_evpn_label2str(path
->extra
->label
,
8553 path
->extra
->num_labels
, tag_buf
,
8556 if (safi
== SAFI_EVPN
) {
8558 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8559 buf2
, sizeof(buf2
));
8560 vty_out(vty
, " Route %s", buf2
);
8561 if (tag_buf
[0] != '\0')
8562 vty_out(vty
, " VNI %s", tag_buf
);
8566 json_object_string_add(json_path
, "VNI",
8571 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8572 struct bgp_path_info
*parent_ri
;
8573 struct bgp_node
*rn
, *prn
;
8575 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8576 rn
= parent_ri
->net
;
8577 if (rn
&& rn
->prn
) {
8579 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8580 buf1
, sizeof(buf1
));
8581 if (is_pi_family_evpn(parent_ri
)) {
8582 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8583 buf2
, sizeof(buf2
));
8584 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8586 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8591 /* Line1 display AS-path, Aggregator */
8594 if (!attr
->aspath
->json
)
8595 aspath_str_update(attr
->aspath
, true);
8596 json_object_lock(attr
->aspath
->json
);
8597 json_object_object_add(json_path
, "aspath",
8598 attr
->aspath
->json
);
8600 if (attr
->aspath
->segments
)
8601 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8603 vty_out(vty
, " Local");
8607 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8609 json_object_boolean_true_add(json_path
, "removed");
8611 vty_out(vty
, ", (removed)");
8614 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8616 json_object_boolean_true_add(json_path
, "stale");
8618 vty_out(vty
, ", (stale)");
8621 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8623 json_object_int_add(json_path
, "aggregatorAs",
8624 attr
->aggregator_as
);
8625 json_object_string_add(
8626 json_path
, "aggregatorId",
8627 inet_ntoa(attr
->aggregator_addr
));
8629 vty_out(vty
, ", (aggregated by %u %s)",
8630 attr
->aggregator_as
,
8631 inet_ntoa(attr
->aggregator_addr
));
8635 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8636 PEER_FLAG_REFLECTOR_CLIENT
)) {
8638 json_object_boolean_true_add(json_path
,
8639 "rxedFromRrClient");
8641 vty_out(vty
, ", (Received from a RR-client)");
8644 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8645 PEER_FLAG_RSERVER_CLIENT
)) {
8647 json_object_boolean_true_add(json_path
,
8648 "rxedFromRsClient");
8650 vty_out(vty
, ", (Received from a RS-client)");
8653 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8655 json_object_boolean_true_add(json_path
,
8656 "dampeningHistoryEntry");
8658 vty_out(vty
, ", (history entry)");
8659 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8661 json_object_boolean_true_add(json_path
,
8662 "dampeningSuppressed");
8664 vty_out(vty
, ", (suppressed due to dampening)");
8670 /* Line2 display Next-hop, Neighbor, Router-id */
8671 /* Display the nexthop */
8672 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8673 || bn
->p
.family
== AF_EVPN
)
8674 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8675 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8676 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8677 || safi
== SAFI_EVPN
) {
8679 json_object_string_add(
8680 json_nexthop_global
, "ip",
8681 inet_ntoa(attr
->mp_nexthop_global_in
));
8683 if (nexthop_hostname
)
8684 json_object_string_add(
8685 json_nexthop_global
, "hostname",
8692 attr
->mp_nexthop_global_in
));
8695 json_object_string_add(
8696 json_nexthop_global
, "ip",
8697 inet_ntoa(attr
->nexthop
));
8699 if (nexthop_hostname
)
8700 json_object_string_add(
8701 json_nexthop_global
, "hostname",
8707 : inet_ntoa(attr
->nexthop
));
8711 json_object_string_add(json_nexthop_global
, "afi",
8715 json_object_string_add(
8716 json_nexthop_global
, "ip",
8717 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
8718 buf
, INET6_ADDRSTRLEN
));
8720 if (nexthop_hostname
)
8721 json_object_string_add(json_nexthop_global
,
8725 json_object_string_add(json_nexthop_global
, "afi",
8727 json_object_string_add(json_nexthop_global
, "scope",
8733 : inet_ntop(AF_INET6
,
8734 &attr
->mp_nexthop_global
,
8735 buf
, INET6_ADDRSTRLEN
));
8739 /* Display the IGP cost or 'inaccessible' */
8740 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8742 json_object_boolean_false_add(json_nexthop_global
,
8745 vty_out(vty
, " (inaccessible)");
8747 if (path
->extra
&& path
->extra
->igpmetric
) {
8749 json_object_int_add(json_nexthop_global
,
8751 path
->extra
->igpmetric
);
8753 vty_out(vty
, " (metric %u)",
8754 path
->extra
->igpmetric
);
8757 /* IGP cost is 0, display this only for json */
8760 json_object_int_add(json_nexthop_global
,
8765 json_object_boolean_true_add(json_nexthop_global
,
8769 /* Display peer "from" output */
8770 /* This path was originated locally */
8771 if (path
->peer
== bgp
->peer_self
) {
8773 if (safi
== SAFI_EVPN
8774 || (bn
->p
.family
== AF_INET
8775 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8777 json_object_string_add(json_peer
, "peerId",
8780 vty_out(vty
, " from 0.0.0.0 ");
8783 json_object_string_add(json_peer
, "peerId",
8786 vty_out(vty
, " from :: ");
8790 json_object_string_add(json_peer
, "routerId",
8791 inet_ntoa(bgp
->router_id
));
8793 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8796 /* We RXed this path from one of our peers */
8800 json_object_string_add(json_peer
, "peerId",
8801 sockunion2str(&path
->peer
->su
,
8804 json_object_string_add(json_peer
, "routerId",
8806 &path
->peer
->remote_id
,
8807 buf1
, sizeof(buf1
)));
8809 if (path
->peer
->hostname
)
8810 json_object_string_add(json_peer
, "hostname",
8811 path
->peer
->hostname
);
8813 if (path
->peer
->domainname
)
8814 json_object_string_add(json_peer
, "domainname",
8815 path
->peer
->domainname
);
8817 if (path
->peer
->conf_if
)
8818 json_object_string_add(json_peer
, "interface",
8819 path
->peer
->conf_if
);
8821 if (path
->peer
->conf_if
) {
8822 if (path
->peer
->hostname
8823 && bgp_flag_check(path
->peer
->bgp
,
8824 BGP_FLAG_SHOW_HOSTNAME
))
8825 vty_out(vty
, " from %s(%s)",
8826 path
->peer
->hostname
,
8827 path
->peer
->conf_if
);
8829 vty_out(vty
, " from %s",
8830 path
->peer
->conf_if
);
8832 if (path
->peer
->hostname
8833 && bgp_flag_check(path
->peer
->bgp
,
8834 BGP_FLAG_SHOW_HOSTNAME
))
8835 vty_out(vty
, " from %s(%s)",
8836 path
->peer
->hostname
,
8839 vty_out(vty
, " from %s",
8840 sockunion2str(&path
->peer
->su
,
8845 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8846 vty_out(vty
, " (%s)",
8847 inet_ntoa(attr
->originator_id
));
8849 vty_out(vty
, " (%s)",
8851 &path
->peer
->remote_id
, buf1
,
8857 * Note when vrfid of nexthop is different from that of prefix
8859 if (path
->extra
&& path
->extra
->bgp_orig
) {
8860 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8865 if (path
->extra
->bgp_orig
->inst_type
8866 == BGP_INSTANCE_TYPE_DEFAULT
)
8867 vn
= VRF_DEFAULT_NAME
;
8869 vn
= path
->extra
->bgp_orig
->name
;
8871 json_object_string_add(json_path
, "nhVrfName", vn
);
8873 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8874 json_object_int_add(json_path
, "nhVrfId", -1);
8876 json_object_int_add(json_path
, "nhVrfId",
8877 (int)nexthop_vrfid
);
8880 if (nexthop_vrfid
== VRF_UNKNOWN
)
8881 vty_out(vty
, " vrf ?");
8883 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8889 json_object_boolean_true_add(json_path
,
8890 "announceNexthopSelf");
8892 vty_out(vty
, " announce-nh-self");
8899 /* display the link-local nexthop */
8900 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8902 json_nexthop_ll
= json_object_new_object();
8903 json_object_string_add(
8904 json_nexthop_ll
, "ip",
8905 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8906 buf
, INET6_ADDRSTRLEN
));
8908 if (nexthop_hostname
)
8909 json_object_string_add(json_nexthop_ll
,
8913 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8914 json_object_string_add(json_nexthop_ll
, "scope",
8917 json_object_boolean_true_add(json_nexthop_ll
,
8920 if (!attr
->mp_nexthop_prefer_global
)
8921 json_object_boolean_true_add(json_nexthop_ll
,
8924 json_object_boolean_true_add(
8925 json_nexthop_global
, "used");
8927 vty_out(vty
, " (%s) %s\n",
8928 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8929 buf
, INET6_ADDRSTRLEN
),
8930 attr
->mp_nexthop_prefer_global
8935 /* If we do not have a link-local nexthop then we must flag the
8939 json_object_boolean_true_add(json_nexthop_global
,
8943 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8944 * Int/Ext/Local, Atomic, best */
8946 json_object_string_add(json_path
, "origin",
8947 bgp_origin_long_str
[attr
->origin
]);
8949 vty_out(vty
, " Origin %s",
8950 bgp_origin_long_str
[attr
->origin
]);
8952 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8955 * Adding "metric" field to match with
8956 * corresponding CLI. "med" will be
8957 * deprecated in future.
8959 json_object_int_add(json_path
, "med", attr
->med
);
8960 json_object_int_add(json_path
, "metric", attr
->med
);
8962 vty_out(vty
, ", metric %u", attr
->med
);
8965 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8967 json_object_int_add(json_path
, "localpref",
8970 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8973 if (attr
->weight
!= 0) {
8975 json_object_int_add(json_path
, "weight", attr
->weight
);
8977 vty_out(vty
, ", weight %u", attr
->weight
);
8980 if (attr
->tag
!= 0) {
8982 json_object_int_add(json_path
, "tag", attr
->tag
);
8984 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8987 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8989 json_object_boolean_false_add(json_path
, "valid");
8991 vty_out(vty
, ", invalid");
8992 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8994 json_object_boolean_true_add(json_path
, "valid");
8996 vty_out(vty
, ", valid");
8999 if (path
->peer
!= bgp
->peer_self
) {
9000 if (path
->peer
->as
== path
->peer
->local_as
) {
9001 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
9003 json_object_string_add(
9007 vty_out(vty
, ", confed-internal");
9010 json_object_string_add(
9011 json_peer
, "type", "internal");
9013 vty_out(vty
, ", internal");
9016 if (bgp_confederation_peers_check(bgp
,
9019 json_object_string_add(
9023 vty_out(vty
, ", confed-external");
9026 json_object_string_add(
9027 json_peer
, "type", "external");
9029 vty_out(vty
, ", external");
9032 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
9034 json_object_boolean_true_add(json_path
, "aggregated");
9035 json_object_boolean_true_add(json_path
, "local");
9037 vty_out(vty
, ", aggregated, local");
9039 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
9041 json_object_boolean_true_add(json_path
, "sourced");
9043 vty_out(vty
, ", sourced");
9046 json_object_boolean_true_add(json_path
, "sourced");
9047 json_object_boolean_true_add(json_path
, "local");
9049 vty_out(vty
, ", sourced, local");
9053 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
9055 json_object_boolean_true_add(json_path
,
9058 vty_out(vty
, ", atomic-aggregate");
9061 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
9062 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
9063 && bgp_path_info_mpath_count(path
))) {
9065 json_object_boolean_true_add(json_path
, "multipath");
9067 vty_out(vty
, ", multipath");
9070 // Mark the bestpath(s)
9071 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
9072 first_as
= aspath_get_first_as(attr
->aspath
);
9076 json_bestpath
= json_object_new_object();
9077 json_object_int_add(json_bestpath
, "bestpathFromAs",
9081 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
9083 vty_out(vty
, ", bestpath-from-AS Local");
9087 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
9090 json_bestpath
= json_object_new_object();
9091 json_object_boolean_true_add(json_bestpath
, "overall");
9092 json_object_string_add(
9093 json_bestpath
, "selectionReason",
9094 bgp_path_selection_reason2str(bn
->reason
));
9096 vty_out(vty
, ", best");
9097 vty_out(vty
, " (%s)",
9098 bgp_path_selection_reason2str(bn
->reason
));
9103 json_object_object_add(json_path
, "bestpath", json_bestpath
);
9108 /* Line 4 display Community */
9109 if (attr
->community
) {
9111 if (!attr
->community
->json
)
9112 community_str(attr
->community
, true);
9113 json_object_lock(attr
->community
->json
);
9114 json_object_object_add(json_path
, "community",
9115 attr
->community
->json
);
9117 vty_out(vty
, " Community: %s\n",
9118 attr
->community
->str
);
9122 /* Line 5 display Extended-community */
9123 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
9125 json_ext_community
= json_object_new_object();
9126 json_object_string_add(json_ext_community
, "string",
9127 attr
->ecommunity
->str
);
9128 json_object_object_add(json_path
, "extendedCommunity",
9129 json_ext_community
);
9131 vty_out(vty
, " Extended Community: %s\n",
9132 attr
->ecommunity
->str
);
9136 /* Line 6 display Large community */
9137 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
9139 if (!attr
->lcommunity
->json
)
9140 lcommunity_str(attr
->lcommunity
, true);
9141 json_object_lock(attr
->lcommunity
->json
);
9142 json_object_object_add(json_path
, "largeCommunity",
9143 attr
->lcommunity
->json
);
9145 vty_out(vty
, " Large Community: %s\n",
9146 attr
->lcommunity
->str
);
9150 /* Line 7 display Originator, Cluster-id */
9151 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
9152 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
9153 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
9155 json_object_string_add(
9156 json_path
, "originatorId",
9157 inet_ntoa(attr
->originator_id
));
9159 vty_out(vty
, " Originator: %s",
9160 inet_ntoa(attr
->originator_id
));
9163 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
9167 json_cluster_list
= json_object_new_object();
9168 json_cluster_list_list
=
9169 json_object_new_array();
9171 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9173 json_string
= json_object_new_string(
9174 inet_ntoa(attr
->cluster
9176 json_object_array_add(
9177 json_cluster_list_list
,
9182 * struct cluster_list does not have
9183 * "str" variable like aspath and community
9184 * do. Add this someday if someone asks
9186 * json_object_string_add(json_cluster_list,
9187 * "string", attr->cluster->str);
9189 json_object_object_add(json_cluster_list
,
9191 json_cluster_list_list
);
9192 json_object_object_add(json_path
, "clusterList",
9195 vty_out(vty
, ", Cluster list: ");
9197 for (i
= 0; i
< attr
->cluster
->length
/ 4;
9200 inet_ntoa(attr
->cluster
9210 if (path
->extra
&& path
->extra
->damp_info
)
9211 bgp_damp_info_vty(vty
, path
, afi
, safi
, json_path
);
9214 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
9215 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
9216 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
9219 json_object_int_add(json_path
, "remoteLabel", label
);
9221 vty_out(vty
, " Remote label: %d\n", label
);
9225 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
9227 json_object_int_add(json_path
, "labelIndex",
9230 vty_out(vty
, " Label Index: %d\n",
9234 /* Line 8 display Addpath IDs */
9235 if (path
->addpath_rx_id
9236 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
9238 json_object_int_add(json_path
, "addpathRxId",
9239 path
->addpath_rx_id
);
9241 /* Keep backwards compatibility with the old API
9242 * by putting TX All's ID in the old field
9244 json_object_int_add(
9245 json_path
, "addpathTxId",
9247 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
9249 /* ... but create a specific field for each
9252 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
9253 json_object_int_add(
9255 bgp_addpath_names(i
)->id_json_name
,
9256 path
->tx_addpath
.addpath_tx_id
[i
]);
9259 vty_out(vty
, " AddPath ID: RX %u, ",
9260 path
->addpath_rx_id
);
9262 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
9266 /* If we used addpath to TX a non-bestpath we need to display
9267 * "Advertised to" on a path-by-path basis
9269 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9272 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9274 bgp_addpath_encode_tx(peer
, afi
, safi
);
9275 has_adj
= bgp_adj_out_lookup(
9277 bgp_addpath_id_for_peer(peer
, afi
, safi
,
9278 &path
->tx_addpath
));
9280 if ((addpath_capable
&& has_adj
)
9281 || (!addpath_capable
&& has_adj
9282 && CHECK_FLAG(path
->flags
,
9283 BGP_PATH_SELECTED
))) {
9284 if (json_path
&& !json_adv_to
)
9285 json_adv_to
= json_object_new_object();
9287 route_vty_out_advertised_to(
9289 " Advertised to:", json_adv_to
);
9295 json_object_object_add(
9296 json_path
, "advertisedTo", json_adv_to
);
9305 /* Line 9 display Uptime */
9306 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
9308 json_last_update
= json_object_new_object();
9309 json_object_int_add(json_last_update
, "epoch", tbuf
);
9310 json_object_string_add(json_last_update
, "string",
9312 json_object_object_add(json_path
, "lastUpdate",
9315 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
9317 /* Line 10 display PMSI tunnel attribute, if present */
9318 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
9320 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
9321 PMSI_TNLTYPE_STR_DEFAULT
);
9324 json_pmsi
= json_object_new_object();
9325 json_object_string_add(json_pmsi
, "tunnelType", str
);
9326 json_object_int_add(json_pmsi
, "label",
9327 label2vni(&attr
->label
));
9328 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9330 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9331 str
, label2vni(&attr
->label
));
9334 /* We've constructed the json object for this path, add it to the json
9338 if (json_nexthop_global
|| json_nexthop_ll
) {
9339 json_nexthops
= json_object_new_array();
9341 if (json_nexthop_global
)
9342 json_object_array_add(json_nexthops
,
9343 json_nexthop_global
);
9345 if (json_nexthop_ll
)
9346 json_object_array_add(json_nexthops
,
9349 json_object_object_add(json_path
, "nexthops",
9353 json_object_object_add(json_path
, "peer", json_peer
);
9354 json_object_array_add(json_paths
, json_path
);
9358 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9359 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9360 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9362 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9363 const char *prefix_list_str
, afi_t afi
,
9364 safi_t safi
, enum bgp_show_type type
);
9365 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9366 const char *filter
, afi_t afi
, safi_t safi
,
9367 enum bgp_show_type type
);
9368 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9369 const char *rmap_str
, afi_t afi
, safi_t safi
,
9370 enum bgp_show_type type
);
9371 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9372 const char *com
, int exact
, afi_t afi
,
9374 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9375 const char *prefix
, afi_t afi
, safi_t safi
,
9376 enum bgp_show_type type
);
9377 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9378 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
9380 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9381 const char *comstr
, int exact
, afi_t afi
,
9382 safi_t safi
, bool use_json
);
9385 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9386 struct bgp_table
*table
, enum bgp_show_type type
,
9387 void *output_arg
, bool use_json
, char *rd
,
9388 int is_last
, unsigned long *output_cum
,
9389 unsigned long *total_cum
,
9390 unsigned long *json_header_depth
)
9392 struct bgp_path_info
*pi
;
9393 struct bgp_node
*rn
;
9396 unsigned long output_count
= 0;
9397 unsigned long total_count
= 0;
9400 json_object
*json_paths
= NULL
;
9403 if (output_cum
&& *output_cum
!= 0)
9406 if (use_json
&& !*json_header_depth
) {
9408 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9409 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9410 " \"localAS\": %u,\n \"routes\": { ",
9411 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9412 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9415 table
->version
, inet_ntoa(bgp
->router_id
),
9416 bgp
->default_local_pref
, bgp
->as
);
9417 *json_header_depth
= 2;
9419 vty_out(vty
, " \"routeDistinguishers\" : {");
9420 ++*json_header_depth
;
9424 if (use_json
&& rd
) {
9425 vty_out(vty
, " \"%s\" : { ", rd
);
9428 /* Start processing of routes. */
9429 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9430 pi
= bgp_node_get_bgp_path_info(rn
);
9436 json_paths
= json_object_new_array();
9440 for (; pi
; pi
= pi
->next
) {
9442 if (type
== bgp_show_type_flap_statistics
9443 || type
== bgp_show_type_flap_neighbor
9444 || type
== bgp_show_type_dampend_paths
9445 || type
== bgp_show_type_damp_neighbor
) {
9446 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9449 if (type
== bgp_show_type_regexp
) {
9450 regex_t
*regex
= output_arg
;
9452 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9456 if (type
== bgp_show_type_prefix_list
) {
9457 struct prefix_list
*plist
= output_arg
;
9459 if (prefix_list_apply(plist
, &rn
->p
)
9463 if (type
== bgp_show_type_filter_list
) {
9464 struct as_list
*as_list
= output_arg
;
9466 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9467 != AS_FILTER_PERMIT
)
9470 if (type
== bgp_show_type_route_map
) {
9471 struct route_map
*rmap
= output_arg
;
9472 struct bgp_path_info path
;
9473 struct attr dummy_attr
;
9474 route_map_result_t ret
;
9476 dummy_attr
= *pi
->attr
;
9478 path
.peer
= pi
->peer
;
9479 path
.attr
= &dummy_attr
;
9481 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9483 if (ret
== RMAP_DENYMATCH
)
9486 if (type
== bgp_show_type_neighbor
9487 || type
== bgp_show_type_flap_neighbor
9488 || type
== bgp_show_type_damp_neighbor
) {
9489 union sockunion
*su
= output_arg
;
9491 if (pi
->peer
== NULL
9492 || pi
->peer
->su_remote
== NULL
9493 || !sockunion_same(pi
->peer
->su_remote
, su
))
9496 if (type
== bgp_show_type_cidr_only
) {
9497 uint32_t destination
;
9499 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9500 if (IN_CLASSC(destination
)
9501 && rn
->p
.prefixlen
== 24)
9503 if (IN_CLASSB(destination
)
9504 && rn
->p
.prefixlen
== 16)
9506 if (IN_CLASSA(destination
)
9507 && rn
->p
.prefixlen
== 8)
9510 if (type
== bgp_show_type_prefix_longer
) {
9512 if (!prefix_match(p
, &rn
->p
))
9515 if (type
== bgp_show_type_community_all
) {
9516 if (!pi
->attr
->community
)
9519 if (type
== bgp_show_type_community
) {
9520 struct community
*com
= output_arg
;
9522 if (!pi
->attr
->community
9523 || !community_match(pi
->attr
->community
,
9527 if (type
== bgp_show_type_community_exact
) {
9528 struct community
*com
= output_arg
;
9530 if (!pi
->attr
->community
9531 || !community_cmp(pi
->attr
->community
, com
))
9534 if (type
== bgp_show_type_community_list
) {
9535 struct community_list
*list
= output_arg
;
9537 if (!community_list_match(pi
->attr
->community
,
9541 if (type
== bgp_show_type_community_list_exact
) {
9542 struct community_list
*list
= output_arg
;
9544 if (!community_list_exact_match(
9545 pi
->attr
->community
, list
))
9548 if (type
== bgp_show_type_lcommunity
) {
9549 struct lcommunity
*lcom
= output_arg
;
9551 if (!pi
->attr
->lcommunity
9552 || !lcommunity_match(pi
->attr
->lcommunity
,
9557 if (type
== bgp_show_type_lcommunity_exact
) {
9558 struct lcommunity
*lcom
= output_arg
;
9560 if (!pi
->attr
->lcommunity
9561 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9565 if (type
== bgp_show_type_lcommunity_list
) {
9566 struct community_list
*list
= output_arg
;
9568 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9573 == bgp_show_type_lcommunity_list_exact
) {
9574 struct community_list
*list
= output_arg
;
9576 if (!lcommunity_list_exact_match(
9577 pi
->attr
->lcommunity
, list
))
9580 if (type
== bgp_show_type_lcommunity_all
) {
9581 if (!pi
->attr
->lcommunity
)
9584 if (type
== bgp_show_type_dampend_paths
9585 || type
== bgp_show_type_damp_neighbor
) {
9586 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9587 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9591 if (!use_json
&& header
) {
9592 vty_out(vty
, "BGP table version is %" PRIu64
9593 ", local router ID is %s, vrf id ",
9595 inet_ntoa(bgp
->router_id
));
9596 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9597 vty_out(vty
, "%s", VRFID_NONE_STR
);
9599 vty_out(vty
, "%u", bgp
->vrf_id
);
9601 vty_out(vty
, "Default local pref %u, ",
9602 bgp
->default_local_pref
);
9603 vty_out(vty
, "local AS %u\n", bgp
->as
);
9604 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9605 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9606 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9607 if (type
== bgp_show_type_dampend_paths
9608 || type
== bgp_show_type_damp_neighbor
)
9609 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9610 else if (type
== bgp_show_type_flap_statistics
9611 || type
== bgp_show_type_flap_neighbor
)
9612 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9614 vty_out(vty
, BGP_SHOW_HEADER
);
9617 if (rd
!= NULL
&& !display
&& !output_count
) {
9620 "Route Distinguisher: %s\n",
9623 if (type
== bgp_show_type_dampend_paths
9624 || type
== bgp_show_type_damp_neighbor
)
9625 damp_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9626 safi
, use_json
, json_paths
);
9627 else if (type
== bgp_show_type_flap_statistics
9628 || type
== bgp_show_type_flap_neighbor
)
9629 flap_route_vty_out(vty
, &rn
->p
, pi
, display
, AFI_IP
,
9630 safi
, use_json
, json_paths
);
9632 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9644 if (p
->family
== AF_FLOWSPEC
) {
9645 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9647 bgp_fs_nlri_get_string((unsigned char *)
9648 p
->u
.prefix_flowspec
.ptr
,
9649 p
->u
.prefix_flowspec
9652 NLRI_STRING_FORMAT_MIN
,
9655 vty_out(vty
, "\"%s/%d\": ",
9657 p
->u
.prefix_flowspec
.prefixlen
);
9659 vty_out(vty
, ",\"%s/%d\": ",
9661 p
->u
.prefix_flowspec
.prefixlen
);
9663 prefix2str(p
, buf2
, sizeof(buf2
));
9665 vty_out(vty
, "\"%s\": ", buf2
);
9667 vty_out(vty
, ",\"%s\": ", buf2
);
9670 json_object_to_json_string_ext(
9671 json_paths
, JSON_C_TO_STRING_PRETTY
));
9672 json_object_free(json_paths
);
9676 json_object_free(json_paths
);
9680 output_count
+= *output_cum
;
9681 *output_cum
= output_count
;
9684 total_count
+= *total_cum
;
9685 *total_cum
= total_count
;
9689 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9693 for (i
= 0; i
< *json_header_depth
; ++i
)
9694 vty_out(vty
, " } ");
9699 /* No route is displayed */
9700 if (output_count
== 0) {
9701 if (type
== bgp_show_type_normal
)
9703 "No BGP prefixes displayed, %ld exist\n",
9707 "\nDisplayed %ld routes and %ld total paths\n",
9708 output_count
, total_count
);
9715 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9716 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9717 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9719 struct bgp_node
*rn
, *next
;
9720 unsigned long output_cum
= 0;
9721 unsigned long total_cum
= 0;
9722 unsigned long json_header_depth
= 0;
9723 struct bgp_table
*itable
;
9726 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9728 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9729 next
= bgp_route_next(rn
);
9730 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9733 itable
= bgp_node_get_bgp_table_info(rn
);
9734 if (itable
!= NULL
) {
9735 struct prefix_rd prd
;
9736 char rd
[RD_ADDRSTRLEN
];
9738 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9739 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9740 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9741 use_json
, rd
, next
== NULL
, &output_cum
,
9742 &total_cum
, &json_header_depth
);
9748 if (output_cum
== 0)
9749 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9753 "\nDisplayed %ld routes and %ld total paths\n",
9754 output_cum
, total_cum
);
9758 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9759 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9761 struct bgp_table
*table
;
9762 unsigned long json_header_depth
= 0;
9765 bgp
= bgp_get_default();
9770 vty_out(vty
, "No BGP process is configured\n");
9772 vty_out(vty
, "{}\n");
9776 table
= bgp
->rib
[afi
][safi
];
9777 /* use MPLS and ENCAP specific shows until they are merged */
9778 if (safi
== SAFI_MPLS_VPN
) {
9779 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9780 output_arg
, use_json
);
9783 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9784 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9785 output_arg
, use_json
,
9788 /* labeled-unicast routes live in the unicast table */
9789 else if (safi
== SAFI_LABELED_UNICAST
)
9790 safi
= SAFI_UNICAST
;
9792 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9793 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9796 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9797 safi_t safi
, bool use_json
)
9799 struct listnode
*node
, *nnode
;
9802 bool route_output
= false;
9805 vty_out(vty
, "{\n");
9807 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9808 route_output
= true;
9811 vty_out(vty
, ",\n");
9815 vty_out(vty
, "\"%s\":",
9816 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9820 vty_out(vty
, "\nInstance %s:\n",
9821 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9825 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9830 vty_out(vty
, "}\n");
9831 else if (!route_output
)
9832 vty_out(vty
, "%% BGP instance not found\n");
9835 /* Header of detailed BGP route information */
9836 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9837 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9838 afi_t afi
, safi_t safi
, json_object
*json
)
9840 struct bgp_path_info
*pi
;
9843 struct listnode
*node
, *nnode
;
9844 char buf1
[RD_ADDRSTRLEN
];
9845 char buf2
[INET6_ADDRSTRLEN
];
9846 char buf3
[EVPN_ROUTE_STRLEN
];
9847 char prefix_str
[BUFSIZ
];
9852 int route_filter_translated_v4
= 0;
9853 int route_filter_v4
= 0;
9854 int route_filter_translated_v6
= 0;
9855 int route_filter_v6
= 0;
9858 int accept_own_nexthop
= 0;
9861 int no_advertise
= 0;
9865 int has_valid_label
= 0;
9866 mpls_label_t label
= 0;
9867 json_object
*json_adv_to
= NULL
;
9870 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9872 if (has_valid_label
)
9873 label
= label_pton(&rn
->local_label
);
9875 if (safi
== SAFI_EVPN
) {
9878 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9879 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9880 : "", prd
? ":" : "",
9881 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9882 buf3
, sizeof(buf3
)));
9884 json_object_string_add(json
, "rd",
9885 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9887 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9891 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9892 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9893 ? prefix_rd2str(prd
, buf1
,
9896 safi
== SAFI_MPLS_VPN
? ":" : "",
9897 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9902 json_object_string_add(json
, "prefix",
9903 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9906 if (has_valid_label
) {
9908 json_object_int_add(json
, "localLabel", label
);
9910 vty_out(vty
, "Local label: %d\n", label
);
9914 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9915 vty_out(vty
, "not allocated\n");
9917 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9919 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9921 if (pi
->extra
&& pi
->extra
->suppress
)
9924 if (pi
->attr
->community
== NULL
)
9927 no_advertise
+= community_include(
9928 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9929 no_export
+= community_include(pi
->attr
->community
,
9930 COMMUNITY_NO_EXPORT
);
9931 local_as
+= community_include(pi
->attr
->community
,
9932 COMMUNITY_LOCAL_AS
);
9933 accept_own
+= community_include(pi
->attr
->community
,
9934 COMMUNITY_ACCEPT_OWN
);
9935 route_filter_translated_v4
+= community_include(
9936 pi
->attr
->community
,
9937 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9938 route_filter_translated_v6
+= community_include(
9939 pi
->attr
->community
,
9940 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9941 route_filter_v4
+= community_include(
9942 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9943 route_filter_v6
+= community_include(
9944 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9945 llgr_stale
+= community_include(pi
->attr
->community
,
9946 COMMUNITY_LLGR_STALE
);
9947 no_llgr
+= community_include(pi
->attr
->community
,
9949 accept_own_nexthop
+=
9950 community_include(pi
->attr
->community
,
9951 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9952 blackhole
+= community_include(pi
->attr
->community
,
9953 COMMUNITY_BLACKHOLE
);
9954 no_peer
+= community_include(pi
->attr
->community
,
9960 vty_out(vty
, "Paths: (%d available", count
);
9962 vty_out(vty
, ", best #%d", best
);
9963 if (safi
== SAFI_UNICAST
) {
9964 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9965 vty_out(vty
, ", table %s",
9968 vty_out(vty
, ", vrf %s",
9972 vty_out(vty
, ", no best path");
9976 ", accept own local route exported and imported in different VRF");
9977 else if (route_filter_translated_v4
)
9979 ", mark translated RTs for VPNv4 route filtering");
9980 else if (route_filter_v4
)
9982 ", attach RT as-is for VPNv4 route filtering");
9983 else if (route_filter_translated_v6
)
9985 ", mark translated RTs for VPNv6 route filtering");
9986 else if (route_filter_v6
)
9988 ", attach RT as-is for VPNv6 route filtering");
9989 else if (llgr_stale
)
9991 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9994 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9995 else if (accept_own_nexthop
)
9997 ", accept local nexthop");
9999 vty_out(vty
, ", inform peer to blackhole prefix");
10000 else if (no_export
)
10001 vty_out(vty
, ", not advertised to EBGP peer");
10002 else if (no_advertise
)
10003 vty_out(vty
, ", not advertised to any peer");
10005 vty_out(vty
, ", not advertised outside local AS");
10008 ", inform EBGP peer not to advertise to their EBGP peers");
10012 ", Advertisements suppressed by an aggregate.");
10013 vty_out(vty
, ")\n");
10016 /* If we are not using addpath then we can display Advertised to and
10018 * show what peers we advertised the bestpath to. If we are using
10020 * though then we must display Advertised to on a path-by-path basis. */
10021 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
10022 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
10023 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
10024 if (json
&& !json_adv_to
)
10025 json_adv_to
= json_object_new_object();
10027 route_vty_out_advertised_to(
10029 " Advertised to non peer-group peers:\n ",
10036 json_object_object_add(json
, "advertisedTo",
10041 vty_out(vty
, " Not advertised to any peer");
10042 vty_out(vty
, "\n");
10047 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
10048 struct bgp_node
*bgp_node
, struct vty
*vty
,
10049 struct bgp
*bgp
, afi_t afi
,
10050 safi_t safi
, json_object
*json
,
10051 enum bgp_path_type pathtype
, int *display
)
10053 struct bgp_path_info
*pi
;
10055 char rdbuf
[RD_ADDRSTRLEN
];
10056 json_object
*json_header
= NULL
;
10057 json_object
*json_paths
= NULL
;
10059 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
10062 if (json
&& !json_paths
) {
10063 /* Instantiate json_paths only if path is valid */
10064 json_paths
= json_object_new_array();
10066 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
10067 json_header
= json_object_new_object();
10069 json_header
= json
;
10073 route_vty_out_detail_header(
10074 vty
, bgp
, bgp_node
, pfx_rd
,
10075 AFI_IP
, safi
, json_header
);
10080 if (pathtype
== BGP_PATH_SHOW_ALL
10081 || (pathtype
== BGP_PATH_SHOW_BESTPATH
10082 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
10083 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
10084 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
10085 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
10086 route_vty_out_detail(vty
, bgp
, bgp_node
,
10091 if (json
&& json_paths
) {
10092 json_object_object_add(json_header
, "paths", json_paths
);
10095 json_object_object_add(json
, rdbuf
, json_header
);
10099 /* Display specified route of BGP table. */
10100 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
10101 struct bgp_table
*rib
, const char *ip_str
,
10102 afi_t afi
, safi_t safi
,
10103 struct prefix_rd
*prd
, int prefix_check
,
10104 enum bgp_path_type pathtype
, bool use_json
)
10108 struct prefix match
;
10109 struct bgp_node
*rn
;
10110 struct bgp_node
*rm
;
10111 struct bgp_table
*table
;
10112 json_object
*json
= NULL
;
10113 json_object
*json_paths
= NULL
;
10115 /* Check IP address argument. */
10116 ret
= str2prefix(ip_str
, &match
);
10118 vty_out(vty
, "address is malformed\n");
10119 return CMD_WARNING
;
10122 match
.family
= afi2family(afi
);
10125 json
= json_object_new_object();
10127 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
10128 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10129 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10131 table
= bgp_node_get_bgp_table_info(rn
);
10135 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10139 && rm
->p
.prefixlen
!= match
.prefixlen
) {
10140 bgp_unlock_node(rm
);
10144 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10145 vty
, bgp
, afi
, safi
, json
,
10146 pathtype
, &display
);
10148 bgp_unlock_node(rm
);
10150 } else if (safi
== SAFI_EVPN
) {
10151 struct bgp_node
*longest_pfx
;
10152 bool is_exact_pfxlen_match
= FALSE
;
10154 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
10155 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10157 table
= bgp_node_get_bgp_table_info(rn
);
10161 longest_pfx
= NULL
;
10162 is_exact_pfxlen_match
= FALSE
;
10164 * Search through all the prefixes for a match. The
10165 * pfx's are enumerated in ascending order of pfxlens.
10166 * So, the last pfx match is the longest match. Set
10167 * is_exact_pfxlen_match when we get exact pfxlen match
10169 for (rm
= bgp_table_top(table
); rm
;
10170 rm
= bgp_route_next(rm
)) {
10172 * Get prefixlen of the ip-prefix within type5
10175 if (evpn_type5_prefix_match(&rm
->p
,
10176 &match
) && rm
->info
) {
10179 bgp_evpn_get_type5_prefixlen(&rm
->p
);
10180 if (type5_pfxlen
== match
.prefixlen
) {
10181 is_exact_pfxlen_match
= TRUE
;
10182 bgp_unlock_node(rm
);
10191 if (prefix_check
&& !is_exact_pfxlen_match
)
10197 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
10198 vty
, bgp
, afi
, safi
, json
,
10199 pathtype
, &display
);
10201 bgp_unlock_node(rm
);
10203 } else if (safi
== SAFI_FLOWSPEC
) {
10205 json_paths
= json_object_new_array();
10207 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
10208 &match
, prefix_check
,
10212 if (use_json
&& display
)
10213 json_object_object_add(json
, "paths", json_paths
);
10215 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
10217 || rn
->p
.prefixlen
== match
.prefixlen
) {
10218 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
10220 pathtype
, &display
);
10223 bgp_unlock_node(rn
);
10228 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10229 json
, JSON_C_TO_STRING_PRETTY
|
10230 JSON_C_TO_STRING_NOSLASHESCAPE
));
10231 json_object_free(json
);
10234 vty_out(vty
, "%% Network not in table\n");
10235 return CMD_WARNING
;
10239 return CMD_SUCCESS
;
10242 /* Display specified route of Main RIB */
10243 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
10244 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
10245 int prefix_check
, enum bgp_path_type pathtype
,
10249 bgp
= bgp_get_default();
10252 vty_out(vty
, "No BGP process is configured\n");
10254 vty_out(vty
, "{}\n");
10255 return CMD_WARNING
;
10259 /* labeled-unicast routes live in the unicast table */
10260 if (safi
== SAFI_LABELED_UNICAST
)
10261 safi
= SAFI_UNICAST
;
10263 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
10264 afi
, safi
, prd
, prefix_check
, pathtype
,
10268 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
10269 struct cmd_token
**argv
, bool exact
, afi_t afi
,
10270 safi_t safi
, bool uj
)
10272 struct lcommunity
*lcom
;
10278 b
= buffer_new(1024);
10279 for (i
= 0; i
< argc
; i
++) {
10281 buffer_putc(b
, ' ');
10283 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
10285 buffer_putstr(b
, argv
[i
]->arg
);
10289 buffer_putc(b
, '\0');
10291 str
= buffer_getstr(b
);
10294 lcom
= lcommunity_str2com(str
);
10295 XFREE(MTYPE_TMP
, str
);
10297 vty_out(vty
, "%% Large-community malformed\n");
10298 return CMD_WARNING
;
10301 return bgp_show(vty
, bgp
, afi
, safi
,
10302 (exact
? bgp_show_type_lcommunity_exact
10303 : bgp_show_type_lcommunity
),
10307 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
10308 const char *lcom
, bool exact
, afi_t afi
,
10309 safi_t safi
, bool uj
)
10311 struct community_list
*list
;
10313 list
= community_list_lookup(bgp_clist
, lcom
, 0,
10314 LARGE_COMMUNITY_LIST_MASTER
);
10315 if (list
== NULL
) {
10316 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
10318 return CMD_WARNING
;
10321 return bgp_show(vty
, bgp
, afi
, safi
,
10322 (exact
? bgp_show_type_lcommunity_list_exact
10323 : bgp_show_type_lcommunity_list
),
10327 DEFUN (show_ip_bgp_large_community_list
,
10328 show_ip_bgp_large_community_list_cmd
,
10329 "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]",
10333 BGP_INSTANCE_HELP_STR
10335 BGP_SAFI_WITH_LABEL_HELP_STR
10336 "Display routes matching the large-community-list\n"
10337 "large-community-list number\n"
10338 "large-community-list name\n"
10339 "Exact match of the large-communities\n"
10343 afi_t afi
= AFI_IP6
;
10344 safi_t safi
= SAFI_UNICAST
;
10346 bool exact_match
= 0;
10348 if (argv_find(argv
, argc
, "ip", &idx
))
10350 if (argv_find(argv
, argc
, "view", &idx
)
10351 || argv_find(argv
, argc
, "vrf", &idx
))
10352 vrf
= argv
[++idx
]->arg
;
10353 if (argv_find(argv
, argc
, "ipv4", &idx
)
10354 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10355 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10356 if (argv_find(argv
, argc
, "unicast", &idx
)
10357 || argv_find(argv
, argc
, "multicast", &idx
))
10358 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10361 bool uj
= use_json(argc
, argv
);
10363 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10365 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10366 return CMD_WARNING
;
10369 argv_find(argv
, argc
, "large-community-list", &idx
);
10371 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10373 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10376 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10377 exact_match
, afi
, safi
, uj
);
10379 DEFUN (show_ip_bgp_large_community
,
10380 show_ip_bgp_large_community_cmd
,
10381 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10385 BGP_INSTANCE_HELP_STR
10387 BGP_SAFI_WITH_LABEL_HELP_STR
10388 "Display routes matching the large-communities\n"
10389 "List of large-community numbers\n"
10390 "Exact match of the large-communities\n"
10394 afi_t afi
= AFI_IP6
;
10395 safi_t safi
= SAFI_UNICAST
;
10397 bool exact_match
= 0;
10399 if (argv_find(argv
, argc
, "ip", &idx
))
10401 if (argv_find(argv
, argc
, "view", &idx
)
10402 || argv_find(argv
, argc
, "vrf", &idx
))
10403 vrf
= argv
[++idx
]->arg
;
10404 if (argv_find(argv
, argc
, "ipv4", &idx
)
10405 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10406 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10407 if (argv_find(argv
, argc
, "unicast", &idx
)
10408 || argv_find(argv
, argc
, "multicast", &idx
))
10409 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10412 bool uj
= use_json(argc
, argv
);
10414 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10416 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10417 return CMD_WARNING
;
10420 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10421 if (argv_find(argv
, argc
, "exact-match", &idx
))
10423 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10424 exact_match
, afi
, safi
, uj
);
10426 return bgp_show(vty
, bgp
, afi
, safi
,
10427 bgp_show_type_lcommunity_all
, NULL
, uj
);
10430 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10434 /* BGP route print out function without JSON */
10435 DEFUN (show_ip_bgp
,
10437 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10438 <dampening <parameters>\
10443 |community-list <(1-500)|WORD> [exact-match]\
10444 |A.B.C.D/M longer-prefixes\
10445 |X:X::X:X/M longer-prefixes\
10450 BGP_INSTANCE_HELP_STR
10452 BGP_SAFI_WITH_LABEL_HELP_STR
10453 "Display detailed information about dampening\n"
10454 "Display detail of configured dampening parameters\n"
10455 "Display routes matching the route-map\n"
10456 "A route-map to match on\n"
10457 "Display routes conforming to the prefix-list\n"
10458 "Prefix-list name\n"
10459 "Display routes conforming to the filter-list\n"
10460 "Regular expression access list name\n"
10461 "BGP RIB advertisement statistics\n"
10462 "Display routes matching the community-list\n"
10463 "community-list number\n"
10464 "community-list name\n"
10465 "Exact match of the communities\n"
10467 "Display route and more specific routes\n"
10469 "Display route and more specific routes\n")
10471 afi_t afi
= AFI_IP6
;
10472 safi_t safi
= SAFI_UNICAST
;
10473 int exact_match
= 0;
10474 struct bgp
*bgp
= NULL
;
10477 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10480 return CMD_WARNING
;
10482 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10483 if (argv_find(argv
, argc
, "parameters", &idx
))
10484 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10487 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10488 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10489 safi
, bgp_show_type_prefix_list
);
10491 if (argv_find(argv
, argc
, "filter-list", &idx
))
10492 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10493 safi
, bgp_show_type_filter_list
);
10495 if (argv_find(argv
, argc
, "statistics", &idx
))
10496 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10498 if (argv_find(argv
, argc
, "route-map", &idx
))
10499 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10500 safi
, bgp_show_type_route_map
);
10502 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10503 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10504 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10506 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10507 exact_match
, afi
, safi
);
10509 /* prefix-longer */
10510 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10511 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10512 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10514 bgp_show_type_prefix_longer
);
10516 return CMD_WARNING
;
10519 /* BGP route print out function with JSON */
10520 DEFUN (show_ip_bgp_json
,
10521 show_ip_bgp_json_cmd
,
10522 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10524 |dampening <flap-statistics|dampened-paths>\
10525 |community [AA:NN|local-AS|no-advertise|no-export\
10526 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10527 |accept-own|accept-own-nexthop|route-filter-v6\
10528 |route-filter-v4|route-filter-translated-v6\
10529 |route-filter-translated-v4] [exact-match]\
10534 BGP_INSTANCE_HELP_STR
10536 BGP_SAFI_WITH_LABEL_HELP_STR
10537 "Display only routes with non-natural netmasks\n"
10538 "Display detailed information about dampening\n"
10539 "Display flap statistics of routes\n"
10540 "Display paths suppressed due to dampening\n"
10541 "Display routes matching the communities\n"
10543 "Do not send outside local AS (well-known community)\n"
10544 "Do not advertise to any peer (well-known community)\n"
10545 "Do not export to next AS (well-known community)\n"
10546 "Graceful shutdown (well-known community)\n"
10547 "Do not export to any peer (well-known community)\n"
10548 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10549 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10550 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10551 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10552 "Should accept VPN route with local nexthop (well-known community)\n"
10553 "RT VPNv6 route filtering (well-known community)\n"
10554 "RT VPNv4 route filtering (well-known community)\n"
10555 "RT translated VPNv6 route filtering (well-known community)\n"
10556 "RT translated VPNv4 route filtering (well-known community)\n"
10557 "Exact match of the communities\n"
10560 afi_t afi
= AFI_IP6
;
10561 safi_t safi
= SAFI_UNICAST
;
10562 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10563 struct bgp
*bgp
= NULL
;
10565 int exact_match
= 0;
10566 bool uj
= use_json(argc
, argv
);
10571 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10574 return CMD_WARNING
;
10576 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10577 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10580 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10581 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10582 return bgp_show(vty
, bgp
, afi
, safi
,
10583 bgp_show_type_dampend_paths
, NULL
, uj
);
10584 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10585 return bgp_show(vty
, bgp
, afi
, safi
,
10586 bgp_show_type_flap_statistics
, NULL
,
10590 if (argv_find(argv
, argc
, "community", &idx
)) {
10591 char *maybecomm
= NULL
;
10592 char *community
= NULL
;
10594 if (idx
+ 1 < argc
) {
10595 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10596 maybecomm
= argv
[idx
+ 1]->arg
;
10598 maybecomm
= argv
[idx
+ 1]->text
;
10601 if (maybecomm
&& !strmatch(maybecomm
, "json")
10602 && !strmatch(maybecomm
, "exact-match"))
10603 community
= maybecomm
;
10605 if (argv_find(argv
, argc
, "exact-match", &idx
))
10609 return bgp_show_community(vty
, bgp
, community
,
10610 exact_match
, afi
, safi
, uj
);
10612 return (bgp_show(vty
, bgp
, afi
, safi
,
10613 bgp_show_type_community_all
, NULL
,
10617 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10620 DEFUN (show_ip_bgp_route
,
10621 show_ip_bgp_route_cmd
,
10622 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10623 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10627 BGP_INSTANCE_HELP_STR
10629 BGP_SAFI_WITH_LABEL_HELP_STR
10630 "Network in the BGP routing table to display\n"
10632 "Network in the BGP routing table to display\n"
10634 "Display only the bestpath\n"
10635 "Display only multipaths\n"
10638 int prefix_check
= 0;
10640 afi_t afi
= AFI_IP6
;
10641 safi_t safi
= SAFI_UNICAST
;
10642 char *prefix
= NULL
;
10643 struct bgp
*bgp
= NULL
;
10644 enum bgp_path_type path_type
;
10645 bool uj
= use_json(argc
, argv
);
10649 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10652 return CMD_WARNING
;
10656 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10657 return CMD_WARNING
;
10660 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10661 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10662 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10664 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10665 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10668 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10669 && afi
!= AFI_IP6
) {
10671 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10672 return CMD_WARNING
;
10674 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10675 && afi
!= AFI_IP
) {
10677 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10678 return CMD_WARNING
;
10681 prefix
= argv
[idx
]->arg
;
10683 /* [<bestpath|multipath>] */
10684 if (argv_find(argv
, argc
, "bestpath", &idx
))
10685 path_type
= BGP_PATH_SHOW_BESTPATH
;
10686 else if (argv_find(argv
, argc
, "multipath", &idx
))
10687 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10689 path_type
= BGP_PATH_SHOW_ALL
;
10691 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10695 DEFUN (show_ip_bgp_regexp
,
10696 show_ip_bgp_regexp_cmd
,
10697 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX [json]",
10701 BGP_INSTANCE_HELP_STR
10703 BGP_SAFI_WITH_LABEL_HELP_STR
10704 "Display routes matching the AS path regular expression\n"
10705 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
10708 afi_t afi
= AFI_IP6
;
10709 safi_t safi
= SAFI_UNICAST
;
10710 struct bgp
*bgp
= NULL
;
10711 bool uj
= use_json(argc
, argv
);
10712 char *regstr
= NULL
;
10715 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10718 return CMD_WARNING
;
10720 // get index of regex
10721 if (argv_find(argv
, argc
, "REGEX", &idx
))
10722 regstr
= argv
[idx
]->arg
;
10724 return bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10725 bgp_show_type_regexp
, uj
);
10728 DEFUN (show_ip_bgp_instance_all
,
10729 show_ip_bgp_instance_all_cmd
,
10730 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10734 BGP_INSTANCE_ALL_HELP_STR
10736 BGP_SAFI_WITH_LABEL_HELP_STR
10739 afi_t afi
= AFI_IP
;
10740 safi_t safi
= SAFI_UNICAST
;
10741 struct bgp
*bgp
= NULL
;
10743 bool uj
= use_json(argc
, argv
);
10748 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10751 return CMD_WARNING
;
10753 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10754 return CMD_SUCCESS
;
10757 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10758 afi_t afi
, safi_t safi
, enum bgp_show_type type
,
10764 if (!config_bgp_aspath_validate(regstr
)) {
10765 vty_out(vty
, "Invalid character in REGEX %s\n",
10767 return CMD_WARNING_CONFIG_FAILED
;
10770 regex
= bgp_regcomp(regstr
);
10772 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10773 return CMD_WARNING
;
10776 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, use_json
);
10777 bgp_regex_free(regex
);
10781 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10782 const char *prefix_list_str
, afi_t afi
,
10783 safi_t safi
, enum bgp_show_type type
)
10785 struct prefix_list
*plist
;
10787 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10788 if (plist
== NULL
) {
10789 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10791 return CMD_WARNING
;
10794 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10797 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10798 const char *filter
, afi_t afi
, safi_t safi
,
10799 enum bgp_show_type type
)
10801 struct as_list
*as_list
;
10803 as_list
= as_list_lookup(filter
);
10804 if (as_list
== NULL
) {
10805 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10807 return CMD_WARNING
;
10810 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10813 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10814 const char *rmap_str
, afi_t afi
, safi_t safi
,
10815 enum bgp_show_type type
)
10817 struct route_map
*rmap
;
10819 rmap
= route_map_lookup_by_name(rmap_str
);
10821 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10822 return CMD_WARNING
;
10825 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10828 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10829 const char *comstr
, int exact
, afi_t afi
,
10830 safi_t safi
, bool use_json
)
10832 struct community
*com
;
10835 com
= community_str2com(comstr
);
10837 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10838 return CMD_WARNING
;
10841 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10842 (exact
? bgp_show_type_community_exact
10843 : bgp_show_type_community
),
10845 community_free(&com
);
10850 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10851 const char *com
, int exact
, afi_t afi
,
10854 struct community_list
*list
;
10856 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10857 if (list
== NULL
) {
10858 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10859 return CMD_WARNING
;
10862 return bgp_show(vty
, bgp
, afi
, safi
,
10863 (exact
? bgp_show_type_community_list_exact
10864 : bgp_show_type_community_list
),
10868 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10869 const char *prefix
, afi_t afi
, safi_t safi
,
10870 enum bgp_show_type type
)
10877 ret
= str2prefix(prefix
, p
);
10879 vty_out(vty
, "%% Malformed Prefix\n");
10880 return CMD_WARNING
;
10883 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10889 BGP_STATS_MAXBITLEN
= 0,
10891 BGP_STATS_PREFIXES
,
10893 BGP_STATS_UNAGGREGATEABLE
,
10894 BGP_STATS_MAX_AGGREGATEABLE
,
10895 BGP_STATS_AGGREGATES
,
10897 BGP_STATS_ASPATH_COUNT
,
10898 BGP_STATS_ASPATH_MAXHOPS
,
10899 BGP_STATS_ASPATH_TOTHOPS
,
10900 BGP_STATS_ASPATH_MAXSIZE
,
10901 BGP_STATS_ASPATH_TOTSIZE
,
10902 BGP_STATS_ASN_HIGHEST
,
10906 static const char *const table_stats_strs
[] = {
10907 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10908 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10909 [BGP_STATS_RIB
] = "Total Advertisements",
10910 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10911 [BGP_STATS_MAX_AGGREGATEABLE
] =
10912 "Maximum aggregateable prefixes",
10913 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10914 [BGP_STATS_SPACE
] = "Address space advertised",
10915 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10916 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10917 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10918 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10919 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10920 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10921 [BGP_STATS_MAX
] = NULL
,
10924 struct bgp_table_stats
{
10925 struct bgp_table
*table
;
10926 unsigned long long counts
[BGP_STATS_MAX
];
10927 double total_space
;
10931 #define TALLY_SIGFIG 100000
10932 static unsigned long
10933 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10935 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10936 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10937 unsigned long ret
= newtot
/ count
;
10939 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10946 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10947 struct bgp_table_stats
*ts
, unsigned int space
)
10949 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10950 struct bgp_path_info
*pi
;
10955 if (!bgp_node_has_bgp_path_info_data(rn
))
10958 ts
->counts
[BGP_STATS_PREFIXES
]++;
10959 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10962 ts
->counts
[BGP_STATS_AVGPLEN
]
10963 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10964 ts
->counts
[BGP_STATS_AVGPLEN
],
10968 /* check if the prefix is included by any other announcements */
10969 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10970 prn
= bgp_node_parent_nolock(prn
);
10972 if (prn
== NULL
|| prn
== top
) {
10973 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10974 /* announced address space */
10976 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10977 } else if (bgp_node_has_bgp_path_info_data(prn
))
10978 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10981 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10982 ts
->counts
[BGP_STATS_RIB
]++;
10984 if (CHECK_FLAG(pi
->attr
->flag
,
10985 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10986 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10988 /* as-path stats */
10989 if (pi
->attr
->aspath
) {
10990 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10991 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10992 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10994 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10996 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10997 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10999 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
11000 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
11002 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
11003 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
11005 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
11006 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11007 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
11009 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
11010 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
11011 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
11014 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
11015 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
11020 static int bgp_table_stats_walker(struct thread
*t
)
11022 struct bgp_node
*rn
, *nrn
;
11023 struct bgp_node
*top
;
11024 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
11025 unsigned int space
= 0;
11027 if (!(top
= bgp_table_top(ts
->table
)))
11030 switch (ts
->table
->afi
) {
11032 space
= IPV4_MAX_BITLEN
;
11035 space
= IPV6_MAX_BITLEN
;
11041 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
11043 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
11044 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
11045 struct bgp_table
*table
;
11047 table
= bgp_node_get_bgp_table_info(rn
);
11051 top
= bgp_table_top(table
);
11052 for (nrn
= bgp_table_top(table
); nrn
;
11053 nrn
= bgp_route_next(nrn
))
11054 bgp_table_stats_rn(nrn
, top
, ts
, space
);
11056 bgp_table_stats_rn(rn
, top
, ts
, space
);
11063 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11066 struct bgp_table_stats ts
;
11069 if (!bgp
->rib
[afi
][safi
]) {
11070 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
11072 return CMD_WARNING
;
11075 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
11077 /* labeled-unicast routes live in the unicast table */
11078 if (safi
== SAFI_LABELED_UNICAST
)
11079 safi
= SAFI_UNICAST
;
11081 memset(&ts
, 0, sizeof(ts
));
11082 ts
.table
= bgp
->rib
[afi
][safi
];
11083 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
11085 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
11086 if (!table_stats_strs
[i
])
11091 case BGP_STATS_ASPATH_AVGHOPS
:
11092 case BGP_STATS_ASPATH_AVGSIZE
:
11093 case BGP_STATS_AVGPLEN
:
11094 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
11095 vty_out (vty
, "%12.2f",
11096 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
11099 case BGP_STATS_ASPATH_TOTHOPS
:
11100 case BGP_STATS_ASPATH_TOTSIZE
:
11101 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11102 vty_out(vty
, "%12.2f",
11104 ? (float)ts
.counts
[i
]
11106 [BGP_STATS_ASPATH_COUNT
]
11109 case BGP_STATS_TOTPLEN
:
11110 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11111 vty_out(vty
, "%12.2f",
11113 ? (float)ts
.counts
[i
]
11115 [BGP_STATS_PREFIXES
]
11118 case BGP_STATS_SPACE
:
11119 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11120 vty_out(vty
, "%12g\n", ts
.total_space
);
11122 if (afi
== AFI_IP6
) {
11123 vty_out(vty
, "%30s: ", "/32 equivalent ");
11124 vty_out(vty
, "%12g\n",
11125 ts
.total_space
* pow(2.0, -128 + 32));
11126 vty_out(vty
, "%30s: ", "/48 equivalent ");
11127 vty_out(vty
, "%12g\n",
11128 ts
.total_space
* pow(2.0, -128 + 48));
11130 vty_out(vty
, "%30s: ", "% announced ");
11131 vty_out(vty
, "%12.2f\n",
11132 ts
.total_space
* 100. * pow(2.0, -32));
11133 vty_out(vty
, "%30s: ", "/8 equivalent ");
11134 vty_out(vty
, "%12.2f\n",
11135 ts
.total_space
* pow(2.0, -32 + 8));
11136 vty_out(vty
, "%30s: ", "/24 equivalent ");
11137 vty_out(vty
, "%12.2f\n",
11138 ts
.total_space
* pow(2.0, -32 + 24));
11142 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
11143 vty_out(vty
, "%12llu", ts
.counts
[i
]);
11146 vty_out(vty
, "\n");
11148 return CMD_SUCCESS
;
11160 PCOUNT_PFCNT
, /* the figure we display to users */
11164 static const char *const pcount_strs
[] = {
11165 [PCOUNT_ADJ_IN
] = "Adj-in",
11166 [PCOUNT_DAMPED
] = "Damped",
11167 [PCOUNT_REMOVED
] = "Removed",
11168 [PCOUNT_HISTORY
] = "History",
11169 [PCOUNT_STALE
] = "Stale",
11170 [PCOUNT_VALID
] = "Valid",
11171 [PCOUNT_ALL
] = "All RIB",
11172 [PCOUNT_COUNTED
] = "PfxCt counted",
11173 [PCOUNT_PFCNT
] = "Useable",
11174 [PCOUNT_MAX
] = NULL
,
11177 struct peer_pcounts
{
11178 unsigned int count
[PCOUNT_MAX
];
11179 const struct peer
*peer
;
11180 const struct bgp_table
*table
;
11184 static void bgp_peer_count_proc(struct bgp_node
*rn
,
11185 struct peer_pcounts
*pc
)
11187 const struct bgp_adj_in
*ain
;
11188 const struct bgp_path_info
*pi
;
11189 const struct peer
*peer
= pc
->peer
;
11191 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
11192 if (ain
->peer
== peer
)
11193 pc
->count
[PCOUNT_ADJ_IN
]++;
11195 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
11197 if (pi
->peer
!= peer
)
11200 pc
->count
[PCOUNT_ALL
]++;
11202 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
11203 pc
->count
[PCOUNT_DAMPED
]++;
11204 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
11205 pc
->count
[PCOUNT_HISTORY
]++;
11206 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
11207 pc
->count
[PCOUNT_REMOVED
]++;
11208 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
11209 pc
->count
[PCOUNT_STALE
]++;
11210 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
11211 pc
->count
[PCOUNT_VALID
]++;
11212 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11213 pc
->count
[PCOUNT_PFCNT
]++;
11215 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
11216 pc
->count
[PCOUNT_COUNTED
]++;
11217 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11219 EC_LIB_DEVELOPMENT
,
11220 "Attempting to count but flags say it is unusable");
11222 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
11224 EC_LIB_DEVELOPMENT
,
11225 "Not counted but flags say we should");
11230 static int bgp_peer_count_walker(struct thread
*t
)
11232 struct bgp_node
*rn
, *rm
;
11233 const struct bgp_table
*table
;
11234 struct peer_pcounts
*pc
= THREAD_ARG(t
);
11236 if (pc
->safi
== SAFI_MPLS_VPN
|| pc
->safi
== SAFI_ENCAP
11237 || pc
->safi
== SAFI_EVPN
) {
11238 /* Special handling for 2-level routing tables. */
11239 for (rn
= bgp_table_top(pc
->table
); rn
;
11240 rn
= bgp_route_next(rn
)) {
11241 table
= bgp_node_get_bgp_table_info(rn
);
11243 for (rm
= bgp_table_top(table
); rm
;
11244 rm
= bgp_route_next(rm
))
11245 bgp_peer_count_proc(rm
, pc
);
11248 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
))
11249 bgp_peer_count_proc(rn
, pc
);
11254 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11255 safi_t safi
, bool use_json
)
11257 struct peer_pcounts pcounts
= {.peer
= peer
};
11259 json_object
*json
= NULL
;
11260 json_object
*json_loop
= NULL
;
11263 json
= json_object_new_object();
11264 json_loop
= json_object_new_object();
11267 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
11268 || !peer
->bgp
->rib
[afi
][safi
]) {
11270 json_object_string_add(
11272 "No such neighbor or address family");
11273 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11274 json_object_free(json
);
11276 vty_out(vty
, "%% No such neighbor or address family\n");
11278 return CMD_WARNING
;
11281 memset(&pcounts
, 0, sizeof(pcounts
));
11282 pcounts
.peer
= peer
;
11283 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
11284 pcounts
.safi
= safi
;
11286 /* in-place call via thread subsystem so as to record execution time
11287 * stats for the thread-walk (i.e. ensure this can't be blamed on
11288 * on just vty_read()).
11290 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
11293 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
11294 json_object_string_add(json
, "multiProtocol",
11295 get_afi_safi_str(afi
, safi
, true));
11296 json_object_int_add(json
, "pfxCounter",
11297 peer
->pcount
[afi
][safi
]);
11299 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11300 json_object_int_add(json_loop
, pcount_strs
[i
],
11303 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
11305 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11306 json_object_string_add(json
, "pfxctDriftFor",
11308 json_object_string_add(
11309 json
, "recommended",
11310 "Please report this bug, with the above command output");
11312 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11313 json
, JSON_C_TO_STRING_PRETTY
));
11314 json_object_free(json
);
11318 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
11319 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
11320 peer
->hostname
, peer
->host
,
11321 get_afi_safi_str(afi
, safi
, false));
11323 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
11324 get_afi_safi_str(afi
, safi
, false));
11327 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
11328 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
11330 for (i
= 0; i
< PCOUNT_MAX
; i
++)
11331 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
11334 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
11335 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
11337 "Please report this bug, with the above command output\n");
11341 return CMD_SUCCESS
;
11344 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
11345 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
11346 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11347 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11351 BGP_INSTANCE_HELP_STR
11354 "Detailed information on TCP and BGP neighbor connections\n"
11355 "Neighbor to display information about\n"
11356 "Neighbor to display information about\n"
11357 "Neighbor on BGP configured interface\n"
11358 "Display detailed prefix count information\n"
11361 afi_t afi
= AFI_IP6
;
11362 safi_t safi
= SAFI_UNICAST
;
11365 struct bgp
*bgp
= NULL
;
11366 bool uj
= use_json(argc
, argv
);
11371 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11374 return CMD_WARNING
;
11376 argv_find(argv
, argc
, "neighbors", &idx
);
11377 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11379 return CMD_WARNING
;
11381 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11384 #ifdef KEEP_OLD_VPN_COMMANDS
11385 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11386 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11387 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11392 "Display information about all VPNv4 NLRIs\n"
11393 "Detailed information on TCP and BGP neighbor connections\n"
11394 "Neighbor to display information about\n"
11395 "Neighbor to display information about\n"
11396 "Neighbor on BGP configured interface\n"
11397 "Display detailed prefix count information\n"
11402 bool uj
= use_json(argc
, argv
);
11404 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11406 return CMD_WARNING
;
11408 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11411 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11412 show_ip_bgp_vpn_all_route_prefix_cmd
,
11413 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11418 "Display information about all VPNv4 NLRIs\n"
11419 "Network in the BGP routing table to display\n"
11420 "Network in the BGP routing table to display\n"
11424 char *network
= NULL
;
11425 struct bgp
*bgp
= bgp_get_default();
11427 vty_out(vty
, "Can't find default instance\n");
11428 return CMD_WARNING
;
11431 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11432 network
= argv
[idx
]->arg
;
11433 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11434 network
= argv
[idx
]->arg
;
11436 vty_out(vty
, "Unable to figure out Network\n");
11437 return CMD_WARNING
;
11440 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11441 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11443 #endif /* KEEP_OLD_VPN_COMMANDS */
11445 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11446 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11447 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11452 "Network in the BGP routing table to display\n"
11453 "Network in the BGP routing table to display\n"
11454 "Network in the BGP routing table to display\n"
11455 "Network in the BGP routing table to display\n"
11459 char *network
= NULL
;
11460 int prefix_check
= 0;
11462 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11463 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11464 network
= argv
[idx
]->arg
;
11465 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11466 argv_find(argv
, argc
, "X:X::X:X/M", &idx
)) {
11467 network
= argv
[idx
]->arg
;
11470 vty_out(vty
, "Unable to figure out Network\n");
11471 return CMD_WARNING
;
11473 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11474 prefix_check
, BGP_PATH_SHOW_ALL
,
11475 use_json(argc
, argv
));
11478 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11479 safi_t safi
, enum bgp_show_adj_route_type type
,
11480 const char *rmap_name
, bool use_json
,
11483 struct bgp_table
*table
;
11484 struct bgp_adj_in
*ain
;
11485 struct bgp_adj_out
*adj
;
11486 unsigned long output_count
;
11487 unsigned long filtered_count
;
11488 struct bgp_node
*rn
;
11494 struct update_subgroup
*subgrp
;
11495 json_object
*json_scode
= NULL
;
11496 json_object
*json_ocode
= NULL
;
11497 json_object
*json_ar
= NULL
;
11498 struct peer_af
*paf
;
11499 bool route_filtered
;
11502 json_scode
= json_object_new_object();
11503 json_ocode
= json_object_new_object();
11504 json_ar
= json_object_new_object();
11506 json_object_string_add(json_scode
, "suppressed", "s");
11507 json_object_string_add(json_scode
, "damped", "d");
11508 json_object_string_add(json_scode
, "history", "h");
11509 json_object_string_add(json_scode
, "valid", "*");
11510 json_object_string_add(json_scode
, "best", ">");
11511 json_object_string_add(json_scode
, "multipath", "=");
11512 json_object_string_add(json_scode
, "internal", "i");
11513 json_object_string_add(json_scode
, "ribFailure", "r");
11514 json_object_string_add(json_scode
, "stale", "S");
11515 json_object_string_add(json_scode
, "removed", "R");
11517 json_object_string_add(json_ocode
, "igp", "i");
11518 json_object_string_add(json_ocode
, "egp", "e");
11519 json_object_string_add(json_ocode
, "incomplete", "?");
11526 json_object_string_add(json
, "alert", "no BGP");
11527 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11528 json_object_free(json
);
11530 vty_out(vty
, "%% No bgp\n");
11534 /* labeled-unicast routes live in the unicast table */
11535 if (safi
== SAFI_LABELED_UNICAST
)
11536 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11538 table
= bgp
->rib
[afi
][safi
];
11540 output_count
= filtered_count
= 0;
11541 subgrp
= peer_subgroup(peer
, afi
, safi
);
11543 if (type
== bgp_show_adj_route_advertised
&& subgrp
11544 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11546 json_object_int_add(json
, "bgpTableVersion",
11548 json_object_string_add(json
, "bgpLocalRouterId",
11549 inet_ntoa(bgp
->router_id
));
11550 json_object_int_add(json
, "defaultLocPrf",
11551 bgp
->default_local_pref
);
11552 json_object_int_add(json
, "localAS", bgp
->as
);
11553 json_object_object_add(json
, "bgpStatusCodes",
11555 json_object_object_add(json
, "bgpOriginCodes",
11557 json_object_string_add(
11558 json
, "bgpOriginatingDefaultNetwork",
11559 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11561 vty_out(vty
, "BGP table version is %" PRIu64
11562 ", local router ID is %s, vrf id ",
11563 table
->version
, inet_ntoa(bgp
->router_id
));
11564 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11565 vty_out(vty
, "%s", VRFID_NONE_STR
);
11567 vty_out(vty
, "%u", bgp
->vrf_id
);
11568 vty_out(vty
, "\n");
11569 vty_out(vty
, "Default local pref %u, ",
11570 bgp
->default_local_pref
);
11571 vty_out(vty
, "local AS %u\n", bgp
->as
);
11572 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11573 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11574 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11576 vty_out(vty
, "Originating default network %s\n\n",
11577 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11582 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11583 if (type
== bgp_show_adj_route_received
11584 || type
== bgp_show_adj_route_filtered
) {
11585 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11586 if (ain
->peer
!= peer
)
11591 json_object_int_add(
11592 json
, "bgpTableVersion",
11594 json_object_string_add(
11596 "bgpLocalRouterId",
11599 json_object_int_add(json
,
11601 bgp
->default_local_pref
);
11602 json_object_int_add(json
,
11603 "localAS", bgp
->as
);
11604 json_object_object_add(
11605 json
, "bgpStatusCodes",
11607 json_object_object_add(
11608 json
, "bgpOriginCodes",
11612 "BGP table version is 0, local router ID is %s, vrf id ",
11615 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11621 vty_out(vty
, "\n");
11623 "Default local pref %u, ",
11624 bgp
->default_local_pref
);
11625 vty_out(vty
, "local AS %u\n",
11628 BGP_SHOW_SCODE_HEADER
);
11630 BGP_SHOW_NCODE_HEADER
);
11632 BGP_SHOW_OCODE_HEADER
);
11638 vty_out(vty
, BGP_SHOW_HEADER
);
11643 route_filtered
= false;
11645 /* Filter prefix using distribute list,
11646 * filter list or prefix list
11648 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11649 safi
)) == FILTER_DENY
)
11650 route_filtered
= true;
11652 /* Filter prefix using route-map */
11653 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11654 afi
, safi
, rmap_name
, NULL
, 0,
11657 if (type
== bgp_show_adj_route_filtered
&&
11658 !route_filtered
&& ret
!= RMAP_DENY
) {
11659 bgp_attr_undup(&attr
, ain
->attr
);
11663 if (type
== bgp_show_adj_route_received
&&
11664 (route_filtered
|| ret
== RMAP_DENY
))
11667 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11668 use_json
, json_ar
);
11669 bgp_attr_undup(&attr
, ain
->attr
);
11672 } else if (type
== bgp_show_adj_route_advertised
) {
11673 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11674 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11675 if (paf
->peer
!= peer
|| !adj
->attr
)
11680 json_object_int_add(
11684 json_object_string_add(
11686 "bgpLocalRouterId",
11689 json_object_int_add(
11690 json
, "defaultLocPrf",
11691 bgp
->default_local_pref
11693 json_object_int_add(
11696 json_object_object_add(
11700 json_object_object_add(
11706 "BGP table version is %" PRIu64
11707 ", local router ID is %s, vrf id ",
11720 vty_out(vty
, "\n");
11722 "Default local pref %u, ",
11723 bgp
->default_local_pref
11729 BGP_SHOW_SCODE_HEADER
);
11731 BGP_SHOW_NCODE_HEADER
);
11733 BGP_SHOW_OCODE_HEADER
);
11745 ret
= bgp_output_modifier(
11746 peer
, &rn
->p
, &attr
, afi
, safi
,
11749 if (ret
!= RMAP_DENY
) {
11750 route_vty_out_tmp(vty
, &rn
->p
,
11759 bgp_attr_undup(&attr
, adj
->attr
);
11765 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11766 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11767 json_object_int_add(json
, "filteredPrefixCounter",
11770 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11771 json
, JSON_C_TO_STRING_PRETTY
));
11772 json_object_free(json
);
11773 } else if (output_count
> 0) {
11774 if (filtered_count
> 0)
11776 "\nTotal number of prefixes %ld (%ld filtered)\n",
11777 output_count
, filtered_count
);
11779 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11784 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11785 safi_t safi
, enum bgp_show_adj_route_type type
,
11786 const char *rmap_name
, bool use_json
)
11788 json_object
*json
= NULL
;
11791 json
= json_object_new_object();
11793 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11795 json_object_string_add(
11797 "No such neighbor or address family");
11798 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11799 json_object_free(json
);
11801 vty_out(vty
, "%% No such neighbor or address family\n");
11803 return CMD_WARNING
;
11806 if ((type
== bgp_show_adj_route_received
11807 || type
== bgp_show_adj_route_filtered
)
11808 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11809 PEER_FLAG_SOFT_RECONFIG
)) {
11811 json_object_string_add(
11813 "Inbound soft reconfiguration not enabled");
11814 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11815 json_object_free(json
);
11818 "%% Inbound soft reconfiguration not enabled\n");
11820 return CMD_WARNING
;
11823 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11825 return CMD_SUCCESS
;
11828 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11829 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11830 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11831 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11835 BGP_INSTANCE_HELP_STR
11837 BGP_SAFI_WITH_LABEL_HELP_STR
11838 "Detailed information on TCP and BGP neighbor connections\n"
11839 "Neighbor to display information about\n"
11840 "Neighbor to display information about\n"
11841 "Neighbor on BGP configured interface\n"
11842 "Display the routes advertised to a BGP neighbor\n"
11843 "Display the received routes from neighbor\n"
11844 "Display the filtered routes received from neighbor\n"
11845 "Route-map to modify the attributes\n"
11846 "Name of the route map\n"
11849 afi_t afi
= AFI_IP6
;
11850 safi_t safi
= SAFI_UNICAST
;
11851 char *rmap_name
= NULL
;
11852 char *peerstr
= NULL
;
11853 struct bgp
*bgp
= NULL
;
11855 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11857 bool uj
= use_json(argc
, argv
);
11862 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11865 return CMD_WARNING
;
11867 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11868 argv_find(argv
, argc
, "neighbors", &idx
);
11869 peerstr
= argv
[++idx
]->arg
;
11871 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11873 return CMD_WARNING
;
11875 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11876 type
= bgp_show_adj_route_advertised
;
11877 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11878 type
= bgp_show_adj_route_received
;
11879 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11880 type
= bgp_show_adj_route_filtered
;
11882 if (argv_find(argv
, argc
, "route-map", &idx
))
11883 rmap_name
= argv
[++idx
]->arg
;
11885 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11888 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11889 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11890 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11896 "Address Family modifier\n"
11897 "Detailed information on TCP and BGP neighbor connections\n"
11898 "Neighbor to display information about\n"
11899 "Neighbor to display information about\n"
11900 "Neighbor on BGP configured interface\n"
11901 "Display information received from a BGP neighbor\n"
11902 "Display the prefixlist filter\n"
11905 afi_t afi
= AFI_IP6
;
11906 safi_t safi
= SAFI_UNICAST
;
11907 char *peerstr
= NULL
;
11910 union sockunion su
;
11916 /* show [ip] bgp */
11917 if (argv_find(argv
, argc
, "ip", &idx
))
11919 /* [<ipv4|ipv6> [unicast]] */
11920 if (argv_find(argv
, argc
, "ipv4", &idx
))
11922 if (argv_find(argv
, argc
, "ipv6", &idx
))
11924 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11925 argv_find(argv
, argc
, "neighbors", &idx
);
11926 peerstr
= argv
[++idx
]->arg
;
11928 bool uj
= use_json(argc
, argv
);
11930 ret
= str2sockunion(peerstr
, &su
);
11932 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11935 vty_out(vty
, "{}\n");
11938 "%% Malformed address or name: %s\n",
11940 return CMD_WARNING
;
11943 peer
= peer_lookup(NULL
, &su
);
11946 vty_out(vty
, "{}\n");
11948 vty_out(vty
, "No peer\n");
11949 return CMD_WARNING
;
11953 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11954 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11957 vty_out(vty
, "Address Family: %s\n",
11958 get_afi_safi_str(afi
, safi
, false));
11959 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11962 vty_out(vty
, "{}\n");
11964 vty_out(vty
, "No functional output\n");
11967 return CMD_SUCCESS
;
11970 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11971 afi_t afi
, safi_t safi
,
11972 enum bgp_show_type type
, bool use_json
)
11974 /* labeled-unicast routes live in the unicast table */
11975 if (safi
== SAFI_LABELED_UNICAST
)
11976 safi
= SAFI_UNICAST
;
11978 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11980 json_object
*json_no
= NULL
;
11981 json_no
= json_object_new_object();
11982 json_object_string_add(
11983 json_no
, "warning",
11984 "No such neighbor or address family");
11985 vty_out(vty
, "%s\n",
11986 json_object_to_json_string(json_no
));
11987 json_object_free(json_no
);
11989 vty_out(vty
, "%% No such neighbor or address family\n");
11990 return CMD_WARNING
;
11993 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11996 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11997 show_ip_bgp_flowspec_routes_detailed_cmd
,
11998 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
12002 BGP_INSTANCE_HELP_STR
12005 "Detailed information on flowspec entries\n"
12008 afi_t afi
= AFI_IP
;
12009 safi_t safi
= SAFI_UNICAST
;
12010 struct bgp
*bgp
= NULL
;
12012 bool uj
= use_json(argc
, argv
);
12017 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12020 return CMD_WARNING
;
12022 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
12025 DEFUN (show_ip_bgp_neighbor_routes
,
12026 show_ip_bgp_neighbor_routes_cmd
,
12027 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
12028 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
12032 BGP_INSTANCE_HELP_STR
12034 BGP_SAFI_WITH_LABEL_HELP_STR
12035 "Detailed information on TCP and BGP neighbor connections\n"
12036 "Neighbor to display information about\n"
12037 "Neighbor to display information about\n"
12038 "Neighbor on BGP configured interface\n"
12039 "Display flap statistics of the routes learned from neighbor\n"
12040 "Display the dampened routes received from neighbor\n"
12041 "Display routes learned from neighbor\n"
12044 char *peerstr
= NULL
;
12045 struct bgp
*bgp
= NULL
;
12046 afi_t afi
= AFI_IP6
;
12047 safi_t safi
= SAFI_UNICAST
;
12049 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
12051 bool uj
= use_json(argc
, argv
);
12056 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
12059 return CMD_WARNING
;
12061 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12062 argv_find(argv
, argc
, "neighbors", &idx
);
12063 peerstr
= argv
[++idx
]->arg
;
12065 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
12067 return CMD_WARNING
;
12069 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
12070 sh_type
= bgp_show_type_flap_neighbor
;
12071 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
12072 sh_type
= bgp_show_type_damp_neighbor
;
12073 else if (argv_find(argv
, argc
, "routes", &idx
))
12074 sh_type
= bgp_show_type_neighbor
;
12076 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
12079 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
12081 struct bgp_distance
{
12082 /* Distance value for the IP source prefix. */
12085 /* Name of the access-list to be matched. */
12089 DEFUN (show_bgp_afi_vpn_rd_route
,
12090 show_bgp_afi_vpn_rd_route_cmd
,
12091 "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]",
12095 "Address Family modifier\n"
12096 "Display information for a route distinguisher\n"
12097 "Route Distinguisher\n"
12098 "Network in the BGP routing table to display\n"
12099 "Network in the BGP routing table to display\n"
12103 struct prefix_rd prd
;
12104 afi_t afi
= AFI_MAX
;
12107 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
12108 vty_out(vty
, "%% Malformed Address Family\n");
12109 return CMD_WARNING
;
12112 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
12114 vty_out(vty
, "%% Malformed Route Distinguisher\n");
12115 return CMD_WARNING
;
12118 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
12119 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
12122 static struct bgp_distance
*bgp_distance_new(void)
12124 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
12127 static void bgp_distance_free(struct bgp_distance
*bdistance
)
12129 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
12132 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
12133 const char *ip_str
, const char *access_list_str
)
12140 struct bgp_node
*rn
;
12141 struct bgp_distance
*bdistance
;
12143 afi
= bgp_node_afi(vty
);
12144 safi
= bgp_node_safi(vty
);
12146 ret
= str2prefix(ip_str
, &p
);
12148 vty_out(vty
, "Malformed prefix\n");
12149 return CMD_WARNING_CONFIG_FAILED
;
12152 distance
= atoi(distance_str
);
12154 /* Get BGP distance node. */
12155 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
12156 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12158 bgp_unlock_node(rn
);
12160 bdistance
= bgp_distance_new();
12161 bgp_node_set_bgp_distance_info(rn
, bdistance
);
12164 /* Set distance value. */
12165 bdistance
->distance
= distance
;
12167 /* Reset access-list configuration. */
12168 if (bdistance
->access_list
) {
12169 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12170 bdistance
->access_list
= NULL
;
12172 if (access_list_str
)
12173 bdistance
->access_list
=
12174 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
12176 return CMD_SUCCESS
;
12179 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
12180 const char *ip_str
, const char *access_list_str
)
12187 struct bgp_node
*rn
;
12188 struct bgp_distance
*bdistance
;
12190 afi
= bgp_node_afi(vty
);
12191 safi
= bgp_node_safi(vty
);
12193 ret
= str2prefix(ip_str
, &p
);
12195 vty_out(vty
, "Malformed prefix\n");
12196 return CMD_WARNING_CONFIG_FAILED
;
12199 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
12200 (struct prefix
*)&p
);
12202 vty_out(vty
, "Can't find specified prefix\n");
12203 return CMD_WARNING_CONFIG_FAILED
;
12206 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12207 distance
= atoi(distance_str
);
12209 if (bdistance
->distance
!= distance
) {
12210 vty_out(vty
, "Distance does not match configured\n");
12211 return CMD_WARNING_CONFIG_FAILED
;
12214 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
12215 bgp_distance_free(bdistance
);
12217 bgp_node_set_bgp_path_info(rn
, NULL
);
12218 bgp_unlock_node(rn
);
12219 bgp_unlock_node(rn
);
12221 return CMD_SUCCESS
;
12224 /* Apply BGP information to distance method. */
12225 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
12226 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
12228 struct bgp_node
*rn
;
12231 struct bgp_distance
*bdistance
;
12232 struct access_list
*alist
;
12233 struct bgp_static
*bgp_static
;
12238 peer
= pinfo
->peer
;
12240 if (pinfo
->attr
->distance
)
12241 return pinfo
->attr
->distance
;
12243 /* Check source address. */
12244 sockunion2hostprefix(&peer
->su
, &q
);
12245 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
12247 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12248 bgp_unlock_node(rn
);
12250 if (bdistance
->access_list
) {
12251 alist
= access_list_lookup(afi
, bdistance
->access_list
);
12253 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
12254 return bdistance
->distance
;
12256 return bdistance
->distance
;
12259 /* Backdoor check. */
12260 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
12262 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12263 bgp_unlock_node(rn
);
12265 if (bgp_static
->backdoor
) {
12266 if (bgp
->distance_local
[afi
][safi
])
12267 return bgp
->distance_local
[afi
][safi
];
12269 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12273 if (peer
->sort
== BGP_PEER_EBGP
) {
12274 if (bgp
->distance_ebgp
[afi
][safi
])
12275 return bgp
->distance_ebgp
[afi
][safi
];
12276 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
12278 if (bgp
->distance_ibgp
[afi
][safi
])
12279 return bgp
->distance_ibgp
[afi
][safi
];
12280 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
12284 /* If we enter `distance bgp (1-255) (1-255) (1-255)`,
12285 * we should tell ZEBRA update the routes for a specific
12286 * AFI/SAFI to reflect changes in RIB.
12288 static void bgp_announce_routes_distance_update(struct bgp
*bgp
,
12290 safi_t update_safi
)
12295 FOREACH_AFI_SAFI (afi
, safi
) {
12296 if (!bgp_fibupd_safi(safi
))
12299 if (afi
!= update_afi
&& safi
!= update_safi
)
12302 if (BGP_DEBUG(zebra
, ZEBRA
))
12304 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
12305 __func__
, afi
, safi
);
12306 bgp_zebra_announce_table(bgp
, afi
, safi
);
12310 DEFUN (bgp_distance
,
12312 "distance bgp (1-255) (1-255) (1-255)",
12313 "Define an administrative distance\n"
12315 "Distance for routes external to the AS\n"
12316 "Distance for routes internal to the AS\n"
12317 "Distance for local routes\n")
12319 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12320 int idx_number
= 2;
12321 int idx_number_2
= 3;
12322 int idx_number_3
= 4;
12323 int distance_ebgp
= atoi(argv
[idx_number
]->arg
);
12324 int distance_ibgp
= atoi(argv
[idx_number_2
]->arg
);
12325 int distance_local
= atoi(argv
[idx_number_3
]->arg
);
12329 afi
= bgp_node_afi(vty
);
12330 safi
= bgp_node_safi(vty
);
12332 if (bgp
->distance_ebgp
[afi
][safi
] != distance_ebgp
12333 || bgp
->distance_ibgp
[afi
][safi
] != distance_ibgp
12334 || bgp
->distance_local
[afi
][safi
] != distance_local
) {
12335 bgp
->distance_ebgp
[afi
][safi
] = distance_ebgp
;
12336 bgp
->distance_ibgp
[afi
][safi
] = distance_ibgp
;
12337 bgp
->distance_local
[afi
][safi
] = distance_local
;
12338 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12340 return CMD_SUCCESS
;
12343 DEFUN (no_bgp_distance
,
12344 no_bgp_distance_cmd
,
12345 "no distance bgp [(1-255) (1-255) (1-255)]",
12347 "Define an administrative distance\n"
12349 "Distance for routes external to the AS\n"
12350 "Distance for routes internal to the AS\n"
12351 "Distance for local routes\n")
12353 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12357 afi
= bgp_node_afi(vty
);
12358 safi
= bgp_node_safi(vty
);
12360 if (bgp
->distance_ebgp
[afi
][safi
] != 0
12361 || bgp
->distance_ibgp
[afi
][safi
] != 0
12362 || bgp
->distance_local
[afi
][safi
] != 0) {
12363 bgp
->distance_ebgp
[afi
][safi
] = 0;
12364 bgp
->distance_ibgp
[afi
][safi
] = 0;
12365 bgp
->distance_local
[afi
][safi
] = 0;
12366 bgp_announce_routes_distance_update(bgp
, afi
, safi
);
12368 return CMD_SUCCESS
;
12372 DEFUN (bgp_distance_source
,
12373 bgp_distance_source_cmd
,
12374 "distance (1-255) A.B.C.D/M",
12375 "Define an administrative distance\n"
12376 "Administrative distance\n"
12377 "IP source prefix\n")
12379 int idx_number
= 1;
12380 int idx_ipv4_prefixlen
= 2;
12381 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12382 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12383 return CMD_SUCCESS
;
12386 DEFUN (no_bgp_distance_source
,
12387 no_bgp_distance_source_cmd
,
12388 "no distance (1-255) A.B.C.D/M",
12390 "Define an administrative distance\n"
12391 "Administrative distance\n"
12392 "IP source prefix\n")
12394 int idx_number
= 2;
12395 int idx_ipv4_prefixlen
= 3;
12396 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12397 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12398 return CMD_SUCCESS
;
12401 DEFUN (bgp_distance_source_access_list
,
12402 bgp_distance_source_access_list_cmd
,
12403 "distance (1-255) A.B.C.D/M WORD",
12404 "Define an administrative distance\n"
12405 "Administrative distance\n"
12406 "IP source prefix\n"
12407 "Access list name\n")
12409 int idx_number
= 1;
12410 int idx_ipv4_prefixlen
= 2;
12412 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12413 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12414 return CMD_SUCCESS
;
12417 DEFUN (no_bgp_distance_source_access_list
,
12418 no_bgp_distance_source_access_list_cmd
,
12419 "no distance (1-255) A.B.C.D/M WORD",
12421 "Define an administrative distance\n"
12422 "Administrative distance\n"
12423 "IP source prefix\n"
12424 "Access list name\n")
12426 int idx_number
= 2;
12427 int idx_ipv4_prefixlen
= 3;
12429 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12430 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12431 return CMD_SUCCESS
;
12434 DEFUN (ipv6_bgp_distance_source
,
12435 ipv6_bgp_distance_source_cmd
,
12436 "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_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12442 return CMD_SUCCESS
;
12445 DEFUN (no_ipv6_bgp_distance_source
,
12446 no_ipv6_bgp_distance_source_cmd
,
12447 "no distance (1-255) X:X::X:X/M",
12449 "Define an administrative distance\n"
12450 "Administrative distance\n"
12451 "IP source prefix\n")
12453 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12454 return CMD_SUCCESS
;
12457 DEFUN (ipv6_bgp_distance_source_access_list
,
12458 ipv6_bgp_distance_source_access_list_cmd
,
12459 "distance (1-255) X:X::X:X/M WORD",
12460 "Define an administrative distance\n"
12461 "Administrative distance\n"
12462 "IP source prefix\n"
12463 "Access list name\n")
12465 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12466 return CMD_SUCCESS
;
12469 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12470 no_ipv6_bgp_distance_source_access_list_cmd
,
12471 "no distance (1-255) X:X::X:X/M WORD",
12473 "Define an administrative distance\n"
12474 "Administrative distance\n"
12475 "IP source prefix\n"
12476 "Access list name\n")
12478 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12479 return CMD_SUCCESS
;
12482 DEFUN (bgp_damp_set
,
12484 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12485 "BGP Specific commands\n"
12486 "Enable route-flap dampening\n"
12487 "Half-life time for the penalty\n"
12488 "Value to start reusing a route\n"
12489 "Value to start suppressing a route\n"
12490 "Maximum duration to suppress a stable route\n")
12492 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12493 int idx_half_life
= 2;
12495 int idx_suppress
= 4;
12496 int idx_max_suppress
= 5;
12497 int half
= DEFAULT_HALF_LIFE
* 60;
12498 int reuse
= DEFAULT_REUSE
;
12499 int suppress
= DEFAULT_SUPPRESS
;
12500 int max
= 4 * half
;
12503 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12504 reuse
= atoi(argv
[idx_reuse
]->arg
);
12505 suppress
= atoi(argv
[idx_suppress
]->arg
);
12506 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12507 } else if (argc
== 3) {
12508 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12513 * These can't be 0 but our SA doesn't understand the
12514 * way our cli is constructed
12518 if (suppress
< reuse
) {
12520 "Suppress value cannot be less than reuse value \n");
12524 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12525 reuse
, suppress
, max
);
12528 DEFUN (bgp_damp_unset
,
12529 bgp_damp_unset_cmd
,
12530 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12532 "BGP Specific commands\n"
12533 "Enable route-flap dampening\n"
12534 "Half-life time for the penalty\n"
12535 "Value to start reusing a route\n"
12536 "Value to start suppressing a route\n"
12537 "Maximum duration to suppress a stable route\n")
12539 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12540 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12543 /* Display specified route of BGP table. */
12544 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12545 const char *ip_str
, afi_t afi
, safi_t safi
,
12546 struct prefix_rd
*prd
, int prefix_check
)
12549 struct prefix match
;
12550 struct bgp_node
*rn
;
12551 struct bgp_node
*rm
;
12552 struct bgp_path_info
*pi
;
12553 struct bgp_path_info
*pi_temp
;
12555 struct bgp_table
*table
;
12557 /* BGP structure lookup. */
12559 bgp
= bgp_lookup_by_name(view_name
);
12561 vty_out(vty
, "%% Can't find BGP instance %s\n",
12563 return CMD_WARNING
;
12566 bgp
= bgp_get_default();
12568 vty_out(vty
, "%% No BGP process is configured\n");
12569 return CMD_WARNING
;
12573 /* Check IP address argument. */
12574 ret
= str2prefix(ip_str
, &match
);
12576 vty_out(vty
, "%% address is malformed\n");
12577 return CMD_WARNING
;
12580 match
.family
= afi2family(afi
);
12582 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12583 || (safi
== SAFI_EVPN
)) {
12584 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12585 rn
= bgp_route_next(rn
)) {
12586 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12588 table
= bgp_node_get_bgp_table_info(rn
);
12591 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12595 || rm
->p
.prefixlen
== match
.prefixlen
) {
12596 pi
= bgp_node_get_bgp_path_info(rm
);
12598 if (pi
->extra
&& pi
->extra
->damp_info
) {
12599 pi_temp
= pi
->next
;
12600 bgp_damp_info_free(
12601 pi
->extra
->damp_info
,
12609 bgp_unlock_node(rm
);
12612 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12615 || rn
->p
.prefixlen
== match
.prefixlen
) {
12616 pi
= bgp_node_get_bgp_path_info(rn
);
12618 if (pi
->extra
&& pi
->extra
->damp_info
) {
12619 pi_temp
= pi
->next
;
12620 bgp_damp_info_free(
12621 pi
->extra
->damp_info
,
12629 bgp_unlock_node(rn
);
12633 return CMD_SUCCESS
;
12636 DEFUN (clear_ip_bgp_dampening
,
12637 clear_ip_bgp_dampening_cmd
,
12638 "clear ip bgp dampening",
12642 "Clear route flap dampening information\n")
12644 bgp_damp_info_clean(AFI_IP
, SAFI_UNICAST
);
12645 return CMD_SUCCESS
;
12648 DEFUN (clear_ip_bgp_dampening_prefix
,
12649 clear_ip_bgp_dampening_prefix_cmd
,
12650 "clear ip bgp dampening A.B.C.D/M",
12654 "Clear route flap dampening information\n"
12657 int idx_ipv4_prefixlen
= 4;
12658 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12659 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12662 DEFUN (clear_ip_bgp_dampening_address
,
12663 clear_ip_bgp_dampening_address_cmd
,
12664 "clear ip bgp dampening A.B.C.D",
12668 "Clear route flap dampening information\n"
12669 "Network to clear damping information\n")
12672 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12673 SAFI_UNICAST
, NULL
, 0);
12676 DEFUN (clear_ip_bgp_dampening_address_mask
,
12677 clear_ip_bgp_dampening_address_mask_cmd
,
12678 "clear ip bgp dampening A.B.C.D A.B.C.D",
12682 "Clear route flap dampening information\n"
12683 "Network to clear damping information\n"
12687 int idx_ipv4_2
= 5;
12689 char prefix_str
[BUFSIZ
];
12691 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12694 vty_out(vty
, "%% Inconsistent address and mask\n");
12695 return CMD_WARNING
;
12698 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12702 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12704 struct vty
*vty
= arg
;
12705 struct peer
*peer
= bucket
->data
;
12706 char buf
[SU_ADDRSTRLEN
];
12708 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12709 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12712 DEFUN (show_bgp_peerhash
,
12713 show_bgp_peerhash_cmd
,
12714 "show bgp peerhash",
12717 "Display information about the BGP peerhash\n")
12719 struct list
*instances
= bm
->bgp
;
12720 struct listnode
*node
;
12723 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12724 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12725 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12729 return CMD_SUCCESS
;
12732 /* also used for encap safi */
12733 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12734 afi_t afi
, safi_t safi
)
12736 struct bgp_node
*prn
;
12737 struct bgp_node
*rn
;
12738 struct bgp_table
*table
;
12740 struct prefix_rd
*prd
;
12741 struct bgp_static
*bgp_static
;
12742 mpls_label_t label
;
12743 char buf
[SU_ADDRSTRLEN
];
12744 char rdbuf
[RD_ADDRSTRLEN
];
12746 /* Network configuration. */
12747 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12748 prn
= bgp_route_next(prn
)) {
12749 table
= bgp_node_get_bgp_table_info(prn
);
12753 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12754 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12755 if (bgp_static
== NULL
)
12759 prd
= (struct prefix_rd
*)&prn
->p
;
12761 /* "network" configuration display. */
12762 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12763 label
= decode_label(&bgp_static
->label
);
12765 vty_out(vty
, " network %s/%d rd %s",
12766 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12768 p
->prefixlen
, rdbuf
);
12769 if (safi
== SAFI_MPLS_VPN
)
12770 vty_out(vty
, " label %u", label
);
12772 if (bgp_static
->rmap
.name
)
12773 vty_out(vty
, " route-map %s",
12774 bgp_static
->rmap
.name
);
12776 if (bgp_static
->backdoor
)
12777 vty_out(vty
, " backdoor");
12779 vty_out(vty
, "\n");
12784 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12785 afi_t afi
, safi_t safi
)
12787 struct bgp_node
*prn
;
12788 struct bgp_node
*rn
;
12789 struct bgp_table
*table
;
12791 struct prefix_rd
*prd
;
12792 struct bgp_static
*bgp_static
;
12793 char buf
[PREFIX_STRLEN
* 2];
12794 char buf2
[SU_ADDRSTRLEN
];
12795 char rdbuf
[RD_ADDRSTRLEN
];
12797 /* Network configuration. */
12798 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12799 prn
= bgp_route_next(prn
)) {
12800 table
= bgp_node_get_bgp_table_info(prn
);
12804 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12805 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12806 if (bgp_static
== NULL
)
12809 char *macrouter
= NULL
;
12812 if (bgp_static
->router_mac
)
12813 macrouter
= prefix_mac2str(
12814 bgp_static
->router_mac
, NULL
, 0);
12815 if (bgp_static
->eth_s_id
)
12816 esi
= esi2str(bgp_static
->eth_s_id
);
12818 prd
= (struct prefix_rd
*)&prn
->p
;
12820 /* "network" configuration display. */
12821 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12822 if (p
->u
.prefix_evpn
.route_type
== 5) {
12823 char local_buf
[PREFIX_STRLEN
];
12824 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12825 struct prefix_evpn
*)p
)
12829 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12830 local_buf
, PREFIX_STRLEN
);
12831 sprintf(buf
, "%s/%u", local_buf
,
12832 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12834 prefix2str(p
, buf
, sizeof(buf
));
12837 if (bgp_static
->gatewayIp
.family
== AF_INET
12838 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12839 inet_ntop(bgp_static
->gatewayIp
.family
,
12840 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12843 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12845 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12846 decode_label(&bgp_static
->label
), esi
, buf2
,
12849 XFREE(MTYPE_TMP
, macrouter
);
12850 XFREE(MTYPE_TMP
, esi
);
12855 /* Configuration of static route announcement and aggregate
12857 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12860 struct bgp_node
*rn
;
12862 struct bgp_static
*bgp_static
;
12863 struct bgp_aggregate
*bgp_aggregate
;
12864 char buf
[SU_ADDRSTRLEN
];
12866 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12867 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12871 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12872 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12876 /* Network configuration. */
12877 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12878 rn
= bgp_route_next(rn
)) {
12879 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12880 if (bgp_static
== NULL
)
12885 vty_out(vty
, " network %s/%d",
12886 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12889 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12890 vty_out(vty
, " label-index %u",
12891 bgp_static
->label_index
);
12893 if (bgp_static
->rmap
.name
)
12894 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12896 if (bgp_static
->backdoor
)
12897 vty_out(vty
, " backdoor");
12899 vty_out(vty
, "\n");
12902 /* Aggregate-address configuration. */
12903 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12904 rn
= bgp_route_next(rn
)) {
12905 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12906 if (bgp_aggregate
== NULL
)
12911 vty_out(vty
, " aggregate-address %s/%d",
12912 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12915 if (bgp_aggregate
->as_set
)
12916 vty_out(vty
, " as-set");
12918 if (bgp_aggregate
->summary_only
)
12919 vty_out(vty
, " summary-only");
12921 if (bgp_aggregate
->rmap
.name
)
12922 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12924 vty_out(vty
, "\n");
12928 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12931 struct bgp_node
*rn
;
12932 struct bgp_distance
*bdistance
;
12934 /* Distance configuration. */
12935 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12936 && bgp
->distance_local
[afi
][safi
]
12937 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12938 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12939 || bgp
->distance_local
[afi
][safi
]
12940 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12941 vty_out(vty
, " distance bgp %d %d %d\n",
12942 bgp
->distance_ebgp
[afi
][safi
],
12943 bgp
->distance_ibgp
[afi
][safi
],
12944 bgp
->distance_local
[afi
][safi
]);
12947 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12948 rn
= bgp_route_next(rn
)) {
12949 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12950 if (bdistance
!= NULL
) {
12951 char buf
[PREFIX_STRLEN
];
12953 vty_out(vty
, " distance %d %s %s\n",
12954 bdistance
->distance
,
12955 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12956 bdistance
->access_list
? bdistance
->access_list
12962 /* Allocate routing table structure and install commands. */
12963 void bgp_route_init(void)
12968 /* Init BGP distance table. */
12969 FOREACH_AFI_SAFI (afi
, safi
)
12970 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12972 /* IPv4 BGP commands. */
12973 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12974 install_element(BGP_NODE
, &bgp_network_cmd
);
12975 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12977 install_element(BGP_NODE
, &aggregate_address_cmd
);
12978 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12979 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12980 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12982 /* IPv4 unicast configuration. */
12983 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12984 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12985 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12987 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12988 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12989 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12990 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12992 /* IPv4 multicast configuration. */
12993 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12994 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12995 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12996 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12997 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12998 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12999 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
13001 /* IPv4 labeled-unicast configuration. */
13002 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
13003 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
13004 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
13005 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
13006 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
13008 install_element(VIEW_NODE
,
13009 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
13010 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
13011 install_element(VIEW_NODE
,
13012 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
13013 #ifdef KEEP_OLD_VPN_COMMANDS
13014 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
13015 #endif /* KEEP_OLD_VPN_COMMANDS */
13016 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
13017 install_element(VIEW_NODE
,
13018 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
13020 /* BGP dampening clear commands */
13021 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
13022 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
13024 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
13025 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
13028 install_element(ENABLE_NODE
,
13029 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
13030 #ifdef KEEP_OLD_VPN_COMMANDS
13031 install_element(ENABLE_NODE
,
13032 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
13033 #endif /* KEEP_OLD_VPN_COMMANDS */
13035 /* New config IPv6 BGP commands. */
13036 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
13037 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
13038 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
13040 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
13041 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
13043 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
13045 install_element(BGP_NODE
, &bgp_distance_cmd
);
13046 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
13047 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
13048 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
13049 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
13050 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
13051 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
13052 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
13053 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
13054 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
13055 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
13056 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
13057 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
13058 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
13059 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
13060 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
13061 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
13062 install_element(BGP_IPV4M_NODE
,
13063 &no_bgp_distance_source_access_list_cmd
);
13064 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
13065 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
13066 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
13067 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13068 install_element(BGP_IPV6_NODE
,
13069 &ipv6_bgp_distance_source_access_list_cmd
);
13070 install_element(BGP_IPV6_NODE
,
13071 &no_ipv6_bgp_distance_source_access_list_cmd
);
13072 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
13073 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
13074 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
13075 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
13076 install_element(BGP_IPV6M_NODE
,
13077 &ipv6_bgp_distance_source_access_list_cmd
);
13078 install_element(BGP_IPV6M_NODE
,
13079 &no_ipv6_bgp_distance_source_access_list_cmd
);
13081 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
13082 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
13083 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
13084 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
13086 /* IPv4 Multicast Mode */
13087 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
13088 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
13090 /* Large Communities */
13091 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
13092 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
13094 /* show bgp ipv4 flowspec detailed */
13095 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
13097 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
13100 void bgp_route_finish(void)
13105 FOREACH_AFI_SAFI (afi
, safi
) {
13106 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
13107 bgp_distance_table
[afi
][safi
] = NULL
;