]>
Commit | Line | Data |
---|---|---|
a4168ebc | 1 | /* BGP EVPN internal definitions |
2 | * Copyright (C) 2017 Cumulus Networks, Inc. | |
3 | * | |
4 | * This file is part of FRR. | |
5 | * | |
6 | * FRR 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 | * FRR 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 | |
17 | * along with FRR; see the file COPYING. If not, write to the Free | |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #ifndef _BGP_EVPN_PRIVATE_H | |
23 | #define _BGP_EVPN_PRIVATE_H | |
24 | ||
25 | #include "vxlan.h" | |
26 | #include "zebra.h" | |
27 | ||
28 | #include "bgpd/bgpd.h" | |
29 | #include "bgpd/bgp_ecommunity.h" | |
30 | ||
60466a63 | 31 | #define RT_ADDRSTRLEN 28 |
9c92b5f7 | 32 | |
e9fc2840 | 33 | /* EVPN prefix lengths. This reprsent the sizeof struct prefix_evpn */ |
a4168ebc | 34 | #define EVPN_TYPE_2_ROUTE_PREFIXLEN 224 |
35 | #define EVPN_TYPE_3_ROUTE_PREFIXLEN 224 | |
e9fc2840 | 36 | #define EVPN_TYPE_5_ROUTE_PREFIXLEN 224 |
a4168ebc | 37 | |
38 | /* EVPN route types. */ | |
d62a17ae | 39 | typedef enum { |
40 | BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */ | |
41 | BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */ | |
42 | BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */ | |
43 | BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */ | |
44 | BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */ | |
a4168ebc | 45 | } bgp_evpn_route_type; |
46 | ||
47 | /* | |
48 | * Hash table of EVIs. Right now, the only type of EVI supported is with | |
49 | * VxLAN encapsulation, hence each EVI corresponds to a L2 VNI. | |
50 | * The VNIs are not "created" through BGP but through some other interface | |
51 | * on the system. This table stores VNIs that BGP comes to know as present | |
52 | * on the system (through interaction with zebra) as well as pre-configured | |
53 | * VNIs (which need to be defined in the system to become "live"). | |
54 | */ | |
d62a17ae | 55 | struct bgpevpn { |
56 | vni_t vni; | |
29c53922 | 57 | vrf_id_t tenant_vrf_id; |
d62a17ae | 58 | u_int32_t flags; |
a4168ebc | 59 | #define VNI_FLAG_CFGD 0x1 /* VNI is user configured */ |
60 | #define VNI_FLAG_LIVE 0x2 /* VNI is "live" */ | |
61 | #define VNI_FLAG_RD_CFGD 0x4 /* RD is user configured. */ | |
62 | #define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */ | |
63 | #define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */ | |
64 | ||
bc4606bd MK |
65 | struct bgp *bgp_vrf; /* back pointer to the vrf instance */ |
66 | ||
1a98c087 MK |
67 | /* Flag to indicate if we are advertising the g/w mac ip for this VNI*/ |
68 | u_int8_t advertise_gw_macip; | |
69 | ||
31310b25 MK |
70 | /* Flag to indicate if we are advertising subnet for this VNI */ |
71 | u_int8_t advertise_subnet; | |
72 | ||
d62a17ae | 73 | /* Id for deriving the RD automatically for this VNI */ |
74 | u_int16_t rd_id; | |
a4168ebc | 75 | |
d62a17ae | 76 | /* RD for this VNI. */ |
77 | struct prefix_rd prd; | |
a4168ebc | 78 | |
d62a17ae | 79 | /* Route type 3 field */ |
80 | struct in_addr originator_ip; | |
a4168ebc | 81 | |
d62a17ae | 82 | /* Import and Export RTs. */ |
83 | struct list *import_rtl; | |
84 | struct list *export_rtl; | |
a4168ebc | 85 | |
d62a17ae | 86 | /* Route table for EVPN routes for this VNI. */ |
87 | struct bgp_table *route_table; | |
a4168ebc | 88 | |
d62a17ae | 89 | QOBJ_FIELDS |
a4168ebc | 90 | }; |
91 | ||
92 | DECLARE_QOBJ_TYPE(bgpevpn) | |
93 | ||
94 | /* Mapping of Import RT to VNIs. | |
95 | * The Import RTs of all VNIs are maintained in a hash table with each | |
96 | * RT linking to all VNIs that will import routes matching this RT. | |
97 | */ | |
d62a17ae | 98 | struct irt_node { |
99 | /* RT */ | |
100 | struct ecommunity_val rt; | |
a4168ebc | 101 | |
d62a17ae | 102 | /* List of VNIs importing routes matching this RT. */ |
103 | struct list *vnis; | |
a4168ebc | 104 | }; |
105 | ||
10ebe1ab MK |
106 | /* Mapping of Import RT to VRFs. |
107 | * The Import RTs of all VRFss are maintained in a hash table with each | |
108 | * RT linking to all VRFs that will import routes matching this RT. | |
109 | */ | |
110 | struct vrf_irt_node { | |
111 | /* RT */ | |
112 | struct ecommunity_val rt; | |
113 | ||
114 | /* List of VNIs importing routes matching this RT. */ | |
115 | struct list *vrfs; | |
116 | }; | |
117 | ||
118 | ||
128ea8ab | 119 | #define RT_TYPE_IMPORT 1 |
120 | #define RT_TYPE_EXPORT 2 | |
121 | #define RT_TYPE_BOTH 3 | |
122 | ||
676f83b9 | 123 | static inline int is_vrf_rd_configured(struct bgp *bgp_vrf) |
124 | { | |
125 | return (CHECK_FLAG(bgp_vrf->vrf_flags, | |
126 | BGP_VRF_RD_CFGD)); | |
127 | } | |
128 | ||
129 | static inline int bgp_evpn_vrf_rd_matches_existing(struct bgp *bgp_vrf, | |
130 | struct prefix_rd *prd) | |
131 | { | |
132 | return (memcmp(&bgp_vrf->vrf_prd.val, prd->val, ECOMMUNITY_SIZE) == 0); | |
133 | } | |
134 | ||
6d8c58b7 MK |
135 | static inline vni_t bgpevpn_get_l3vni(struct bgpevpn *vpn) |
136 | { | |
bc4606bd | 137 | return vpn->bgp_vrf ? vpn->bgp_vrf->l3vni : 0; |
6d8c58b7 MK |
138 | } |
139 | ||
140 | static inline void bgpevpn_get_rmac(struct bgpevpn *vpn, struct ethaddr *rmac) | |
141 | { | |
6d8c58b7 | 142 | memset(rmac, 0, sizeof(struct ethaddr)); |
bc4606bd | 143 | if (!vpn->bgp_vrf) |
6d8c58b7 | 144 | return; |
bc4606bd | 145 | memcpy(rmac, &vpn->bgp_vrf->rmac, sizeof(struct ethaddr)); |
6d8c58b7 MK |
146 | } |
147 | ||
148 | static inline struct list *bgpevpn_get_vrf_export_rtl(struct bgpevpn *vpn) | |
149 | { | |
bc4606bd | 150 | if (!vpn->bgp_vrf) |
6d8c58b7 MK |
151 | return NULL; |
152 | ||
bc4606bd | 153 | return vpn->bgp_vrf->vrf_export_rtl; |
6d8c58b7 MK |
154 | } |
155 | ||
156 | static inline struct list *bgpevpn_get_vrf_import_rtl(struct bgpevpn *vpn) | |
157 | { | |
bc4606bd | 158 | if (!vpn->bgp_vrf) |
6d8c58b7 MK |
159 | return NULL; |
160 | ||
bc4606bd | 161 | return vpn->bgp_vrf->vrf_import_rtl; |
6d8c58b7 MK |
162 | } |
163 | ||
6a8657d0 MK |
164 | static inline void bgpevpn_unlink_from_l3vni(struct bgpevpn *vpn) |
165 | { | |
bc4606bd MK |
166 | /* bail if vpn is not associated to bgp_vrf */ |
167 | if (!vpn->bgp_vrf) | |
6a8657d0 | 168 | return; |
bc4606bd MK |
169 | |
170 | listnode_delete(vpn->bgp_vrf->l2vnis, vpn); | |
171 | ||
172 | /* remove the backpointer to the vrf instance */ | |
173 | vpn->bgp_vrf = NULL; | |
6a8657d0 MK |
174 | } |
175 | ||
176 | static inline void bgpevpn_link_to_l3vni(struct bgpevpn *vpn) | |
177 | { | |
178 | struct bgp *bgp_vrf = NULL; | |
179 | ||
bc4606bd MK |
180 | /* bail if vpn is already associated to vrf */ |
181 | if (vpn->bgp_vrf) | |
182 | return; | |
183 | ||
6a8657d0 MK |
184 | bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id); |
185 | if (!bgp_vrf || !bgp_vrf->l2vnis) | |
186 | return; | |
bc4606bd MK |
187 | |
188 | /* associate the vpn to the bgp_vrf instance */ | |
189 | vpn->bgp_vrf = bgp_vrf; | |
6a8657d0 MK |
190 | listnode_add_sort(bgp_vrf->l2vnis, vpn); |
191 | } | |
192 | ||
d62a17ae | 193 | static inline int is_vni_configured(struct bgpevpn *vpn) |
128ea8ab | 194 | { |
d62a17ae | 195 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_CFGD)); |
128ea8ab | 196 | } |
197 | ||
d62a17ae | 198 | static inline int is_vni_live(struct bgpevpn *vpn) |
128ea8ab | 199 | { |
d62a17ae | 200 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_LIVE)); |
128ea8ab | 201 | } |
202 | ||
d62a17ae | 203 | static inline int is_rd_configured(struct bgpevpn *vpn) |
128ea8ab | 204 | { |
d62a17ae | 205 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_RD_CFGD)); |
128ea8ab | 206 | } |
207 | ||
d62a17ae | 208 | static inline int bgp_evpn_rd_matches_existing(struct bgpevpn *vpn, |
209 | struct prefix_rd *prd) | |
128ea8ab | 210 | { |
d62a17ae | 211 | return (memcmp(&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0); |
128ea8ab | 212 | } |
213 | ||
d62a17ae | 214 | static inline int is_import_rt_configured(struct bgpevpn *vpn) |
128ea8ab | 215 | { |
d62a17ae | 216 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD)); |
128ea8ab | 217 | } |
218 | ||
d62a17ae | 219 | static inline int is_export_rt_configured(struct bgpevpn *vpn) |
128ea8ab | 220 | { |
d62a17ae | 221 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD)); |
128ea8ab | 222 | } |
223 | ||
d62a17ae | 224 | static inline int is_vni_param_configured(struct bgpevpn *vpn) |
128ea8ab | 225 | { |
d62a17ae | 226 | return (is_rd_configured(vpn) || is_import_rt_configured(vpn) |
227 | || is_export_rt_configured(vpn)); | |
128ea8ab | 228 | } |
229 | ||
bc59a672 MK |
230 | static inline void encode_rmac_extcomm(struct ecommunity_val *eval, |
231 | struct ethaddr *rmac) | |
232 | { | |
233 | memset(eval, 0, sizeof(*eval)); | |
234 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
235 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; | |
236 | memcpy(&eval->val[2], rmac, ETH_ALEN); | |
237 | } | |
238 | ||
ead40654 MK |
239 | static inline void encode_default_gw_extcomm(struct ecommunity_val *eval) |
240 | { | |
241 | memset(eval, 0, sizeof(*eval)); | |
242 | eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE; | |
243 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_DEF_GW; | |
244 | } | |
245 | ||
d62a17ae | 246 | static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq, |
247 | struct ecommunity_val *eval) | |
128ea8ab | 248 | { |
d62a17ae | 249 | memset(eval, 0, sizeof(*eval)); |
250 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
251 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY; | |
252 | if (static_mac) | |
253 | eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY; | |
254 | eval->val[4] = (seq >> 24) & 0xff; | |
255 | eval->val[5] = (seq >> 16) & 0xff; | |
256 | eval->val[6] = (seq >> 8) & 0xff; | |
257 | eval->val[7] = seq & 0xff; | |
128ea8ab | 258 | } |
259 | ||
90264d64 MK |
260 | static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, |
261 | struct prefix *ip) | |
262 | { | |
263 | memset(ip, 0, sizeof(struct prefix)); | |
264 | if (IS_EVPN_PREFIX_IPADDR_V4(evp)) { | |
265 | ip->family = AF_INET; | |
266 | ip->prefixlen = evp->prefix.ip_prefix_length; | |
267 | memcpy(&(ip->u.prefix4), | |
268 | &(evp->prefix.ip.ip), | |
269 | IPV4_MAX_BYTELEN); | |
270 | } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) { | |
271 | ip->family = AF_INET6; | |
272 | ip->prefixlen = evp->prefix.ip_prefix_length; | |
273 | memcpy(&(ip->u.prefix6), | |
274 | &(evp->prefix.ip.ip), | |
275 | IPV6_MAX_BYTELEN); | |
276 | } | |
277 | } | |
278 | ||
d3135ba3 | 279 | static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp, |
280 | struct prefix *ip) | |
281 | { | |
282 | memset(ip, 0, sizeof(struct prefix)); | |
283 | if (IS_EVPN_PREFIX_IPADDR_V4(evp)) { | |
284 | ip->family = AF_INET; | |
285 | ip->prefixlen = IPV4_MAX_BITLEN; | |
286 | memcpy(&(ip->u.prefix4), | |
287 | &(evp->prefix.ip.ip), | |
288 | IPV4_MAX_BYTELEN); | |
289 | } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) { | |
290 | ip->family = AF_INET6; | |
291 | ip->prefixlen = IPV6_MAX_BITLEN; | |
292 | memcpy(&(ip->u.prefix6), | |
293 | &(evp->prefix.ip.ip), | |
294 | IPV6_MAX_BYTELEN); | |
295 | } | |
296 | } | |
297 | ||
d62a17ae | 298 | static inline void build_evpn_type2_prefix(struct prefix_evpn *p, |
299 | struct ethaddr *mac, | |
300 | struct ipaddr *ip) | |
128ea8ab | 301 | { |
d62a17ae | 302 | memset(p, 0, sizeof(struct prefix_evpn)); |
b03b8898 | 303 | p->family = AF_EVPN; |
d62a17ae | 304 | p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN; |
305 | p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; | |
28328ea9 | 306 | memcpy(&p->prefix.mac.octet, mac->octet, ETH_ALEN); |
d62a17ae | 307 | p->prefix.ip.ipa_type = IPADDR_NONE; |
308 | if (ip) | |
309 | memcpy(&p->prefix.ip, ip, sizeof(*ip)); | |
128ea8ab | 310 | } |
311 | ||
342dd0c6 | 312 | static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp, |
313 | struct prefix *ip_prefix) | |
314 | { | |
315 | struct ipaddr ip; | |
316 | ||
317 | memset(&ip, 0, sizeof(struct ipaddr)); | |
318 | if (ip_prefix->family == AF_INET) { | |
319 | ip.ipa_type = IPADDR_V4; | |
320 | memcpy(&ip.ipaddr_v4, &ip_prefix->u.prefix4, | |
321 | sizeof(struct in_addr)); | |
322 | } else { | |
323 | ip.ipa_type = IPADDR_V6; | |
324 | memcpy(&ip.ipaddr_v6, &ip_prefix->u.prefix6, | |
325 | sizeof(struct in6_addr)); | |
326 | } | |
327 | ||
328 | memset(evp, 0, sizeof(struct prefix_evpn)); | |
329 | evp->family = AF_EVPN; | |
330 | evp->prefixlen = EVPN_TYPE_5_ROUTE_PREFIXLEN; | |
331 | evp->prefix.ip_prefix_length = ip_prefix->prefixlen; | |
332 | evp->prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE; | |
333 | evp->prefix.ip.ipa_type = ip.ipa_type; | |
334 | memcpy(&evp->prefix.ip, &ip, sizeof(struct ipaddr)); | |
335 | } | |
336 | ||
d62a17ae | 337 | static inline void build_evpn_type3_prefix(struct prefix_evpn *p, |
338 | struct in_addr originator_ip) | |
128ea8ab | 339 | { |
d62a17ae | 340 | memset(p, 0, sizeof(struct prefix_evpn)); |
b03b8898 | 341 | p->family = AF_EVPN; |
d62a17ae | 342 | p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN; |
343 | p->prefix.route_type = BGP_EVPN_IMET_ROUTE; | |
344 | p->prefix.ip.ipa_type = IPADDR_V4; | |
345 | p->prefix.ip.ipaddr_v4 = originator_ip; | |
128ea8ab | 346 | } |
347 | ||
06d2e8f3 MK |
348 | static inline int advertise_type5_routes(struct bgp *bgp_vrf, |
349 | afi_t afi) | |
350 | { | |
351 | if (!bgp_vrf->l3vni) | |
352 | return 0; | |
353 | ||
354 | if (afi == AFI_IP && | |
355 | CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) | |
356 | return 1; | |
357 | ||
358 | if (afi == AFI_IP6 && | |
359 | CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) | |
360 | return 1; | |
361 | ||
362 | return 0; | |
363 | } | |
364 | ||
c581d8b0 | 365 | extern void evpn_rt_delete_auto(struct bgp*, vni_t, struct list*); |
523cafc4 | 366 | extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf, |
367 | struct ecommunity *ecomadd); | |
368 | extern void bgp_evpn_unconfigure_export_rt_for_vrf(struct bgp *bgp_vrf, | |
369 | struct ecommunity *ecomdel); | |
370 | extern void bgp_evpn_configure_import_rt_for_vrf(struct bgp *bgp_vrf, | |
371 | struct ecommunity *ecomadd); | |
372 | extern void bgp_evpn_unconfigure_import_rt_for_vrf(struct bgp *bgp_vrf, | |
373 | struct ecommunity *ecomdel); | |
d62a17ae | 374 | extern int bgp_evpn_handle_export_rt_change(struct bgp *bgp, |
375 | struct bgpevpn *vpn); | |
676f83b9 | 376 | extern void bgp_evpn_handle_vrf_rd_change(struct bgp *bgp_vrf, int withdraw); |
d62a17ae | 377 | extern void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn, |
378 | int withdraw); | |
379 | extern int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn); | |
380 | extern int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn); | |
523cafc4 | 381 | extern void bgp_evpn_map_vrf_to_its_rts(struct bgp *bgp_vrf); |
382 | extern void bgp_evpn_unmap_vrf_from_its_rts(struct bgp *bgp_vrf); | |
d62a17ae | 383 | extern void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn); |
384 | extern void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp, | |
385 | struct bgpevpn *vpn); | |
386 | extern void bgp_evpn_derive_auto_rt_import(struct bgp *bgp, | |
387 | struct bgpevpn *vpn); | |
388 | extern void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, | |
389 | struct bgpevpn *vpn); | |
390 | extern void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn); | |
676f83b9 | 391 | extern void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp); |
d62a17ae | 392 | extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni); |
393 | extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, | |
29c53922 MK |
394 | struct in_addr originator_ip, |
395 | vrf_id_t tenant_vrf_id); | |
d62a17ae | 396 | extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn); |
a4168ebc | 397 | #endif /* _BGP_EVPN_PRIVATE_H */ |