]>
Commit | Line | Data |
---|---|---|
185fb14a AK |
1 | /* EVPN header for multihoming procedures |
2 | * | |
3 | * Copyright (C) 2019 Cumulus Networks | |
c44ab6f1 | 4 | * Anuradha Karuppiah |
185fb14a AK |
5 | * |
6 | * This file is part of FRRouting. | |
7 | * | |
8 | * FRRouting is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2, or (at your option) any | |
11 | * later version. | |
12 | * | |
13 | * FRRouting is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | */ | |
19 | ||
20 | #ifndef _FRR_BGP_EVPN_MH_H | |
21 | #define _FRR_BGP_EVPN_MH_H | |
22 | ||
23 | #include "vxlan.h" | |
24 | #include "bgpd.h" | |
25 | #include "bgp_evpn.h" | |
26 | #include "bgp_evpn_private.h" | |
27 | ||
c44ab6f1 AK |
28 | #define BGP_EVPN_AD_ES_ETH_TAG 0xffffffff |
29 | #define BGP_EVPN_AD_EVI_ETH_TAG 0 | |
30 | ||
31 | #define BGP_EVPNES_INCONS_STR_SZ 80 | |
32 | #define BGP_EVPN_FLAG_STR_SZ 5 | |
33 | #define BGP_EVPN_VTEPS_FLAG_STR_SZ (BGP_EVPN_FLAG_STR_SZ * ES_VTEP_MAX_CNT) | |
34 | ||
35 | #define BGP_EVPN_CONS_CHECK_INTERVAL 60 | |
36 | ||
37 | ||
38 | /* Ethernet Segment entry - | |
39 | * - Local and remote ESs are maintained in a global RB tree, | |
40 | * bgp_mh_info->es_rb_tree using ESI as key | |
41 | * - Local ESs are received from zebra (BGP_EVPNES_LOCAL) | |
42 | * - Remotes ESs are implicitly created (by reference) by a remote ES-EVI | |
43 | * (BGP_EVPNES_REMOTE) | |
44 | * - An ES can be simulatenously LOCAL and REMOTE; infact all LOCAL ESs are | |
45 | * expected to have REMOTE ES peers. | |
46 | */ | |
47 | struct bgp_evpn_es { | |
48 | /* Ethernet Segment Identifier */ | |
49 | esi_t esi; | |
50 | char esi_str[ESI_STR_LEN]; | |
51 | ||
52 | /* es flags */ | |
53 | uint32_t flags; | |
54 | /* created via zebra config */ | |
55 | #define BGP_EVPNES_LOCAL (1 << 0) | |
56 | /* created implicitly by a remote ES-EVI reference */ | |
57 | #define BGP_EVPNES_REMOTE (1 << 1) | |
58 | /* local ES link is oper-up */ | |
59 | #define BGP_EVPNES_OPER_UP (1 << 2) | |
60 | /* enable generation of EAD-EVI routes */ | |
61 | #define BGP_EVPNES_ADV_EVI (1 << 3) | |
62 | /* consistency checks pending */ | |
63 | #define BGP_EVPNES_CONS_CHECK_PEND (1 << 4) | |
64 | ||
65 | /* memory used for adding the es to bgp->es_rb_tree */ | |
66 | RB_ENTRY(bgp_evpn_es) rb_node; | |
67 | ||
68 | /* [EVPNES_LOCAL] memory used for linking the es to | |
69 | * bgp_mh_info->local_es_list | |
70 | */ | |
71 | struct listnode es_listnode; | |
72 | ||
73 | /* memory used for linking the es to "processing" pending list | |
74 | * bgp_mh_info->pend_es_list | |
75 | */ | |
76 | struct listnode pend_es_listnode; | |
77 | ||
78 | /* [EVPNES_LOCAL] Id for deriving the RD automatically for this ESI */ | |
79 | uint16_t rd_id; | |
80 | ||
81 | /* [EVPNES_LOCAL] RD for this ES */ | |
82 | struct prefix_rd prd; | |
83 | ||
84 | /* [EVPNES_LOCAL] originator ip address */ | |
85 | struct in_addr originator_ip; | |
86 | ||
87 | /* [EVPNES_LOCAL] Route table for EVPN routes for this ESI- | |
88 | * - Type-4 local and remote routes | |
89 | * - Type-1 local routes | |
90 | */ | |
91 | struct bgp_table *route_table; | |
92 | ||
93 | /* list of PEs (bgp_evpn_es_vtep) attached to the ES */ | |
94 | struct list *es_vtep_list; | |
95 | ||
96 | /* List of ES-EVIs associated with this ES */ | |
97 | struct list *es_evi_list; | |
98 | ||
c589d847 AK |
99 | /* List of ES-VRFs associated with this ES */ |
100 | struct list *es_vrf_list; | |
101 | ||
26c03e43 AK |
102 | /* List of MAC-IP global routes using this ES as destination - |
103 | * element is bgp_path_info_extra->es_info | |
104 | */ | |
105 | struct list *macip_path_list; | |
106 | ||
c44ab6f1 AK |
107 | /* Number of remote VNIs referencing this ES */ |
108 | uint32_t remote_es_evi_cnt; | |
109 | ||
110 | uint32_t inconsistencies; | |
111 | /* there are one or more EVIs whose VTEP list doesn't match | |
112 | * with the ES's VTEP list | |
113 | */ | |
114 | #define BGP_EVPNES_INCONS_VTEP_LIST (1 << 0) | |
115 | ||
116 | /* number of es-evi entries whose VTEP list doesn't match | |
117 | * with the ES's | |
118 | */ | |
119 | uint32_t incons_evi_vtep_cnt; | |
120 | ||
74e2bd89 AK |
121 | /* preference config for BUM-DF election. advertised via the ESR. */ |
122 | uint16_t df_pref; | |
123 | ||
c44ab6f1 AK |
124 | QOBJ_FIELDS |
125 | }; | |
126 | DECLARE_QOBJ_TYPE(bgp_evpn_es) | |
127 | RB_HEAD(bgp_es_rb_head, bgp_evpn_es); | |
128 | RB_PROTOTYPE(bgp_es_rb_head, bgp_evpn_es, rb_node, bgp_es_rb_cmp); | |
129 | ||
130 | /* PE attached to an ES */ | |
131 | struct bgp_evpn_es_vtep { | |
132 | struct bgp_evpn_es *es; /* parent ES */ | |
133 | struct in_addr vtep_ip; | |
134 | ||
135 | uint32_t flags; | |
136 | /* Rxed a Type4 route from this PE */ | |
137 | #define BGP_EVPNES_VTEP_ESR (1 << 0) | |
138 | /* Active (rxed EAD-ES and EAD-EVI) and can be included as | |
139 | * a nexthop | |
140 | */ | |
141 | #define BGP_EVPNES_VTEP_ACTIVE (1 << 1) | |
142 | ||
143 | uint32_t evi_cnt; /* es_evis referencing this vtep as an active path */ | |
144 | ||
74e2bd89 AK |
145 | /* Algorithm and preference for DF election. Rxed via the ESR */ |
146 | uint8_t df_alg; | |
147 | uint16_t df_pref; | |
148 | ||
c44ab6f1 AK |
149 | /* memory used for adding the entry to es->es_vtep_list */ |
150 | struct listnode es_listnode; | |
151 | }; | |
152 | ||
c589d847 AK |
153 | /* ES-VRF element needed for managing L3 NHGs. It is implicitly created |
154 | * when an ES-EVI is associated with a tenant VRF | |
155 | */ | |
156 | struct bgp_evpn_es_vrf { | |
157 | struct bgp_evpn_es *es; | |
158 | struct bgp *bgp_vrf; | |
159 | ||
160 | uint32_t flags; | |
161 | /* NHG can only be activated if there are active VTEPs in the ES and | |
162 | * there is a valid L3-VNI associated with the VRF | |
163 | */ | |
164 | #define BGP_EVPNES_VRF_NHG_ACTIVE (1 << 0) | |
165 | ||
166 | /* memory used for adding the es_vrf to | |
167 | * es_vrf->bgp_vrf->es_vrf_rb_tree | |
168 | */ | |
169 | RB_ENTRY(bgp_evpn_es_vrf) rb_node; | |
170 | ||
171 | /* memory used for linking the es_vrf to es_vrf->es->es_vrf_list */ | |
172 | struct listnode es_listnode; | |
173 | ||
174 | uint32_t nhg_id; | |
6348981a | 175 | uint32_t v6_nhg_id; |
c589d847 AK |
176 | |
177 | /* Number of ES-EVI entries associated with this ES-VRF */ | |
178 | uint32_t ref_cnt; | |
179 | }; | |
180 | ||
c44ab6f1 AK |
181 | /* ES per-EVI info |
182 | * - ES-EVIs are maintained per-L2-VNI (vpn->es_evi_rb_tree) | |
183 | * - ES-EVIs are also linked to the parent ES (es->es_evi_list) | |
184 | * - Local ES-EVIs are created by zebra (via config). They are linked to a | |
185 | * per-VNI list (vpn->local_es_evi_list) for quick access | |
186 | * - Remote ES-EVIs are created implicitly when a bgp_evpn_es_evi_vtep | |
187 | * references it. | |
188 | */ | |
189 | struct bgp_evpn_es_evi { | |
190 | struct bgp_evpn_es *es; | |
191 | struct bgpevpn *vpn; | |
192 | ||
193 | /* ES-EVI flags */ | |
194 | uint32_t flags; | |
195 | /* local ES-EVI, created by zebra */ | |
196 | #define BGP_EVPNES_EVI_LOCAL (1 << 0) | |
197 | /* created via a remote VTEP imported by BGP */ | |
198 | #define BGP_EVPNES_EVI_REMOTE (1 << 1) | |
199 | #define BGP_EVPNES_EVI_INCONS_VTEP_LIST (1 << 2) | |
200 | ||
201 | /* memory used for adding the es_evi to es_evi->vpn->es_evi_rb_tree */ | |
202 | RB_ENTRY(bgp_evpn_es_evi) rb_node; | |
203 | /* memory used for linking the es_evi to | |
204 | * es_evi->vpn->local_es_evi_list | |
205 | */ | |
206 | struct listnode l2vni_listnode; | |
207 | /* memory used for linking the es_evi to | |
208 | * es_evi->es->es_evi_list | |
209 | */ | |
210 | struct listnode es_listnode; | |
211 | ||
212 | /* list of PEs (bgp_evpn_es_evi_vtep) attached to the ES for this VNI */ | |
213 | struct list *es_evi_vtep_list; | |
c589d847 AK |
214 | |
215 | struct bgp_evpn_es_vrf *es_vrf; | |
c44ab6f1 AK |
216 | }; |
217 | ||
218 | /* PE attached to an ES for a VNI. This entry is created when an EAD-per-ES | |
219 | * or EAD-per-EVI Type1 route is imported into the VNI. | |
220 | */ | |
221 | struct bgp_evpn_es_evi_vtep { | |
222 | struct bgp_evpn_es_evi *es_evi; /* parent ES-EVI */ | |
223 | struct in_addr vtep_ip; | |
224 | ||
225 | uint32_t flags; | |
226 | /* Rxed an EAD-per-ES route from the PE */ | |
227 | #define BGP_EVPN_EVI_VTEP_EAD_PER_ES (1 << 0) /* rxed EAD-per-ES */ | |
228 | /* Rxed an EAD-per-EVI route from the PE */ | |
229 | #define BGP_EVPN_EVI_VTEP_EAD_PER_EVI (1 << 1) /* rxed EAD-per-EVI */ | |
230 | /* VTEP is active i.e. will result in the creation of an es-vtep */ | |
231 | #define BGP_EVPN_EVI_VTEP_ACTIVE (1 << 2) | |
232 | #define BGP_EVPN_EVI_VTEP_EAD (BGP_EVPN_EVI_VTEP_EAD_PER_ES |\ | |
233 | BGP_EVPN_EVI_VTEP_EAD_PER_EVI) | |
234 | ||
235 | /* memory used for adding the entry to es_evi->es_evi_vtep_list */ | |
236 | struct listnode es_evi_listnode; | |
237 | struct bgp_evpn_es_vtep *es_vtep; | |
238 | }; | |
239 | ||
240 | /* multihoming information stored in bgp_master */ | |
241 | #define bgp_mh_info (bm->mh_info) | |
242 | struct bgp_evpn_mh_info { | |
243 | /* RB tree of Ethernet segments (used for EVPN-MH) */ | |
244 | struct bgp_es_rb_head es_rb_tree; | |
245 | /* List of local ESs */ | |
246 | struct list *local_es_list; | |
247 | /* List of ESs with pending/periodic processing */ | |
248 | struct list *pend_es_list; | |
249 | /* periodic timer for running background consistency checks */ | |
250 | struct thread *t_cons_check; | |
251 | ||
252 | /* config knobs for optimizing or interop */ | |
253 | /* Generate EAD-EVI routes even if the ES is oper-down. This can be | |
254 | * enabled as an optimization to avoid a storm of updates when an ES | |
255 | * link flaps. | |
256 | */ | |
257 | bool ead_evi_adv_for_down_links; | |
258 | /* Enable ES consistency checking */ | |
259 | bool consistency_checking; | |
6348981a | 260 | bool host_routes_use_l3nhg; |
c44ab6f1 AK |
261 | }; |
262 | ||
263 | /****************************************************************************/ | |
7904e9fd | 264 | static inline int bgp_evpn_is_es_local(struct bgp_evpn_es *es) |
c44ab6f1 AK |
265 | { |
266 | return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ? 1 : 0; | |
267 | } | |
268 | ||
269 | extern esi_t *zero_esi; | |
7904e9fd AK |
270 | static inline bool bgp_evpn_is_esi_valid(esi_t *esi) |
271 | { | |
272 | return !!memcmp(esi, zero_esi, sizeof(esi_t)); | |
273 | } | |
274 | ||
c44ab6f1 AK |
275 | static inline esi_t *bgp_evpn_attr_get_esi(struct attr *attr) |
276 | { | |
7904e9fd AK |
277 | return attr ? &attr->esi : zero_esi; |
278 | } | |
279 | ||
280 | static inline bool bgp_evpn_attr_is_sync(struct attr *attr) | |
281 | { | |
282 | return attr ? !!(attr->es_flags & | |
283 | (ATTR_ES_PEER_PROXY | ATTR_ES_PEER_ACTIVE)) : false; | |
284 | } | |
285 | ||
286 | static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr *attr) | |
287 | { | |
288 | return attr ? attr->mm_sync_seqnum : 0; | |
289 | } | |
290 | ||
291 | static inline bool bgp_evpn_attr_is_active_on_peer(struct attr *attr) | |
292 | { | |
293 | return attr ? | |
294 | !!(attr->es_flags & ATTR_ES_PEER_ACTIVE) : false; | |
295 | } | |
296 | ||
297 | static inline bool bgp_evpn_attr_is_router_on_peer(struct attr *attr) | |
298 | { | |
299 | return attr ? | |
300 | !!(attr->es_flags & ATTR_ES_PEER_ROUTER) : false; | |
301 | } | |
302 | ||
303 | static inline bool bgp_evpn_attr_is_proxy(struct attr *attr) | |
304 | { | |
305 | return attr ? !!(attr->es_flags & ATTR_ES_PROXY_ADVERT) : false; | |
306 | } | |
307 | ||
308 | static inline bool bgp_evpn_attr_is_local_es(struct attr *attr) | |
309 | { | |
310 | return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false; | |
c44ab6f1 AK |
311 | } |
312 | ||
74e2bd89 AK |
313 | static inline uint32_t bgp_evpn_attr_get_df_pref(struct attr *attr) |
314 | { | |
315 | return (attr) ? attr->df_pref : 0; | |
316 | } | |
317 | ||
c44ab6f1 AK |
318 | /****************************************************************************/ |
319 | extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp, | |
320 | struct bgp_evpn_es *es, afi_t afi, safi_t safi, | |
321 | struct prefix_evpn *evp, struct bgp_path_info *pi, | |
322 | int install); | |
323 | int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi, | |
324 | struct attr *attr, uint8_t *pfx, int psize, | |
325 | uint32_t addpath_id); | |
326 | int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi, | |
327 | struct attr *attr, uint8_t *pfx, int psize, | |
328 | uint32_t addpath_id); | |
185fb14a | 329 | extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, |
74e2bd89 AK |
330 | struct in_addr originator_ip, bool oper_up, |
331 | uint16_t df_pref); | |
c44ab6f1 AK |
332 | extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi); |
333 | extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni); | |
334 | extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni); | |
335 | extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, | |
336 | const struct prefix_evpn *p); | |
337 | extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, | |
338 | const struct prefix_evpn *p); | |
339 | extern void bgp_evpn_mh_init(void); | |
340 | extern void bgp_evpn_mh_finish(void); | |
341 | void bgp_evpn_vni_es_init(struct bgpevpn *vpn); | |
342 | void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn); | |
343 | void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj); | |
344 | void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail); | |
345 | void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni, | |
346 | bool uj, bool detail); | |
347 | void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail); | |
348 | struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi); | |
7904e9fd | 349 | extern bool bgp_evpn_is_esi_local(esi_t *esi); |
c589d847 AK |
350 | extern void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf); |
351 | extern void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi); | |
352 | extern void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi, | |
353 | struct bgp *bgp_vrf); | |
26c03e43 AK |
354 | extern void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info); |
355 | extern void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info); | |
356 | extern void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, | |
357 | esi_t *esi); | |
358 | extern bool bgp_evpn_es_is_vtep_active(esi_t *esi, struct in_addr nh); | |
6348981a AK |
359 | extern bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, |
360 | struct bgp_path_info *pi, uint32_t *nhg_p); | |
c44ab6f1 | 361 | |
185fb14a | 362 | #endif /* _FRR_BGP_EVPN_MH_H */ |