Line data Source code
1 : /* MPLS-VPN
2 : * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
3 : *
4 : * This file is part of GxNU Zebra.
5 : *
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
9 : * later version.
10 : *
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.
15 : *
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
19 : */
20 :
21 : #ifndef _QUAGGA_BGP_MPLSVPN_H
22 : #define _QUAGGA_BGP_MPLSVPN_H
23 :
24 : #include "bgpd/bgp_attr.h"
25 : #include "bgpd/bgp_route.h"
26 : #include "bgpd/bgp_rd.h"
27 : #include "bgpd/bgp_zebra.h"
28 : #include "bgpd/bgp_vty.h"
29 :
30 : #define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
31 : #define MPLS_LABEL_IS_NULL(label) \
32 : ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \
33 : || (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \
34 : || (label) == MPLS_LABEL_IMPLICIT_NULL)
35 :
36 : #define BGP_VPNVX_HELP_STR BGP_AF_STR BGP_AF_STR
37 :
38 : #define V4_HEADER \
39 : " Network Next Hop Metric LocPrf Weight Path\n"
40 : #define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n"
41 : #define V4_HEADER_OVERLAY \
42 : " Network Next Hop EthTag Overlay Index RouterMac\n"
43 :
44 : #define BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH 20
45 :
46 : extern void bgp_mplsvpn_init(void);
47 : extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *);
48 : extern uint32_t decode_label(mpls_label_t *);
49 : extern void encode_label(mpls_label_t, mpls_label_t *);
50 :
51 : extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
52 : int *index, afi_t *afi);
53 : extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
54 : enum bgp_show_type type, void *output_arg,
55 : int tags, bool use_json);
56 :
57 : extern void vpn_leak_from_vrf_update(struct bgp *to_bgp, struct bgp *from_bgp,
58 : struct bgp_path_info *path_vrf);
59 :
60 : extern void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, struct bgp *from_bgp,
61 : struct bgp_path_info *path_vrf);
62 :
63 : extern void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp,
64 : struct bgp *from_bgp, afi_t afi);
65 :
66 : extern void vpn_leak_from_vrf_update_all(struct bgp *to_bgp,
67 : struct bgp *from_bgp, afi_t afi);
68 :
69 : extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi);
70 :
71 : extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
72 : afi_t afi);
73 :
74 : extern bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
75 : struct bgp_path_info *path_vpn,
76 : struct prefix_rd *prd);
77 :
78 : extern void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn);
79 :
80 : extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
81 : extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
82 : extern void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi);
83 : extern void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi);
84 : extern void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp);
85 : extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi);
86 : extern void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi);
87 : extern void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp);
88 : extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc);
89 : extern void ensure_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi);
90 : extern void delete_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi);
91 : extern void delete_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf,
92 : afi_t afi);
93 : extern void delete_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf);
94 : extern void ensure_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf,
95 : afi_t afi);
96 : extern void ensure_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf);
97 : extern void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
98 : uint8_t size);
99 : extern void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
100 : afi_t afi, safi_t safi);
101 : void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
102 : afi_t afi, safi_t safi);
103 :
104 : static inline bool is_bgp_vrf_mplsvpn(struct bgp *bgp)
105 : {
106 : afi_t afi;
107 :
108 : if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
109 : for (afi = 0; afi < AFI_MAX; ++afi) {
110 : if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
111 : BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
112 : || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
113 : BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT))
114 : return true;
115 : }
116 : return false;
117 : }
118 :
119 66 : static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
120 : const char **pmsg)
121 : {
122 66 : if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
123 : && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
124 :
125 0 : if (pmsg)
126 0 : *pmsg = "source bgp instance neither vrf nor default";
127 0 : return 0;
128 : }
129 :
130 : /* Is vrf configured to export to vpn? */
131 66 : if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
132 : BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
133 : && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
134 : BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
135 66 : if (pmsg)
136 26 : *pmsg = "export not set";
137 66 : return 0;
138 : }
139 :
140 : /* Is there an RT list set? */
141 0 : if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
142 0 : if (pmsg)
143 0 : *pmsg = "rtlist tovpn not defined";
144 0 : return 0;
145 : }
146 :
147 : /* Is there an RD set? */
148 0 : if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
149 : BGP_VPN_POLICY_TOVPN_RD_SET)) {
150 0 : if (pmsg)
151 0 : *pmsg = "rd not defined";
152 0 : return 0;
153 : }
154 :
155 : /* Is a route-map specified, but not defined? */
156 0 : if (bgp_vrf->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN] &&
157 0 : !bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
158 0 : if (pmsg)
159 0 : *pmsg = "route-map tovpn named but not defined";
160 0 : return 0;
161 : }
162 :
163 : /* Is there an "auto" export label that isn't allocated yet? */
164 0 : if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
165 0 : BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
166 0 : (bgp_vrf->vpn_policy[afi].tovpn_label == MPLS_LABEL_NONE)) {
167 :
168 0 : if (pmsg)
169 0 : *pmsg = "auto label not allocated";
170 0 : return 0;
171 : }
172 :
173 : return 1;
174 : }
175 :
176 0 : static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
177 : const char **pmsg)
178 : {
179 0 : if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
180 : && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
181 :
182 0 : if (pmsg)
183 0 : *pmsg = "destination bgp instance neither vrf nor default";
184 0 : return 0;
185 : }
186 :
187 0 : if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
188 0 : if (pmsg)
189 0 : *pmsg = "destination bgp instance vrf is VRF_UNKNOWN";
190 0 : return 0;
191 : }
192 :
193 : /* Is vrf configured to import from vpn? */
194 0 : if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
195 : BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)
196 : && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
197 : BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
198 0 : if (pmsg)
199 0 : *pmsg = "import not set";
200 0 : return 0;
201 : }
202 :
203 : /* Is there an RT list set? */
204 0 : if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
205 0 : if (pmsg)
206 0 : *pmsg = "rtlist fromvpn not defined";
207 0 : return 0;
208 : }
209 :
210 : /* Is a route-map specified, but not defined? */
211 0 : if (bgp_vrf->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN] &&
212 0 : !bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
213 0 : if (pmsg)
214 0 : *pmsg = "route-map fromvpn named but not defined";
215 0 : return 0;
216 : }
217 : return 1;
218 : }
219 :
220 8 : static inline void vpn_leak_prechange(enum vpn_policy_direction direction,
221 : afi_t afi, struct bgp *bgp_vpn,
222 : struct bgp *bgp_vrf)
223 : {
224 : /* Detect when default bgp instance is not (yet) defined by config */
225 8 : if (!bgp_vpn)
226 : return;
227 :
228 8 : if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
229 0 : vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
230 :
231 0 : vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
232 : }
233 16 : if ((direction == BGP_VPN_POLICY_DIR_TOVPN) &&
234 8 : vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) {
235 :
236 0 : vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
237 : }
238 : }
239 :
240 0 : static inline void vpn_leak_postchange(enum vpn_policy_direction direction,
241 : afi_t afi, struct bgp *bgp_vpn,
242 : struct bgp *bgp_vrf)
243 : {
244 : /* Detect when default bgp instance is not (yet) defined by config */
245 0 : if (!bgp_vpn)
246 : return;
247 :
248 0 : if (direction == BGP_VPN_POLICY_DIR_FROMVPN) {
249 : /* trigger a flush to re-sync with ADJ-RIB-in */
250 0 : if (!CHECK_FLAG(bgp_vpn->af_flags[afi][SAFI_MPLS_VPN],
251 : BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
252 0 : bgp_clear_soft_in(bgp_vpn, afi, SAFI_MPLS_VPN);
253 : else
254 0 : vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
255 : }
256 0 : if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
257 :
258 0 : if (bgp_vrf->vpn_policy[afi].tovpn_label !=
259 : bgp_vrf->vpn_policy[afi]
260 0 : .tovpn_zebra_vrf_label_last_sent) {
261 0 : vpn_leak_zebra_vrf_label_update(bgp_vrf, afi);
262 : }
263 :
264 0 : if (bgp_vrf->vpn_policy[afi].tovpn_sid_index == 0 &&
265 0 : !CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
266 0 : BGP_VPN_POLICY_TOVPN_SID_AUTO) &&
267 0 : bgp_vrf->tovpn_sid_index == 0 &&
268 0 : !CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
269 0 : delete_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
270 :
271 0 : if (!bgp_vrf->vpn_policy[afi].tovpn_sid && !bgp_vrf->tovpn_sid)
272 0 : ensure_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
273 :
274 0 : if ((!bgp_vrf->vpn_policy[afi].tovpn_sid &&
275 0 : bgp_vrf->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent) ||
276 0 : (!bgp_vrf->tovpn_sid &&
277 0 : bgp_vrf->tovpn_zebra_vrf_sid_last_sent))
278 0 : vpn_leak_zebra_vrf_sid_withdraw(bgp_vrf, afi);
279 :
280 0 : if (bgp_vrf->vpn_policy[afi].tovpn_sid) {
281 0 : if (sid_diff(bgp_vrf->vpn_policy[afi].tovpn_sid,
282 : bgp_vrf->vpn_policy[afi]
283 0 : .tovpn_zebra_vrf_sid_last_sent)) {
284 0 : vpn_leak_zebra_vrf_sid_update(bgp_vrf, afi);
285 : }
286 0 : } else if (bgp_vrf->tovpn_sid) {
287 0 : if (sid_diff(bgp_vrf->tovpn_sid,
288 0 : bgp_vrf->tovpn_zebra_vrf_sid_last_sent)) {
289 0 : vpn_leak_zebra_vrf_sid_update(bgp_vrf, afi);
290 : }
291 : }
292 :
293 0 : vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
294 : }
295 : }
296 :
297 : /* Flag if the route is injectable into VPN. This would be either a
298 : * non-imported route or a non-VPN imported route.
299 : */
300 26 : static inline bool is_route_injectable_into_vpn(struct bgp_path_info *pi)
301 : {
302 26 : struct bgp_path_info *parent_pi;
303 26 : struct bgp_table *table;
304 26 : struct bgp_dest *dest;
305 :
306 26 : if (pi->sub_type != BGP_ROUTE_IMPORTED ||
307 0 : !pi->extra ||
308 0 : !pi->extra->parent)
309 : return true;
310 :
311 0 : parent_pi = (struct bgp_path_info *)pi->extra->parent;
312 0 : dest = parent_pi->net;
313 0 : if (!dest)
314 : return true;
315 0 : table = bgp_dest_table(dest);
316 0 : if (table &&
317 0 : (table->afi == AFI_IP || table->afi == AFI_IP6) &&
318 0 : table->safi == SAFI_MPLS_VPN)
319 0 : return false;
320 : return true;
321 : }
322 :
323 : /* Flag if the route path's family is VPN. */
324 0 : static inline bool is_pi_family_vpn(struct bgp_path_info *pi)
325 : {
326 0 : return (is_pi_family_matching(pi, AFI_IP, SAFI_MPLS_VPN) ||
327 0 : is_pi_family_matching(pi, AFI_IP6, SAFI_MPLS_VPN));
328 : }
329 :
330 : extern void vpn_policy_routemap_event(const char *rmap_name);
331 :
332 : extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
333 :
334 : extern void vpn_leak_postchange_all(void);
335 : extern void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
336 : bool is_config);
337 : extern void bgp_vpn_leak_unimport(struct bgp *from_bgp);
338 : extern void bgp_vpn_leak_export(struct bgp *from_bgp);
339 :
340 : #endif /* _QUAGGA_BGP_MPLSVPN_H */
|