]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_mplsvpn.h
Merge pull request #12317 from mobash-rasool/ospf-fixes
[mirror_frr.git] / bgpd / bgp_mplsvpn.h
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 *from_bgp,
79 struct bgp_path_info *path_vpn);
80
81 extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
82 extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
83 extern void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi);
84 extern void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi);
85 extern void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp);
86 extern void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi);
87 extern void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi);
88 extern void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp);
89 extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc);
90 extern void ensure_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi);
91 extern void delete_vrf_tovpn_sid(struct bgp *vpn, struct bgp *vrf, afi_t afi);
92 extern void delete_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf,
93 afi_t afi);
94 extern void delete_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf);
95 extern void ensure_vrf_tovpn_sid_per_af(struct bgp *vpn, struct bgp *vrf,
96 afi_t afi);
97 extern void ensure_vrf_tovpn_sid_per_vrf(struct bgp *vpn, struct bgp *vrf);
98 extern void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
99 uint8_t size);
100 extern void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
101 afi_t afi, safi_t safi);
102 void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
103 afi_t afi, safi_t safi);
104
105 static inline bool is_bgp_vrf_mplsvpn(struct bgp *bgp)
106 {
107 afi_t afi;
108
109 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
110 for (afi = 0; afi < AFI_MAX; ++afi) {
111 if (CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
112 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
113 || CHECK_FLAG(bgp->af_flags[afi][SAFI_UNICAST],
114 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT))
115 return true;
116 }
117 return false;
118 }
119
120 static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
121 const char **pmsg)
122 {
123 if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
124 && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
125
126 if (pmsg)
127 *pmsg = "source bgp instance neither vrf nor default";
128 return 0;
129 }
130
131 /* Is vrf configured to export to vpn? */
132 if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
133 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)
134 && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
135 BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
136 if (pmsg)
137 *pmsg = "export not set";
138 return 0;
139 }
140
141 /* Is there an RT list set? */
142 if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
143 if (pmsg)
144 *pmsg = "rtlist tovpn not defined";
145 return 0;
146 }
147
148 /* Is there an RD set? */
149 if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
150 BGP_VPN_POLICY_TOVPN_RD_SET)) {
151 if (pmsg)
152 *pmsg = "rd not defined";
153 return 0;
154 }
155
156 /* Is a route-map specified, but not defined? */
157 if (bgp_vrf->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN] &&
158 !bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
159 if (pmsg)
160 *pmsg = "route-map tovpn named but not defined";
161 return 0;
162 }
163
164 /* Is there an "auto" export label that isn't allocated yet? */
165 if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
166 BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
167 (bgp_vrf->vpn_policy[afi].tovpn_label == MPLS_LABEL_NONE)) {
168
169 if (pmsg)
170 *pmsg = "auto label not allocated";
171 return 0;
172 }
173
174 return 1;
175 }
176
177 static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
178 const char **pmsg)
179 {
180 if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
181 && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
182
183 if (pmsg)
184 *pmsg = "destination bgp instance neither vrf nor default";
185 return 0;
186 }
187
188 if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
189 if (pmsg)
190 *pmsg = "destination bgp instance vrf is VRF_UNKNOWN";
191 return 0;
192 }
193
194 /* Is vrf configured to import from vpn? */
195 if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
196 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)
197 && !CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
198 BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
199 if (pmsg)
200 *pmsg = "import not set";
201 return 0;
202 }
203
204 /* Is there an RT list set? */
205 if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
206 if (pmsg)
207 *pmsg = "rtlist fromvpn not defined";
208 return 0;
209 }
210
211 /* Is a route-map specified, but not defined? */
212 if (bgp_vrf->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN] &&
213 !bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
214 if (pmsg)
215 *pmsg = "route-map fromvpn named but not defined";
216 return 0;
217 }
218 return 1;
219 }
220
221 static inline void vpn_leak_prechange(enum vpn_policy_direction direction,
222 afi_t afi, struct bgp *bgp_vpn,
223 struct bgp *bgp_vrf)
224 {
225 /* Detect when default bgp instance is not (yet) defined by config */
226 if (!bgp_vpn)
227 return;
228
229 if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
230 vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
231
232 vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
233 }
234 if ((direction == BGP_VPN_POLICY_DIR_TOVPN) &&
235 vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) {
236
237 vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
238 }
239 }
240
241 static inline void vpn_leak_postchange(enum vpn_policy_direction direction,
242 afi_t afi, struct bgp *bgp_vpn,
243 struct bgp *bgp_vrf)
244 {
245 /* Detect when default bgp instance is not (yet) defined by config */
246 if (!bgp_vpn)
247 return;
248
249 if (direction == BGP_VPN_POLICY_DIR_FROMVPN) {
250 /* trigger a flush to re-sync with ADJ-RIB-in */
251 if (!CHECK_FLAG(bgp_vpn->af_flags[afi][SAFI_MPLS_VPN],
252 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
253 bgp_clear_soft_in(bgp_vpn, afi, SAFI_MPLS_VPN);
254 else
255 vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
256 }
257 if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
258
259 if (bgp_vrf->vpn_policy[afi].tovpn_label !=
260 bgp_vrf->vpn_policy[afi]
261 .tovpn_zebra_vrf_label_last_sent) {
262 vpn_leak_zebra_vrf_label_update(bgp_vrf, afi);
263 }
264
265 if (bgp_vrf->vpn_policy[afi].tovpn_sid_index == 0 &&
266 !CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
267 BGP_VPN_POLICY_TOVPN_SID_AUTO) &&
268 bgp_vrf->tovpn_sid_index == 0 &&
269 !CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
270 delete_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
271
272 if (!bgp_vrf->vpn_policy[afi].tovpn_sid && !bgp_vrf->tovpn_sid)
273 ensure_vrf_tovpn_sid(bgp_vpn, bgp_vrf, afi);
274
275 if ((!bgp_vrf->vpn_policy[afi].tovpn_sid &&
276 bgp_vrf->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent) ||
277 (!bgp_vrf->tovpn_sid &&
278 bgp_vrf->tovpn_zebra_vrf_sid_last_sent))
279 vpn_leak_zebra_vrf_sid_withdraw(bgp_vrf, afi);
280
281 if (bgp_vrf->vpn_policy[afi].tovpn_sid) {
282 if (sid_diff(bgp_vrf->vpn_policy[afi].tovpn_sid,
283 bgp_vrf->vpn_policy[afi]
284 .tovpn_zebra_vrf_sid_last_sent)) {
285 vpn_leak_zebra_vrf_sid_update(bgp_vrf, afi);
286 }
287 } else if (bgp_vrf->tovpn_sid) {
288 if (sid_diff(bgp_vrf->tovpn_sid,
289 bgp_vrf->tovpn_zebra_vrf_sid_last_sent)) {
290 vpn_leak_zebra_vrf_sid_update(bgp_vrf, afi);
291 }
292 }
293
294 vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
295 }
296 }
297
298 /* Flag if the route is injectable into VPN. This would be either a
299 * non-imported route or a non-VPN imported route.
300 */
301 static inline bool is_route_injectable_into_vpn(struct bgp_path_info *pi)
302 {
303 struct bgp_path_info *parent_pi;
304 struct bgp_table *table;
305 struct bgp_dest *dest;
306
307 if (pi->sub_type != BGP_ROUTE_IMPORTED ||
308 !pi->extra ||
309 !pi->extra->parent)
310 return true;
311
312 parent_pi = (struct bgp_path_info *)pi->extra->parent;
313 dest = parent_pi->net;
314 if (!dest)
315 return true;
316 table = bgp_dest_table(dest);
317 if (table &&
318 (table->afi == AFI_IP || table->afi == AFI_IP6) &&
319 table->safi == SAFI_MPLS_VPN)
320 return false;
321 return true;
322 }
323
324 /* Flag if the route path's family is VPN. */
325 static inline bool is_pi_family_vpn(struct bgp_path_info *pi)
326 {
327 return (is_pi_family_matching(pi, AFI_IP, SAFI_MPLS_VPN) ||
328 is_pi_family_matching(pi, AFI_IP6, SAFI_MPLS_VPN));
329 }
330
331 extern void vpn_policy_routemap_event(const char *rmap_name);
332
333 extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
334
335 extern void vpn_leak_postchange_all(void);
336 extern void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
337 bool is_config);
338 extern void bgp_vpn_leak_unimport(struct bgp *from_bgp);
339 extern void bgp_vpn_leak_export(struct bgp *from_bgp);
340
341 #endif /* _QUAGGA_BGP_MPLSVPN_H */