1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
5 * This file is part of GxNU Zebra.
8 #ifndef _QUAGGA_BGP_MPLSVPN_H
9 #define _QUAGGA_BGP_MPLSVPN_H
11 #include "bgpd/bgp_attr.h"
12 #include "bgpd/bgp_route.h"
13 #include "bgpd/bgp_rd.h"
14 #include "bgpd/bgp_zebra.h"
15 #include "bgpd/bgp_vty.h"
17 #define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
18 #define MPLS_LABEL_IS_NULL(label) \
19 ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
20 || (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
21 || (label) == MPLS_LABEL_IMPLICIT_NULL)
23 #define BGP_VPNVX_HELP_STR BGP_AF_STR BGP_AF_STR
26 " Network Next Hop Metric LocPrf Weight Path\n"
27 #define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
28 #define V4_HEADER_OVERLAY \
29 " Network Next Hop EthTag Overlay Index RouterMac\n"
31 #define BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH 20
33 extern void bgp_mplsvpn_init(void);
34 extern int bgp_nlri_parse_vpn(struct peer
*, struct attr
*, struct bgp_nlri
*);
35 extern uint32_t decode_label(mpls_label_t
*);
36 extern void encode_label(mpls_label_t
, mpls_label_t
*);
38 extern int argv_find_and_parse_vpnvx(struct cmd_token
**argv
, int argc
,
39 int *index
, afi_t
*afi
);
40 extern int bgp_show_mpls_vpn(struct vty
*vty
, afi_t afi
, struct prefix_rd
*prd
,
41 enum bgp_show_type type
, void *output_arg
,
42 int tags
, bool use_json
);
44 extern void vpn_leak_from_vrf_update(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
45 struct bgp_path_info
*path_vrf
);
47 extern void vpn_leak_from_vrf_withdraw(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
48 struct bgp_path_info
*path_vrf
);
50 extern void vpn_leak_from_vrf_withdraw_all(struct bgp
*to_bgp
,
51 struct bgp
*from_bgp
, afi_t afi
);
53 extern void vpn_leak_from_vrf_update_all(struct bgp
*to_bgp
,
54 struct bgp
*from_bgp
, afi_t afi
);
56 extern void vpn_leak_to_vrf_withdraw_all(struct bgp
*to_bgp
, afi_t afi
);
58 extern void vpn_leak_to_vrf_update_all(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
61 extern bool vpn_leak_to_vrf_update(struct bgp
*from_bgp
,
62 struct bgp_path_info
*path_vpn
,
63 struct prefix_rd
*prd
);
65 extern void vpn_leak_to_vrf_withdraw(struct bgp_path_info
*path_vpn
);
67 extern void vpn_leak_zebra_vrf_label_update(struct bgp
*bgp
, afi_t afi
);
68 extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp
*bgp
, afi_t afi
);
69 extern void vpn_leak_zebra_vrf_sid_update(struct bgp
*bgp
, afi_t afi
);
70 extern void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp
*bgp
, afi_t afi
);
71 extern void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp
*bgp
);
72 extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp
*bgp
, afi_t afi
);
73 extern void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp
*bgp
, afi_t afi
);
74 extern void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp
*bgp
);
75 extern int vpn_leak_label_callback(mpls_label_t label
, void *lblid
, bool alloc
);
76 extern void ensure_vrf_tovpn_sid(struct bgp
*vpn
, struct bgp
*vrf
, afi_t afi
);
77 extern void delete_vrf_tovpn_sid(struct bgp
*vpn
, struct bgp
*vrf
, afi_t afi
);
78 extern void delete_vrf_tovpn_sid_per_af(struct bgp
*vpn
, struct bgp
*vrf
,
80 extern void delete_vrf_tovpn_sid_per_vrf(struct bgp
*vpn
, struct bgp
*vrf
);
81 extern void ensure_vrf_tovpn_sid_per_af(struct bgp
*vpn
, struct bgp
*vrf
,
83 extern void ensure_vrf_tovpn_sid_per_vrf(struct bgp
*vpn
, struct bgp
*vrf
);
84 extern void transpose_sid(struct in6_addr
*sid
, uint32_t label
, uint8_t offset
,
86 extern void vrf_import_from_vrf(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
87 afi_t afi
, safi_t safi
);
88 void vrf_unimport_from_vrf(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
89 afi_t afi
, safi_t safi
);
91 static inline bool is_bgp_vrf_mplsvpn(struct bgp
*bgp
)
95 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
96 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
97 if (CHECK_FLAG(bgp
->af_flags
[afi
][SAFI_UNICAST
],
98 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT
)
99 || CHECK_FLAG(bgp
->af_flags
[afi
][SAFI_UNICAST
],
100 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT
))
106 static inline int vpn_leak_to_vpn_active(struct bgp
*bgp_vrf
, afi_t afi
,
109 if (bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_VRF
110 && bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
) {
113 *pmsg
= "source bgp instance neither vrf nor default";
117 /* Is vrf configured to export to vpn? */
118 if (!CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
119 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT
)
120 && !CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
121 BGP_CONFIG_VRF_TO_VRF_EXPORT
)) {
123 *pmsg
= "export not set";
127 /* Is there an RT list set? */
128 if (!bgp_vrf
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]) {
130 *pmsg
= "rtlist tovpn not defined";
134 /* Is there an RD set? */
135 if (!CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
136 BGP_VPN_POLICY_TOVPN_RD_SET
)) {
138 *pmsg
= "rd not defined";
142 /* Is a route-map specified, but not defined? */
143 if (bgp_vrf
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
] &&
144 !bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
]) {
146 *pmsg
= "route-map tovpn named but not defined";
150 /* Is there an "auto" export label that isn't allocated yet? */
151 if (CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
152 BGP_VPN_POLICY_TOVPN_LABEL_AUTO
) &&
153 (bgp_vrf
->vpn_policy
[afi
].tovpn_label
== MPLS_LABEL_NONE
)) {
156 *pmsg
= "auto label not allocated";
163 static inline int vpn_leak_from_vpn_active(struct bgp
*bgp_vrf
, afi_t afi
,
166 if (bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_VRF
167 && bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
) {
170 *pmsg
= "destination bgp instance neither vrf nor default";
174 if (bgp_vrf
->vrf_id
== VRF_UNKNOWN
) {
176 *pmsg
= "destination bgp instance vrf is VRF_UNKNOWN";
180 /* Is vrf configured to import from vpn? */
181 if (!CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
182 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT
)
183 && !CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
184 BGP_CONFIG_VRF_TO_VRF_IMPORT
)) {
186 *pmsg
= "import not set";
190 /* Is there an RT list set? */
191 if (!bgp_vrf
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
193 *pmsg
= "rtlist fromvpn not defined";
197 /* Is a route-map specified, but not defined? */
198 if (bgp_vrf
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_FROMVPN
] &&
199 !bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
201 *pmsg
= "route-map fromvpn named but not defined";
207 static inline void vpn_leak_prechange(enum vpn_policy_direction direction
,
208 afi_t afi
, struct bgp
*bgp_vpn
,
211 /* Detect when default bgp instance is not (yet) defined by config */
215 if ((direction
== BGP_VPN_POLICY_DIR_FROMVPN
) &&
216 vpn_leak_from_vpn_active(bgp_vrf
, afi
, NULL
)) {
218 vpn_leak_to_vrf_withdraw_all(bgp_vrf
, afi
);
220 if ((direction
== BGP_VPN_POLICY_DIR_TOVPN
) &&
221 vpn_leak_to_vpn_active(bgp_vrf
, afi
, NULL
)) {
223 vpn_leak_from_vrf_withdraw_all(bgp_vpn
, bgp_vrf
, afi
);
227 static inline void vpn_leak_postchange(enum vpn_policy_direction direction
,
228 afi_t afi
, struct bgp
*bgp_vpn
,
231 /* Detect when default bgp instance is not (yet) defined by config */
235 if (direction
== BGP_VPN_POLICY_DIR_FROMVPN
) {
236 /* trigger a flush to re-sync with ADJ-RIB-in */
237 if (!CHECK_FLAG(bgp_vpn
->af_flags
[afi
][SAFI_MPLS_VPN
],
238 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL
))
239 bgp_clear_soft_in(bgp_vpn
, afi
, SAFI_MPLS_VPN
);
241 vpn_leak_to_vrf_update_all(bgp_vrf
, bgp_vpn
, afi
);
243 if (direction
== BGP_VPN_POLICY_DIR_TOVPN
) {
245 if (bgp_vrf
->vpn_policy
[afi
].tovpn_label
!=
246 bgp_vrf
->vpn_policy
[afi
]
247 .tovpn_zebra_vrf_label_last_sent
) {
248 vpn_leak_zebra_vrf_label_update(bgp_vrf
, afi
);
251 if (bgp_vrf
->vpn_policy
[afi
].tovpn_sid_index
== 0 &&
252 !CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
253 BGP_VPN_POLICY_TOVPN_SID_AUTO
) &&
254 bgp_vrf
->tovpn_sid_index
== 0 &&
255 !CHECK_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_TOVPN_SID_AUTO
))
256 delete_vrf_tovpn_sid(bgp_vpn
, bgp_vrf
, afi
);
258 if (!bgp_vrf
->vpn_policy
[afi
].tovpn_sid
&& !bgp_vrf
->tovpn_sid
)
259 ensure_vrf_tovpn_sid(bgp_vpn
, bgp_vrf
, afi
);
261 if ((!bgp_vrf
->vpn_policy
[afi
].tovpn_sid
&&
262 bgp_vrf
->vpn_policy
[afi
].tovpn_zebra_vrf_sid_last_sent
) ||
263 (!bgp_vrf
->tovpn_sid
&&
264 bgp_vrf
->tovpn_zebra_vrf_sid_last_sent
))
265 vpn_leak_zebra_vrf_sid_withdraw(bgp_vrf
, afi
);
267 if (bgp_vrf
->vpn_policy
[afi
].tovpn_sid
) {
268 if (sid_diff(bgp_vrf
->vpn_policy
[afi
].tovpn_sid
,
269 bgp_vrf
->vpn_policy
[afi
]
270 .tovpn_zebra_vrf_sid_last_sent
)) {
271 vpn_leak_zebra_vrf_sid_update(bgp_vrf
, afi
);
273 } else if (bgp_vrf
->tovpn_sid
) {
274 if (sid_diff(bgp_vrf
->tovpn_sid
,
275 bgp_vrf
->tovpn_zebra_vrf_sid_last_sent
)) {
276 vpn_leak_zebra_vrf_sid_update(bgp_vrf
, afi
);
280 vpn_leak_from_vrf_update_all(bgp_vpn
, bgp_vrf
, afi
);
284 /* Flag if the route is injectable into VPN. This would be either a
285 * non-imported route or a non-VPN imported route.
287 static inline bool is_route_injectable_into_vpn(struct bgp_path_info
*pi
)
289 struct bgp_path_info
*parent_pi
;
290 struct bgp_table
*table
;
291 struct bgp_dest
*dest
;
293 if (pi
->sub_type
!= BGP_ROUTE_IMPORTED
||
298 parent_pi
= (struct bgp_path_info
*)pi
->extra
->parent
;
299 dest
= parent_pi
->net
;
302 table
= bgp_dest_table(dest
);
304 (table
->afi
== AFI_IP
|| table
->afi
== AFI_IP6
) &&
305 table
->safi
== SAFI_MPLS_VPN
)
310 /* Flag if the route path's family is VPN. */
311 static inline bool is_pi_family_vpn(struct bgp_path_info
*pi
)
313 return (is_pi_family_matching(pi
, AFI_IP
, SAFI_MPLS_VPN
) ||
314 is_pi_family_matching(pi
, AFI_IP6
, SAFI_MPLS_VPN
));
317 extern void vpn_policy_routemap_event(const char *rmap_name
);
319 extern vrf_id_t
get_first_vrf_for_redirect_with_rt(struct ecommunity
*eckey
);
321 extern void vpn_leak_postchange_all(void);
322 extern void vpn_handle_router_id_update(struct bgp
*bgp
, bool withdraw
,
324 extern void bgp_vpn_leak_unimport(struct bgp
*from_bgp
);
325 extern void bgp_vpn_leak_export(struct bgp
*from_bgp
);
327 #endif /* _QUAGGA_BGP_MPLSVPN_H */