]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
a4168ebc | 2 | /* BGP EVPN internal definitions |
3 | * Copyright (C) 2017 Cumulus Networks, Inc. | |
a4168ebc | 4 | */ |
5 | ||
6 | #ifndef _BGP_EVPN_PRIVATE_H | |
7 | #define _BGP_EVPN_PRIVATE_H | |
8 | ||
9 | #include "vxlan.h" | |
10 | #include "zebra.h" | |
11 | ||
12 | #include "bgpd/bgpd.h" | |
13 | #include "bgpd/bgp_ecommunity.h" | |
14 | ||
60466a63 | 15 | #define RT_ADDRSTRLEN 28 |
9c92b5f7 | 16 | |
2f04c4f0 AK |
17 | /* EVPN prefix lengths. This represents the sizeof struct evpn_addr |
18 | * in bits */ | |
19 | #define EVPN_ROUTE_PREFIXLEN (sizeof(struct evpn_addr) * 8) | |
a4168ebc | 20 | |
c44ab6f1 AK |
21 | /* EVPN route RD buffer length */ |
22 | #define BGP_EVPN_PREFIX_RD_LEN 100 | |
23 | ||
24 | /* packet sizes for EVPN routes */ | |
25 | /* Type-1 route should be 25 bytes | |
26 | * RD (8), ESI (10), eth-tag (4), vni (3) | |
27 | */ | |
28 | #define BGP_EVPN_TYPE1_PSIZE 25 | |
29 | /* Type-4 route should be either 23 or 35 bytes | |
30 | * RD (8), ESI (10), ip-len (1), ip (4 or 16) | |
31 | */ | |
32 | #define BGP_EVPN_TYPE4_V4_PSIZE 23 | |
33 | #define BGP_EVPN_TYPE4_V6_PSIZE 34 | |
34 | ||
c44ab6f1 AK |
35 | RB_HEAD(bgp_es_evi_rb_head, bgp_evpn_es_evi); |
36 | RB_PROTOTYPE(bgp_es_evi_rb_head, bgp_evpn_es_evi, rb_node, | |
37 | bgp_es_evi_rb_cmp); | |
a4168ebc | 38 | /* |
39 | * Hash table of EVIs. Right now, the only type of EVI supported is with | |
40 | * VxLAN encapsulation, hence each EVI corresponds to a L2 VNI. | |
41 | * The VNIs are not "created" through BGP but through some other interface | |
42 | * on the system. This table stores VNIs that BGP comes to know as present | |
43 | * on the system (through interaction with zebra) as well as pre-configured | |
44 | * VNIs (which need to be defined in the system to become "live"). | |
45 | */ | |
d62a17ae | 46 | struct bgpevpn { |
47 | vni_t vni; | |
29c53922 | 48 | vrf_id_t tenant_vrf_id; |
9daa5d47 | 49 | ifindex_t svi_ifindex; |
d7c0a89a | 50 | uint32_t flags; |
a4168ebc | 51 | #define VNI_FLAG_CFGD 0x1 /* VNI is user configured */ |
52 | #define VNI_FLAG_LIVE 0x2 /* VNI is "live" */ | |
53 | #define VNI_FLAG_RD_CFGD 0x4 /* RD is user configured. */ | |
54 | #define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */ | |
55 | #define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */ | |
c48d9f5f MK |
56 | #define VNI_FLAG_USE_TWO_LABELS 0x20 /* Attach both L2-VNI and L3-VNI if |
57 | needed for this VPN */ | |
a4168ebc | 58 | |
bc4606bd MK |
59 | struct bgp *bgp_vrf; /* back pointer to the vrf instance */ |
60 | ||
996c9314 LB |
61 | /* Flag to indicate if we are |
62 | * advertising the g/w mac ip for | |
63 | * this VNI*/ | |
d7c0a89a | 64 | uint8_t advertise_gw_macip; |
1a98c087 | 65 | |
d7c0a89a QY |
66 | /* Flag to indicate if we are |
67 | * advertising subnet for this VNI */ | |
68 | uint8_t advertise_subnet; | |
31310b25 | 69 | |
24864e44 CS |
70 | /* Flag to indicate if we are advertising the svi mac ip for this VNI*/ |
71 | uint8_t advertise_svi_macip; | |
72 | ||
d7c0a89a QY |
73 | /* Id for deriving the RD |
74 | * automatically for this VNI */ | |
75 | uint16_t rd_id; | |
a4168ebc | 76 | |
d7c0a89a QY |
77 | /* RD for this VNI. */ |
78 | struct prefix_rd prd; | |
fa566a94 | 79 | char *prd_pretty; |
a4168ebc | 80 | |
d7c0a89a QY |
81 | /* Route type 3 field */ |
82 | struct in_addr originator_ip; | |
a4168ebc | 83 | |
76d07c7a AK |
84 | /* PIM-SM MDT group for BUM flooding */ |
85 | struct in_addr mcast_grp; | |
86 | ||
d7c0a89a QY |
87 | /* Import and Export RTs. */ |
88 | struct list *import_rtl; | |
89 | struct list *export_rtl; | |
a4168ebc | 90 | |
021b6596 AD |
91 | /* |
92 | * EVPN route that uses gateway IP overlay index as its nexthop | |
93 | * needs to do a recursive lookup. | |
94 | * A remote MAC/IP entry should be present for the gateway IP. | |
95 | * Maintain a hash of the addresses received via remote MAC/IP routes | |
96 | * for efficient gateway IP recursive lookup in this EVI | |
97 | */ | |
98 | struct hash *remote_ip_hash; | |
99 | ||
852d9f97 | 100 | /* Route tables for EVPN routes for |
d7c0a89a | 101 | * this VNI. */ |
852d9f97 SW |
102 | struct bgp_table *ip_table; |
103 | struct bgp_table *mac_table; | |
a4168ebc | 104 | |
c44ab6f1 AK |
105 | /* RB tree of ES-EVIs */ |
106 | struct bgp_es_evi_rb_head es_evi_rb_tree; | |
50f74cf1 | 107 | |
c44ab6f1 AK |
108 | /* List of local ESs */ |
109 | struct list *local_es_evi_list; | |
50f74cf1 | 110 | |
96244aca | 111 | QOBJ_FIELDS; |
50f74cf1 | 112 | }; |
113 | ||
96244aca | 114 | DECLARE_QOBJ_TYPE(bgpevpn); |
50f74cf1 | 115 | |
a4168ebc | 116 | /* Mapping of Import RT to VNIs. |
117 | * The Import RTs of all VNIs are maintained in a hash table with each | |
118 | * RT linking to all VNIs that will import routes matching this RT. | |
119 | */ | |
d62a17ae | 120 | struct irt_node { |
121 | /* RT */ | |
122 | struct ecommunity_val rt; | |
a4168ebc | 123 | |
d62a17ae | 124 | /* List of VNIs importing routes matching this RT. */ |
125 | struct list *vnis; | |
a4168ebc | 126 | }; |
127 | ||
10ebe1ab MK |
128 | /* Mapping of Import RT to VRFs. |
129 | * The Import RTs of all VRFss are maintained in a hash table with each | |
130 | * RT linking to all VRFs that will import routes matching this RT. | |
131 | */ | |
132 | struct vrf_irt_node { | |
133 | /* RT */ | |
134 | struct ecommunity_val rt; | |
135 | ||
136 | /* List of VNIs importing routes matching this RT. */ | |
137 | struct list *vrfs; | |
138 | }; | |
139 | ||
140 | ||
128ea8ab | 141 | #define RT_TYPE_IMPORT 1 |
142 | #define RT_TYPE_EXPORT 2 | |
143 | #define RT_TYPE_BOTH 3 | |
144 | ||
85c8d83b CS |
145 | #define EVPN_DAD_DEFAULT_TIME 180 /* secs */ |
146 | #define EVPN_DAD_DEFAULT_MAX_MOVES 5 /* default from RFC 7432 */ | |
147 | #define EVPN_DAD_DEFAULT_AUTO_RECOVERY_TIME 1800 /* secs */ | |
148 | ||
149 | struct bgp_evpn_info { | |
150 | /* enable disable dup detect */ | |
151 | bool dup_addr_detect; | |
152 | ||
153 | /* Detection time(M) */ | |
154 | int dad_time; | |
155 | /* Detection max moves(N) */ | |
156 | uint32_t dad_max_moves; | |
157 | /* Permanent freeze */ | |
158 | bool dad_freeze; | |
159 | /* Recovery time */ | |
160 | uint32_t dad_freeze_time; | |
24864e44 CS |
161 | |
162 | /* EVPN enable - advertise svi macip routes */ | |
163 | int advertise_svi_macip; | |
164 | ||
5394a276 CS |
165 | /* PIP feature knob */ |
166 | bool advertise_pip; | |
167 | /* PIP IP (sys ip) */ | |
168 | struct in_addr pip_ip; | |
169 | struct in_addr pip_ip_static; | |
170 | /* PIP MAC (sys MAC) */ | |
171 | struct ethaddr pip_rmac; | |
172 | struct ethaddr pip_rmac_static; | |
173 | struct ethaddr pip_rmac_zebra; | |
174 | bool is_anycast_mac; | |
85c8d83b CS |
175 | }; |
176 | ||
021b6596 AD |
177 | /* This structure defines an entry in remote_ip_hash */ |
178 | struct evpn_remote_ip { | |
179 | struct ipaddr addr; | |
180 | struct list *macip_path_list; | |
181 | }; | |
182 | ||
ca337b46 SW |
183 | /* |
184 | * Wrapper struct for l3 RT's | |
185 | */ | |
186 | struct vrf_route_target { | |
187 | /* flags based on config to determine how RTs are handled */ | |
188 | uint8_t flags; | |
189 | #define BGP_VRF_RT_AUTO (1 << 0) | |
58d8948c | 190 | #define BGP_VRF_RT_WILD (1 << 1) |
ca337b46 SW |
191 | |
192 | struct ecommunity *ecom; | |
193 | }; | |
194 | ||
676f83b9 | 195 | static inline int is_vrf_rd_configured(struct bgp *bgp_vrf) |
196 | { | |
996c9314 | 197 | return (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD)); |
676f83b9 | 198 | } |
199 | ||
200 | static inline int bgp_evpn_vrf_rd_matches_existing(struct bgp *bgp_vrf, | |
201 | struct prefix_rd *prd) | |
202 | { | |
203 | return (memcmp(&bgp_vrf->vrf_prd.val, prd->val, ECOMMUNITY_SIZE) == 0); | |
204 | } | |
205 | ||
6d8c58b7 MK |
206 | static inline vni_t bgpevpn_get_l3vni(struct bgpevpn *vpn) |
207 | { | |
bc4606bd | 208 | return vpn->bgp_vrf ? vpn->bgp_vrf->l3vni : 0; |
6d8c58b7 MK |
209 | } |
210 | ||
211 | static inline void bgpevpn_get_rmac(struct bgpevpn *vpn, struct ethaddr *rmac) | |
212 | { | |
6d8c58b7 | 213 | memset(rmac, 0, sizeof(struct ethaddr)); |
bc4606bd | 214 | if (!vpn->bgp_vrf) |
6d8c58b7 | 215 | return; |
bc4606bd | 216 | memcpy(rmac, &vpn->bgp_vrf->rmac, sizeof(struct ethaddr)); |
6d8c58b7 MK |
217 | } |
218 | ||
219 | static inline struct list *bgpevpn_get_vrf_export_rtl(struct bgpevpn *vpn) | |
220 | { | |
bc4606bd | 221 | if (!vpn->bgp_vrf) |
6d8c58b7 MK |
222 | return NULL; |
223 | ||
bc4606bd | 224 | return vpn->bgp_vrf->vrf_export_rtl; |
6d8c58b7 MK |
225 | } |
226 | ||
227 | static inline struct list *bgpevpn_get_vrf_import_rtl(struct bgpevpn *vpn) | |
228 | { | |
bc4606bd | 229 | if (!vpn->bgp_vrf) |
6d8c58b7 MK |
230 | return NULL; |
231 | ||
bc4606bd | 232 | return vpn->bgp_vrf->vrf_import_rtl; |
6d8c58b7 MK |
233 | } |
234 | ||
c589d847 AK |
235 | extern void bgp_evpn_es_evi_vrf_ref(struct bgpevpn *vpn); |
236 | extern void bgp_evpn_es_evi_vrf_deref(struct bgpevpn *vpn); | |
237 | ||
6a8657d0 MK |
238 | static inline void bgpevpn_unlink_from_l3vni(struct bgpevpn *vpn) |
239 | { | |
bc4606bd MK |
240 | /* bail if vpn is not associated to bgp_vrf */ |
241 | if (!vpn->bgp_vrf) | |
6a8657d0 | 242 | return; |
996c9314 | 243 | |
c48d9f5f | 244 | UNSET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS); |
bc4606bd | 245 | listnode_delete(vpn->bgp_vrf->l2vnis, vpn); |
996c9314 | 246 | |
c589d847 AK |
247 | bgp_evpn_es_evi_vrf_deref(vpn); |
248 | ||
bc4606bd | 249 | /* remove the backpointer to the vrf instance */ |
0c68e088 | 250 | bgp_unlock(vpn->bgp_vrf); |
bc4606bd | 251 | vpn->bgp_vrf = NULL; |
6a8657d0 MK |
252 | } |
253 | ||
254 | static inline void bgpevpn_link_to_l3vni(struct bgpevpn *vpn) | |
255 | { | |
256 | struct bgp *bgp_vrf = NULL; | |
257 | ||
bc4606bd MK |
258 | /* bail if vpn is already associated to vrf */ |
259 | if (vpn->bgp_vrf) | |
260 | return; | |
261 | ||
6a8657d0 | 262 | bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id); |
c48d9f5f | 263 | if (!bgp_vrf) |
6a8657d0 | 264 | return; |
c48d9f5f | 265 | |
bc4606bd | 266 | /* associate the vpn to the bgp_vrf instance */ |
0c68e088 | 267 | vpn->bgp_vrf = bgp_lock(bgp_vrf); |
6a8657d0 | 268 | listnode_add_sort(bgp_vrf->l2vnis, vpn); |
83ea2eb0 | 269 | |
10f70510 AD |
270 | /* |
271 | * If L3VNI is configured, | |
272 | * check if we are advertising two labels for this vpn | |
273 | */ | |
274 | if (bgp_vrf->l3vni && | |
275 | !CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)) | |
c48d9f5f | 276 | SET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS); |
c589d847 AK |
277 | |
278 | bgp_evpn_es_evi_vrf_ref(vpn); | |
6a8657d0 MK |
279 | } |
280 | ||
d62a17ae | 281 | static inline int is_vni_configured(struct bgpevpn *vpn) |
128ea8ab | 282 | { |
d62a17ae | 283 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_CFGD)); |
128ea8ab | 284 | } |
285 | ||
d62a17ae | 286 | static inline int is_vni_live(struct bgpevpn *vpn) |
128ea8ab | 287 | { |
d62a17ae | 288 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_LIVE)); |
128ea8ab | 289 | } |
290 | ||
3d0b43d7 | 291 | static inline int is_l3vni_live(struct bgp *bgp_vrf) |
292 | { | |
293 | return (bgp_vrf->l3vni && bgp_vrf->l3vni_svi_ifindex); | |
294 | } | |
295 | ||
d62a17ae | 296 | static inline int is_rd_configured(struct bgpevpn *vpn) |
128ea8ab | 297 | { |
d62a17ae | 298 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_RD_CFGD)); |
128ea8ab | 299 | } |
300 | ||
d62a17ae | 301 | static inline int bgp_evpn_rd_matches_existing(struct bgpevpn *vpn, |
302 | struct prefix_rd *prd) | |
128ea8ab | 303 | { |
d62a17ae | 304 | return (memcmp(&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0); |
128ea8ab | 305 | } |
306 | ||
d62a17ae | 307 | static inline int is_import_rt_configured(struct bgpevpn *vpn) |
128ea8ab | 308 | { |
d62a17ae | 309 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD)); |
128ea8ab | 310 | } |
311 | ||
d62a17ae | 312 | static inline int is_export_rt_configured(struct bgpevpn *vpn) |
128ea8ab | 313 | { |
d62a17ae | 314 | return (CHECK_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD)); |
128ea8ab | 315 | } |
316 | ||
50f74cf1 | 317 | static inline void encode_es_rt_extcomm(struct ecommunity_val *eval, |
318 | struct ethaddr *mac) | |
319 | { | |
320 | memset(eval, 0, sizeof(struct ecommunity_val)); | |
321 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
322 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT; | |
323 | memcpy(&eval->val[2], mac, ETH_ALEN); | |
324 | } | |
325 | ||
74e2bd89 AK |
326 | static inline void encode_df_elect_extcomm(struct ecommunity_val *eval, |
327 | uint16_t pref) | |
328 | { | |
329 | memset(eval, 0, sizeof(*eval)); | |
330 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
331 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION; | |
332 | eval->val[2] = EVPN_MH_DF_ALG_PREF; | |
333 | eval->val[6] = (pref >> 8) & 0xff; | |
334 | eval->val[7] = pref & 0xff; | |
335 | } | |
336 | ||
c44ab6f1 AK |
337 | static inline void encode_esi_label_extcomm(struct ecommunity_val *eval, |
338 | bool single_active) | |
339 | { | |
340 | memset(eval, 0, sizeof(struct ecommunity_val)); | |
341 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
342 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL; | |
343 | if (single_active) | |
344 | eval->val[2] |= (1 << 0); | |
345 | } | |
346 | ||
bc59a672 MK |
347 | static inline void encode_rmac_extcomm(struct ecommunity_val *eval, |
348 | struct ethaddr *rmac) | |
349 | { | |
350 | memset(eval, 0, sizeof(*eval)); | |
351 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
352 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; | |
353 | memcpy(&eval->val[2], rmac, ETH_ALEN); | |
354 | } | |
355 | ||
ead40654 MK |
356 | static inline void encode_default_gw_extcomm(struct ecommunity_val *eval) |
357 | { | |
358 | memset(eval, 0, sizeof(*eval)); | |
359 | eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE; | |
360 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_DEF_GW; | |
361 | } | |
362 | ||
d7c0a89a | 363 | static inline void encode_mac_mobility_extcomm(int static_mac, uint32_t seq, |
d62a17ae | 364 | struct ecommunity_val *eval) |
128ea8ab | 365 | { |
d62a17ae | 366 | memset(eval, 0, sizeof(*eval)); |
367 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
368 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY; | |
369 | if (static_mac) | |
370 | eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY; | |
371 | eval->val[4] = (seq >> 24) & 0xff; | |
372 | eval->val[5] = (seq >> 16) & 0xff; | |
373 | eval->val[6] = (seq >> 8) & 0xff; | |
374 | eval->val[7] = seq & 0xff; | |
128ea8ab | 375 | } |
376 | ||
68e33151 | 377 | static inline void encode_na_flag_extcomm(struct ecommunity_val *eval, |
9c7edc03 | 378 | uint8_t na_flag, bool proxy) |
68e33151 CS |
379 | { |
380 | memset(eval, 0, sizeof(*eval)); | |
381 | eval->val[0] = ECOMMUNITY_ENCODE_EVPN; | |
382 | eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ND; | |
383 | if (na_flag) | |
384 | eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG; | |
9c7edc03 AK |
385 | if (proxy) |
386 | eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG; | |
68e33151 CS |
387 | } |
388 | ||
bd494ec5 | 389 | static inline void ip_prefix_from_type5_prefix(const struct prefix_evpn *evp, |
90264d64 MK |
390 | struct prefix *ip) |
391 | { | |
392 | memset(ip, 0, sizeof(struct prefix)); | |
3714a385 | 393 | if (is_evpn_prefix_ipaddr_v4(evp)) { |
90264d64 | 394 | ip->family = AF_INET; |
3714a385 | 395 | ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length; |
396 | memcpy(&(ip->u.prefix4), &(evp->prefix.prefix_addr.ip.ip), | |
90264d64 | 397 | IPV4_MAX_BYTELEN); |
3714a385 | 398 | } else if (is_evpn_prefix_ipaddr_v6(evp)) { |
90264d64 | 399 | ip->family = AF_INET6; |
3714a385 | 400 | ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length; |
401 | memcpy(&(ip->u.prefix6), &(evp->prefix.prefix_addr.ip.ip), | |
90264d64 MK |
402 | IPV6_MAX_BYTELEN); |
403 | } | |
404 | } | |
405 | ||
123214ef | 406 | static inline int is_evpn_prefix_default(const struct prefix *evp) |
6fb219da MK |
407 | { |
408 | if (evp->family != AF_EVPN) | |
409 | return 0; | |
410 | ||
3714a385 | 411 | return ((evp->u.prefix_evpn.prefix_addr.ip_prefix_length == 0) ? |
412 | 1 : 0); | |
6fb219da MK |
413 | } |
414 | ||
bd494ec5 | 415 | static inline void ip_prefix_from_type2_prefix(const struct prefix_evpn *evp, |
d3135ba3 | 416 | struct prefix *ip) |
417 | { | |
418 | memset(ip, 0, sizeof(struct prefix)); | |
3714a385 | 419 | if (is_evpn_prefix_ipaddr_v4(evp)) { |
d3135ba3 | 420 | ip->family = AF_INET; |
421 | ip->prefixlen = IPV4_MAX_BITLEN; | |
3714a385 | 422 | memcpy(&(ip->u.prefix4), &(evp->prefix.macip_addr.ip.ip), |
d3135ba3 | 423 | IPV4_MAX_BYTELEN); |
3714a385 | 424 | } else if (is_evpn_prefix_ipaddr_v6(evp)) { |
d3135ba3 | 425 | ip->family = AF_INET6; |
426 | ip->prefixlen = IPV6_MAX_BITLEN; | |
3714a385 | 427 | memcpy(&(ip->u.prefix6), &(evp->prefix.macip_addr.ip.ip), |
d3135ba3 | 428 | IPV6_MAX_BYTELEN); |
429 | } | |
430 | } | |
431 | ||
bd494ec5 | 432 | static inline void ip_prefix_from_evpn_prefix(const struct prefix_evpn *evp, |
3714a385 | 433 | struct prefix *ip) |
434 | { | |
435 | if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) | |
436 | ip_prefix_from_type2_prefix(evp, ip); | |
437 | else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) | |
438 | ip_prefix_from_type5_prefix(evp, ip); | |
439 | } | |
440 | ||
d62a17ae | 441 | static inline void build_evpn_type2_prefix(struct prefix_evpn *p, |
442 | struct ethaddr *mac, | |
443 | struct ipaddr *ip) | |
128ea8ab | 444 | { |
d62a17ae | 445 | memset(p, 0, sizeof(struct prefix_evpn)); |
b03b8898 | 446 | p->family = AF_EVPN; |
50f74cf1 | 447 | p->prefixlen = EVPN_ROUTE_PREFIXLEN; |
d62a17ae | 448 | p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; |
3714a385 | 449 | memcpy(&p->prefix.macip_addr.mac.octet, mac->octet, ETH_ALEN); |
450 | p->prefix.macip_addr.ip.ipa_type = IPADDR_NONE; | |
cabddbf5 | 451 | memcpy(&p->prefix.macip_addr.ip, ip, sizeof(*ip)); |
128ea8ab | 452 | } |
453 | ||
bd494ec5 DS |
454 | static inline void |
455 | build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp, | |
456 | const struct prefix *ip_prefix) | |
342dd0c6 | 457 | { |
458 | struct ipaddr ip; | |
459 | ||
460 | memset(&ip, 0, sizeof(struct ipaddr)); | |
461 | if (ip_prefix->family == AF_INET) { | |
462 | ip.ipa_type = IPADDR_V4; | |
463 | memcpy(&ip.ipaddr_v4, &ip_prefix->u.prefix4, | |
464 | sizeof(struct in_addr)); | |
465 | } else { | |
466 | ip.ipa_type = IPADDR_V6; | |
467 | memcpy(&ip.ipaddr_v6, &ip_prefix->u.prefix6, | |
468 | sizeof(struct in6_addr)); | |
469 | } | |
470 | ||
471 | memset(evp, 0, sizeof(struct prefix_evpn)); | |
472 | evp->family = AF_EVPN; | |
50f74cf1 | 473 | evp->prefixlen = EVPN_ROUTE_PREFIXLEN; |
342dd0c6 | 474 | evp->prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE; |
3714a385 | 475 | evp->prefix.prefix_addr.ip_prefix_length = ip_prefix->prefixlen; |
476 | evp->prefix.prefix_addr.ip.ipa_type = ip.ipa_type; | |
477 | memcpy(&evp->prefix.prefix_addr.ip, &ip, sizeof(struct ipaddr)); | |
342dd0c6 | 478 | } |
479 | ||
d62a17ae | 480 | static inline void build_evpn_type3_prefix(struct prefix_evpn *p, |
481 | struct in_addr originator_ip) | |
128ea8ab | 482 | { |
d62a17ae | 483 | memset(p, 0, sizeof(struct prefix_evpn)); |
b03b8898 | 484 | p->family = AF_EVPN; |
50f74cf1 | 485 | p->prefixlen = EVPN_ROUTE_PREFIXLEN; |
d62a17ae | 486 | p->prefix.route_type = BGP_EVPN_IMET_ROUTE; |
3714a385 | 487 | p->prefix.imet_addr.ip.ipa_type = IPADDR_V4; |
488 | p->prefix.imet_addr.ip.ipaddr_v4 = originator_ip; | |
128ea8ab | 489 | } |
490 | ||
50f74cf1 | 491 | static inline void build_evpn_type4_prefix(struct prefix_evpn *p, |
492 | esi_t *esi, | |
493 | struct in_addr originator_ip) | |
494 | { | |
495 | memset(p, 0, sizeof(struct prefix_evpn)); | |
496 | p->family = AF_EVPN; | |
497 | p->prefixlen = EVPN_ROUTE_PREFIXLEN; | |
498 | p->prefix.route_type = BGP_EVPN_ES_ROUTE; | |
499 | p->prefix.es_addr.ip_prefix_length = IPV4_MAX_BITLEN; | |
500 | p->prefix.es_addr.ip.ipa_type = IPADDR_V4; | |
501 | p->prefix.es_addr.ip.ipaddr_v4 = originator_ip; | |
502 | memcpy(&p->prefix.es_addr.esi, esi, sizeof(esi_t)); | |
503 | } | |
504 | ||
c44ab6f1 AK |
505 | static inline void build_evpn_type1_prefix(struct prefix_evpn *p, |
506 | uint32_t eth_tag, | |
507 | esi_t *esi, | |
508 | struct in_addr originator_ip) | |
509 | { | |
510 | memset(p, 0, sizeof(struct prefix_evpn)); | |
511 | p->family = AF_EVPN; | |
512 | p->prefixlen = EVPN_ROUTE_PREFIXLEN; | |
513 | p->prefix.route_type = BGP_EVPN_AD_ROUTE; | |
514 | p->prefix.ead_addr.eth_tag = eth_tag; | |
c44ab6f1 AK |
515 | p->prefix.ead_addr.ip.ipa_type = IPADDR_V4; |
516 | p->prefix.ead_addr.ip.ipaddr_v4 = originator_ip; | |
517 | memcpy(&p->prefix.ead_addr.esi, esi, sizeof(esi_t)); | |
518 | } | |
519 | ||
520 | static inline void evpn_type1_prefix_global_copy(struct prefix_evpn *global_p, | |
521 | const struct prefix_evpn *vni_p) | |
522 | { | |
523 | memcpy(global_p, vni_p, sizeof(*global_p)); | |
c44ab6f1 | 524 | global_p->prefix.ead_addr.ip.ipa_type = 0; |
3a6290bd | 525 | global_p->prefix.ead_addr.ip.ipaddr_v4.s_addr = INADDR_ANY; |
7b0db0e4 | 526 | global_p->prefix.ead_addr.frag_id = 0; |
c44ab6f1 AK |
527 | } |
528 | ||
529 | /* EAD prefix in the global table doesn't include the VTEP-IP so | |
530 | * we need to create a different copy for the VNI | |
531 | */ | |
852d9f97 SW |
532 | static inline struct prefix_evpn * |
533 | evpn_type1_prefix_vni_ip_copy(struct prefix_evpn *vni_p, | |
534 | const struct prefix_evpn *global_p, | |
535 | struct in_addr originator_ip) | |
c44ab6f1 AK |
536 | { |
537 | memcpy(vni_p, global_p, sizeof(*vni_p)); | |
c44ab6f1 AK |
538 | vni_p->prefix.ead_addr.ip.ipa_type = IPADDR_V4; |
539 | vni_p->prefix.ead_addr.ip.ipaddr_v4 = originator_ip; | |
540 | ||
541 | return vni_p; | |
542 | } | |
543 | ||
852d9f97 SW |
544 | static inline void evpn_type2_prefix_global_copy( |
545 | struct prefix_evpn *global_p, const struct prefix_evpn *vni_p, | |
546 | const struct ethaddr *mac, const struct ipaddr *ip) | |
34c7f35f SW |
547 | { |
548 | memcpy(global_p, vni_p, sizeof(*global_p)); | |
852d9f97 SW |
549 | |
550 | if (mac) | |
551 | global_p->prefix.macip_addr.mac = *mac; | |
552 | ||
553 | if (ip) | |
554 | global_p->prefix.macip_addr.ip = *ip; | |
34c7f35f SW |
555 | } |
556 | ||
557 | static inline void | |
852d9f97 SW |
558 | evpn_type2_prefix_vni_ip_copy(struct prefix_evpn *vni_p, |
559 | const struct prefix_evpn *global_p) | |
34c7f35f SW |
560 | { |
561 | memcpy(vni_p, global_p, sizeof(*vni_p)); | |
562 | memset(&vni_p->prefix.macip_addr.mac, 0, sizeof(struct ethaddr)); | |
563 | } | |
564 | ||
852d9f97 SW |
565 | static inline void |
566 | evpn_type2_prefix_vni_mac_copy(struct prefix_evpn *vni_p, | |
567 | const struct prefix_evpn *global_p) | |
568 | { | |
569 | memcpy(vni_p, global_p, sizeof(*vni_p)); | |
570 | memset(&vni_p->prefix.macip_addr.ip, 0, sizeof(struct ipaddr)); | |
571 | } | |
572 | ||
34c7f35f SW |
573 | /* Get MAC of path_info prefix */ |
574 | static inline struct ethaddr * | |
575 | evpn_type2_path_info_get_mac(const struct bgp_path_info *local_pi) | |
576 | { | |
577 | assert(local_pi->extra); | |
852d9f97 SW |
578 | return &local_pi->extra->vni_info.mac; |
579 | } | |
580 | ||
581 | /* Get IP of path_info prefix */ | |
582 | static inline struct ipaddr * | |
583 | evpn_type2_path_info_get_ip(const struct bgp_path_info *local_pi) | |
584 | { | |
585 | assert(local_pi->extra); | |
586 | return &local_pi->extra->vni_info.ip; | |
34c7f35f SW |
587 | } |
588 | ||
589 | /* Set MAC of path_info prefix */ | |
590 | static inline void evpn_type2_path_info_set_mac(struct bgp_path_info *local_pi, | |
591 | const struct ethaddr mac) | |
592 | { | |
593 | assert(local_pi->extra); | |
852d9f97 SW |
594 | local_pi->extra->vni_info.mac = mac; |
595 | } | |
596 | ||
597 | /* Set IP of path_info prefix */ | |
598 | static inline void evpn_type2_path_info_set_ip(struct bgp_path_info *local_pi, | |
599 | const struct ipaddr ip) | |
600 | { | |
601 | assert(local_pi->extra); | |
602 | local_pi->extra->vni_info.ip = ip; | |
603 | } | |
604 | ||
605 | /* Is the IP empty for the RT's dest? */ | |
606 | static inline bool is_evpn_type2_dest_ipaddr_none(const struct bgp_dest *dest) | |
607 | { | |
608 | const struct prefix_evpn *evp = | |
609 | (const struct prefix_evpn *)bgp_dest_get_prefix(dest); | |
610 | ||
611 | assert(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE); | |
612 | return is_evpn_prefix_ipaddr_none(evp); | |
34c7f35f SW |
613 | } |
614 | ||
486456ca MK |
615 | static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi, |
616 | safi_t safi) | |
617 | { | |
618 | if (afi == AFI_IP && | |
619 | CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], | |
620 | BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4)) | |
621 | return 1; | |
622 | else if (afi == AFI_IP6 && | |
623 | CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], | |
624 | BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6)) | |
625 | return 1; | |
626 | return 0; | |
627 | } | |
628 | ||
50f74cf1 | 629 | static inline void es_get_system_mac(esi_t *esi, |
630 | struct ethaddr *mac) | |
631 | { | |
2bb9eff4 DS |
632 | /* |
633 | * for type-1 and type-3 ESIs, | |
634 | * the system mac starts at val[1] | |
50f74cf1 | 635 | */ |
636 | memcpy(mac, &esi->val[1], ETH_ALEN); | |
637 | } | |
638 | ||
0ca10580 CS |
639 | static inline bool bgp_evpn_is_svi_macip_enabled(struct bgpevpn *vpn) |
640 | { | |
641 | struct bgp *bgp_evpn = NULL; | |
642 | ||
643 | bgp_evpn = bgp_get_evpn(); | |
644 | ||
645 | return (bgp_evpn->evpn_info->advertise_svi_macip || | |
646 | vpn->advertise_svi_macip); | |
647 | } | |
648 | ||
9c7edc03 AK |
649 | static inline bool bgp_evpn_is_path_local(struct bgp *bgp, |
650 | struct bgp_path_info *pi) | |
651 | { | |
652 | return (pi->peer == bgp->peer_self | |
653 | && pi->type == ZEBRA_ROUTE_BGP | |
654 | && pi->sub_type == BGP_ROUTE_STATIC); | |
655 | } | |
656 | ||
c44ab6f1 AK |
657 | extern struct zclient *zclient; |
658 | ||
5fd9c12b KA |
659 | extern void bgp_evpn_install_uninstall_default_route(struct bgp *bgp_vrf, |
660 | afi_t afi, safi_t safi, | |
661 | bool add); | |
ca337b46 SW |
662 | extern void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, struct list *rtl, |
663 | bool is_l3); | |
523cafc4 | 664 | extern void bgp_evpn_configure_export_rt_for_vrf(struct bgp *bgp_vrf, |
665 | struct ecommunity *ecomadd); | |
58d8948c | 666 | extern void bgp_evpn_configure_export_auto_rt_for_vrf(struct bgp *bgp_vrf); |
523cafc4 | 667 | extern void bgp_evpn_unconfigure_export_rt_for_vrf(struct bgp *bgp_vrf, |
668 | struct ecommunity *ecomdel); | |
58d8948c | 669 | extern void bgp_evpn_unconfigure_export_auto_rt_for_vrf(struct bgp *bgp_vrf); |
523cafc4 | 670 | extern void bgp_evpn_configure_import_rt_for_vrf(struct bgp *bgp_vrf, |
58d8948c SW |
671 | struct ecommunity *ecomadd, |
672 | bool is_wildcard); | |
673 | extern void bgp_evpn_configure_import_auto_rt_for_vrf(struct bgp *bgp_vrf); | |
523cafc4 | 674 | extern void bgp_evpn_unconfigure_import_rt_for_vrf(struct bgp *bgp_vrf, |
675 | struct ecommunity *ecomdel); | |
58d8948c | 676 | extern void bgp_evpn_unconfigure_import_auto_rt_for_vrf(struct bgp *bgp_vrf); |
d62a17ae | 677 | extern int bgp_evpn_handle_export_rt_change(struct bgp *bgp, |
678 | struct bgpevpn *vpn); | |
bf1061d8 | 679 | extern void bgp_evpn_handle_autort_change(struct bgp *bgp); |
676f83b9 | 680 | extern void bgp_evpn_handle_vrf_rd_change(struct bgp *bgp_vrf, int withdraw); |
d62a17ae | 681 | extern void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn, |
682 | int withdraw); | |
683 | extern int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn); | |
684 | extern int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn); | |
523cafc4 | 685 | extern void bgp_evpn_map_vrf_to_its_rts(struct bgp *bgp_vrf); |
686 | extern void bgp_evpn_unmap_vrf_from_its_rts(struct bgp *bgp_vrf); | |
d62a17ae | 687 | extern void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn); |
688 | extern void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp, | |
689 | struct bgpevpn *vpn); | |
690 | extern void bgp_evpn_derive_auto_rt_import(struct bgp *bgp, | |
691 | struct bgpevpn *vpn); | |
692 | extern void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, | |
693 | struct bgpevpn *vpn); | |
694 | extern void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn); | |
676f83b9 | 695 | extern void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp); |
d62a17ae | 696 | extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni); |
697 | extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, | |
76d07c7a AK |
698 | struct in_addr originator_ip, |
699 | vrf_id_t tenant_vrf_id, | |
9daa5d47 AD |
700 | struct in_addr mcast_grp, |
701 | ifindex_t svi_ifindex); | |
d62a17ae | 702 | extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn); |
7df407ed | 703 | extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni); |
0ca10580 | 704 | extern int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn); |
185fb14a AK |
705 | extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi, |
706 | struct bgp_dest *dest, | |
707 | struct bgp_path_info **pi); | |
c44ab6f1 AK |
708 | int vni_list_cmp(void *p1, void *p2); |
709 | extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, | |
09319b4e | 710 | struct bgp_dest *dest); |
09319b4e | 711 | extern struct bgp_dest * |
34c7f35f SW |
712 | bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi, |
713 | const struct prefix_evpn *evp, struct prefix_rd *prd, | |
714 | const struct bgp_path_info *local_pi); | |
0da34e49 DA |
715 | extern struct bgp_dest *bgp_evpn_global_node_lookup( |
716 | struct bgp_table *table, safi_t safi, const struct prefix_evpn *evp, | |
717 | struct prefix_rd *prd, const struct bgp_path_info *local_pi); | |
34c7f35f | 718 | extern struct bgp_dest * |
852d9f97 SW |
719 | bgp_evpn_vni_ip_node_get(struct bgp_table *const table, |
720 | const struct prefix_evpn *evp, | |
721 | const struct bgp_path_info *parent_pi); | |
722 | extern struct bgp_dest * | |
723 | bgp_evpn_vni_ip_node_lookup(const struct bgp_table *const table, | |
26c03e43 | 724 | const struct prefix_evpn *evp, |
852d9f97 SW |
725 | const struct bgp_path_info *parent_pi); |
726 | extern struct bgp_dest * | |
727 | bgp_evpn_vni_mac_node_get(struct bgp_table *const table, | |
728 | const struct prefix_evpn *evp, | |
729 | const struct bgp_path_info *parent_pi); | |
730 | extern struct bgp_dest * | |
731 | bgp_evpn_vni_mac_node_lookup(const struct bgp_table *const table, | |
732 | const struct prefix_evpn *evp, | |
733 | const struct bgp_path_info *parent_pi); | |
734 | extern struct bgp_dest * | |
735 | bgp_evpn_vni_node_get(struct bgpevpn *vpn, const struct prefix_evpn *p, | |
34c7f35f SW |
736 | const struct bgp_path_info *parent_pi); |
737 | extern struct bgp_dest * | |
852d9f97 | 738 | bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn, const struct prefix_evpn *p, |
34c7f35f | 739 | const struct bgp_path_info *parent_pi); |
852d9f97 | 740 | |
34c7f35f | 741 | extern void bgp_evpn_import_route_in_vrfs(struct bgp_path_info *pi, int import); |
70524092 AK |
742 | extern void bgp_evpn_update_type2_route_entry(struct bgp *bgp, |
743 | struct bgpevpn *vpn, | |
744 | struct bgp_node *rn, | |
745 | struct bgp_path_info *local_pi, | |
746 | const char *caller); | |
58bff4d1 AK |
747 | extern int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf, |
748 | struct bgp_path_info *pi, | |
749 | int install); | |
74efb822 | 750 | extern void bgp_evpn_import_type2_route(struct bgp_path_info *pi, int import); |
f4a5218d AK |
751 | extern void bgp_evpn_xxport_delete_ecomm(void *val); |
752 | extern int bgp_evpn_route_target_cmp(struct ecommunity *ecom1, | |
753 | struct ecommunity *ecom2); | |
a4168ebc | 754 | #endif /* _BGP_EVPN_PRIVATE_H */ |