2 * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GxNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef _QUAGGA_BGP_MPLSVPN_H
22 #define _QUAGGA_BGP_MPLSVPN_H
24 #include "bgpd/bgp_attr.h"
25 #include "bgpd/bgp_route.h"
26 #include "bgpd/bgp_rd.h"
27 #include "bgpd/bgp_zebra.h"
29 #define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
30 #define MPLS_LABEL_IS_NULL(label) \
31 ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
32 || (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
33 || (label) == MPLS_LABEL_IMPLICIT_NULL)
35 #define BGP_VPNVX_HELP_STR \
40 " Network Next Hop Metric LocPrf Weight Path\n"
41 #define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
42 #define V4_HEADER_OVERLAY \
43 " Network Next Hop EthTag Overlay Index RouterMac\n"
45 extern void bgp_mplsvpn_init(void);
46 extern int bgp_nlri_parse_vpn(struct peer
*, struct attr
*, struct bgp_nlri
*);
47 extern uint32_t decode_label(mpls_label_t
*);
48 extern void encode_label(mpls_label_t
, mpls_label_t
*);
50 extern int argv_find_and_parse_vpnvx(struct cmd_token
**argv
, int argc
,
51 int *index
, afi_t
*afi
);
52 extern int bgp_show_mpls_vpn(struct vty
*vty
, afi_t afi
, struct prefix_rd
*prd
,
53 enum bgp_show_type type
, void *output_arg
,
54 int tags
, bool use_json
);
56 extern void vpn_leak_from_vrf_update(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
,
57 struct bgp_path_info
*path_vrf
);
59 extern void vpn_leak_from_vrf_withdraw(struct bgp
*bgp_vpn
, struct bgp
*bgp_vrf
,
60 struct bgp_path_info
*path_vrf
);
62 extern void vpn_leak_from_vrf_withdraw_all(struct bgp
*bgp_vpn
,
63 struct bgp
*bgp_vrf
, afi_t afi
);
65 extern void vpn_leak_from_vrf_update_all(struct bgp
*bgp_vpn
,
66 struct bgp
*bgp_vrf
, afi_t afi
);
68 extern void vpn_leak_to_vrf_withdraw_all(struct bgp
*bgp_vrf
, afi_t afi
);
70 extern void vpn_leak_to_vrf_update_all(struct bgp
*bgp_vrf
, struct bgp
*bgp_vpn
,
73 extern void vpn_leak_to_vrf_update(struct bgp
*bgp_vpn
,
74 struct bgp_path_info
*path_vpn
);
76 extern void vpn_leak_to_vrf_withdraw(struct bgp
*bgp_vpn
,
77 struct bgp_path_info
*path_vpn
);
79 extern void vpn_leak_zebra_vrf_label_update(struct bgp
*bgp
, afi_t afi
);
80 extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp
*bgp
, afi_t afi
);
81 extern void vpn_leak_zebra_vrf_sid_update(struct bgp
*bgp
, afi_t afi
);
82 extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp
*bgp
, afi_t afi
);
83 extern int vpn_leak_label_callback(mpls_label_t label
, void *lblid
, bool alloc
);
84 extern void ensure_vrf_tovpn_sid(struct bgp
*vpn
, struct bgp
*vrf
, afi_t afi
);
85 extern void transpose_sid(struct in6_addr
*sid
, uint32_t label
, uint8_t offset
,
87 extern void vrf_import_from_vrf(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
88 afi_t afi
, safi_t safi
);
89 void vrf_unimport_from_vrf(struct bgp
*to_bgp
, struct bgp
*from_bgp
,
90 afi_t afi
, safi_t safi
);
92 static inline bool is_bgp_vrf_mplsvpn(struct bgp
*bgp
)
96 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
97 for (afi
= 0; afi
< AFI_MAX
; ++afi
) {
98 if (CHECK_FLAG(bgp
->af_flags
[afi
][SAFI_UNICAST
],
99 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT
)
100 || CHECK_FLAG(bgp
->af_flags
[afi
][SAFI_UNICAST
],
101 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT
))
107 static inline int vpn_leak_to_vpn_active(struct bgp
*bgp_vrf
, afi_t afi
,
110 if (bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_VRF
111 && bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
) {
114 *pmsg
= "source bgp instance neither vrf nor default";
118 /* Is vrf configured to export to vpn? */
119 if (!CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
120 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT
)
121 && !CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
122 BGP_CONFIG_VRF_TO_VRF_EXPORT
)) {
124 *pmsg
= "export not set";
128 /* Is there an RT list set? */
129 if (!bgp_vrf
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_TOVPN
]) {
131 *pmsg
= "rtlist tovpn not defined";
135 /* Is there an RD set? */
136 if (!CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
137 BGP_VPN_POLICY_TOVPN_RD_SET
)) {
139 *pmsg
= "rd not defined";
143 /* Is a route-map specified, but not defined? */
144 if (bgp_vrf
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_TOVPN
] &&
145 !bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_TOVPN
]) {
147 *pmsg
= "route-map tovpn named but not defined";
151 /* Is there an "auto" export label that isn't allocated yet? */
152 if (CHECK_FLAG(bgp_vrf
->vpn_policy
[afi
].flags
,
153 BGP_VPN_POLICY_TOVPN_LABEL_AUTO
) &&
154 (bgp_vrf
->vpn_policy
[afi
].tovpn_label
== MPLS_LABEL_NONE
)) {
157 *pmsg
= "auto label not allocated";
164 static inline int vpn_leak_from_vpn_active(struct bgp
*bgp_vrf
, afi_t afi
,
167 if (bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_VRF
168 && bgp_vrf
->inst_type
!= BGP_INSTANCE_TYPE_DEFAULT
) {
171 *pmsg
= "destination bgp instance neither vrf nor default";
175 if (bgp_vrf
->vrf_id
== VRF_UNKNOWN
) {
177 *pmsg
= "destination bgp instance vrf is VRF_UNKNOWN";
181 /* Is vrf configured to import from vpn? */
182 if (!CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
183 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT
)
184 && !CHECK_FLAG(bgp_vrf
->af_flags
[afi
][SAFI_UNICAST
],
185 BGP_CONFIG_VRF_TO_VRF_IMPORT
)) {
187 *pmsg
= "import not set";
191 /* Is there an RT list set? */
192 if (!bgp_vrf
->vpn_policy
[afi
].rtlist
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
194 *pmsg
= "rtlist fromvpn not defined";
198 /* Is a route-map specified, but not defined? */
199 if (bgp_vrf
->vpn_policy
[afi
].rmap_name
[BGP_VPN_POLICY_DIR_FROMVPN
] &&
200 !bgp_vrf
->vpn_policy
[afi
].rmap
[BGP_VPN_POLICY_DIR_FROMVPN
]) {
202 *pmsg
= "route-map fromvpn named but not defined";
208 static inline void vpn_leak_prechange(vpn_policy_direction_t direction
,
209 afi_t afi
, struct bgp
*bgp_vpn
,
212 /* Detect when default bgp instance is not (yet) defined by config */
216 if ((direction
== BGP_VPN_POLICY_DIR_FROMVPN
) &&
217 vpn_leak_from_vpn_active(bgp_vrf
, afi
, NULL
)) {
219 vpn_leak_to_vrf_withdraw_all(bgp_vrf
, afi
);
221 if ((direction
== BGP_VPN_POLICY_DIR_TOVPN
) &&
222 vpn_leak_to_vpn_active(bgp_vrf
, afi
, NULL
)) {
224 vpn_leak_from_vrf_withdraw_all(bgp_vpn
, bgp_vrf
, afi
);
228 static inline void vpn_leak_postchange(vpn_policy_direction_t direction
,
229 afi_t afi
, struct bgp
*bgp_vpn
,
232 /* Detect when default bgp instance is not (yet) defined by config */
236 if (direction
== BGP_VPN_POLICY_DIR_FROMVPN
)
237 vpn_leak_to_vrf_update_all(bgp_vrf
, bgp_vpn
, afi
);
238 if (direction
== BGP_VPN_POLICY_DIR_TOVPN
) {
240 if (bgp_vrf
->vpn_policy
[afi
].tovpn_label
!=
241 bgp_vrf
->vpn_policy
[afi
]
242 .tovpn_zebra_vrf_label_last_sent
) {
243 vpn_leak_zebra_vrf_label_update(bgp_vrf
, afi
);
246 if (!bgp_vrf
->vpn_policy
[afi
].tovpn_sid
)
247 ensure_vrf_tovpn_sid(bgp_vpn
, bgp_vrf
, afi
);
249 if (!bgp_vrf
->vpn_policy
[afi
].tovpn_sid
250 && bgp_vrf
->vpn_policy
[afi
].tovpn_zebra_vrf_sid_last_sent
)
251 vpn_leak_zebra_vrf_sid_withdraw(bgp_vrf
, afi
);
253 if (sid_diff(bgp_vrf
->vpn_policy
[afi
].tovpn_sid
,
254 bgp_vrf
->vpn_policy
[afi
]
255 .tovpn_zebra_vrf_sid_last_sent
)) {
256 vpn_leak_zebra_vrf_sid_update(bgp_vrf
, afi
);
259 vpn_leak_from_vrf_update_all(bgp_vpn
, bgp_vrf
, afi
);
263 /* Flag if the route is injectable into VPN. This would be either a
264 * non-imported route or a non-VPN imported route.
266 static inline bool is_route_injectable_into_vpn(struct bgp_path_info
*pi
)
268 struct bgp_path_info
*parent_pi
;
269 struct bgp_table
*table
;
270 struct bgp_dest
*dest
;
272 if (pi
->sub_type
!= BGP_ROUTE_IMPORTED
||
277 parent_pi
= (struct bgp_path_info
*)pi
->extra
->parent
;
278 dest
= parent_pi
->net
;
281 table
= bgp_dest_table(dest
);
283 (table
->afi
== AFI_IP
|| table
->afi
== AFI_IP6
) &&
284 table
->safi
== SAFI_MPLS_VPN
)
289 /* Flag if the route path's family is VPN. */
290 static inline bool is_pi_family_vpn(struct bgp_path_info
*pi
)
292 return (is_pi_family_matching(pi
, AFI_IP
, SAFI_MPLS_VPN
) ||
293 is_pi_family_matching(pi
, AFI_IP6
, SAFI_MPLS_VPN
));
296 extern void vpn_policy_routemap_event(const char *rmap_name
);
298 extern vrf_id_t
get_first_vrf_for_redirect_with_rt(struct ecommunity
*eckey
);
300 extern void vpn_leak_postchange_all(void);
301 extern void vpn_handle_router_id_update(struct bgp
*bgp
, bool withdraw
,
303 extern void bgp_vpn_leak_unimport(struct bgp
*from_bgp
);
304 extern void bgp_vpn_leak_export(struct bgp
*from_bgp
);
306 #endif /* _QUAGGA_BGP_MPLSVPN_H */