]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_mh.h
bgpd: Fix continue/break change from old commit
[mirror_frr.git] / bgpd / bgp_evpn_mh.h
1 /* EVPN header for multihoming procedures
2 *
3 * Copyright (C) 2019 Cumulus Networks
4 * Anuradha Karuppiah
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
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_VTEPS_FLAG_STR_SZ (BGP_EVPN_FLAG_STR_SZ * ES_VTEP_MAX_CNT)
33
34 #define BGP_EVPN_CONS_CHECK_INTERVAL 60
35
36 #define BGP_EVPN_MH_USE_ES_L3NHG_DEF true
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 /* ES is in LACP bypass mode - don't advertise EAD-ES or ESR */
65 #define BGP_EVPNES_BYPASS (1 << 5)
66 /* bits needed for printing the flags + null */
67 #define BGP_EVPN_FLAG_STR_SZ 7
68
69 /* memory used for adding the es to bgp->es_rb_tree */
70 RB_ENTRY(bgp_evpn_es) rb_node;
71
72 /* [EVPNES_LOCAL] memory used for linking the es to
73 * bgp_mh_info->local_es_list
74 */
75 struct listnode es_listnode;
76
77 /* memory used for linking the es to "processing" pending list
78 * bgp_mh_info->pend_es_list
79 */
80 struct listnode pend_es_listnode;
81
82 /* [EVPNES_LOCAL] Id for deriving the RD automatically for this ESI */
83 uint16_t rd_id;
84
85 /* [EVPNES_LOCAL] RD for this ES */
86 struct prefix_rd prd;
87
88 /* [EVPNES_LOCAL] originator ip address */
89 struct in_addr originator_ip;
90
91 /* [EVPNES_LOCAL] Route table for EVPN routes for this ESI-
92 * - Type-4 local and remote routes
93 * - Type-1 local routes
94 */
95 struct bgp_table *route_table;
96
97 /* list of PEs (bgp_evpn_es_vtep) attached to the ES */
98 struct list *es_vtep_list;
99
100 /* List of ES-EVIs associated with this ES */
101 struct list *es_evi_list;
102
103 /* List of ES-VRFs associated with this ES */
104 struct list *es_vrf_list;
105
106 /* List of MAC-IP VNI paths using this ES as destination -
107 * element is bgp_path_info_extra->es_info
108 * Note: Only local/zebra-added MACIP paths in the VNI
109 * routing table are linked to this list
110 */
111 struct list *macip_evi_path_list;
112
113 /* List of MAC-IP paths in the global routing table using this
114 * ES as destination - data is bgp_path_info_extra->es_info
115 * Note: Only non-local/imported MACIP paths in the global
116 * routing table are linked to this list
117 */
118 struct list *macip_global_path_list;
119
120 /* Number of remote VNIs referencing this ES */
121 uint32_t remote_es_evi_cnt;
122
123 uint32_t inconsistencies;
124 /* there are one or more EVIs whose VTEP list doesn't match
125 * with the ES's VTEP list
126 */
127 #define BGP_EVPNES_INCONS_VTEP_LIST (1 << 0)
128
129 /* number of es-evi entries whose VTEP list doesn't match
130 * with the ES's
131 */
132 uint32_t incons_evi_vtep_cnt;
133
134 /* preference config for BUM-DF election. advertised via the ESR. */
135 uint16_t df_pref;
136
137 QOBJ_FIELDS;
138 };
139 DECLARE_QOBJ_TYPE(bgp_evpn_es);
140 RB_HEAD(bgp_es_rb_head, bgp_evpn_es);
141 RB_PROTOTYPE(bgp_es_rb_head, bgp_evpn_es, rb_node, bgp_es_rb_cmp);
142
143 /* PE attached to an ES */
144 struct bgp_evpn_es_vtep {
145 struct bgp_evpn_es *es; /* parent ES */
146 struct in_addr vtep_ip;
147
148 char vtep_str[INET6_ADDRSTRLEN];
149
150 uint32_t flags;
151 /* Rxed a Type4 route from this PE */
152 #define BGP_EVPNES_VTEP_ESR (1 << 0)
153 /* Active (rxed EAD-ES and EAD-EVI) and can be included as
154 * a nexthop
155 */
156 #define BGP_EVPNES_VTEP_ACTIVE (1 << 1)
157
158 uint32_t evi_cnt; /* es_evis referencing this vtep as an active path */
159
160 /* Algorithm and preference for DF election. Rxed via the ESR */
161 uint8_t df_alg;
162 uint16_t df_pref;
163
164 /* memory used for adding the entry to es->es_vtep_list */
165 struct listnode es_listnode;
166 };
167
168 /* ES-VRF element needed for managing L3 NHGs. It is implicitly created
169 * when an ES-EVI is associated with a tenant VRF
170 */
171 struct bgp_evpn_es_vrf {
172 struct bgp_evpn_es *es;
173 struct bgp *bgp_vrf;
174
175 uint32_t flags;
176 /* NHG can only be activated if there are active VTEPs in the ES and
177 * there is a valid L3-VNI associated with the VRF
178 */
179 #define BGP_EVPNES_VRF_NHG_ACTIVE (1 << 0)
180
181 /* memory used for adding the es_vrf to
182 * es_vrf->bgp_vrf->es_vrf_rb_tree
183 */
184 RB_ENTRY(bgp_evpn_es_vrf) rb_node;
185
186 /* memory used for linking the es_vrf to es_vrf->es->es_vrf_list */
187 struct listnode es_listnode;
188
189 uint32_t nhg_id;
190 uint32_t v6_nhg_id;
191
192 /* Number of ES-EVI entries associated with this ES-VRF */
193 uint32_t ref_cnt;
194 };
195
196 /* ES per-EVI info
197 * - ES-EVIs are maintained per-L2-VNI (vpn->es_evi_rb_tree)
198 * - ES-EVIs are also linked to the parent ES (es->es_evi_list)
199 * - Local ES-EVIs are created by zebra (via config). They are linked to a
200 * per-VNI list (vpn->local_es_evi_list) for quick access
201 * - Remote ES-EVIs are created implicitly when a bgp_evpn_es_evi_vtep
202 * references it.
203 */
204 struct bgp_evpn_es_evi {
205 struct bgp_evpn_es *es;
206 struct bgpevpn *vpn;
207
208 /* ES-EVI flags */
209 uint32_t flags;
210 /* local ES-EVI, created by zebra */
211 #define BGP_EVPNES_EVI_LOCAL (1 << 0)
212 /* created via a remote VTEP imported by BGP */
213 #define BGP_EVPNES_EVI_REMOTE (1 << 1)
214 #define BGP_EVPNES_EVI_INCONS_VTEP_LIST (1 << 2)
215
216 /* memory used for adding the es_evi to es_evi->vpn->es_evi_rb_tree */
217 RB_ENTRY(bgp_evpn_es_evi) rb_node;
218 /* memory used for linking the es_evi to
219 * es_evi->vpn->local_es_evi_list
220 */
221 struct listnode l2vni_listnode;
222 /* memory used for linking the es_evi to
223 * es_evi->es->es_evi_list
224 */
225 struct listnode es_listnode;
226
227 /* list of PEs (bgp_evpn_es_evi_vtep) attached to the ES for this VNI */
228 struct list *es_evi_vtep_list;
229
230 struct bgp_evpn_es_vrf *es_vrf;
231 };
232
233 /* PE attached to an ES for a VNI. This entry is created when an EAD-per-ES
234 * or EAD-per-EVI Type1 route is imported into the VNI.
235 */
236 struct bgp_evpn_es_evi_vtep {
237 struct bgp_evpn_es_evi *es_evi; /* parent ES-EVI */
238 struct in_addr vtep_ip;
239
240 uint32_t flags;
241 /* Rxed an EAD-per-ES route from the PE */
242 #define BGP_EVPN_EVI_VTEP_EAD_PER_ES (1 << 0) /* rxed EAD-per-ES */
243 /* Rxed an EAD-per-EVI route from the PE */
244 #define BGP_EVPN_EVI_VTEP_EAD_PER_EVI (1 << 1) /* rxed EAD-per-EVI */
245 /* VTEP is active i.e. will result in the creation of an es-vtep */
246 #define BGP_EVPN_EVI_VTEP_ACTIVE (1 << 2)
247 #define BGP_EVPN_EVI_VTEP_EAD (BGP_EVPN_EVI_VTEP_EAD_PER_ES |\
248 BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
249
250 /* memory used for adding the entry to es_evi->es_evi_vtep_list */
251 struct listnode es_evi_listnode;
252 struct bgp_evpn_es_vtep *es_vtep;
253 };
254
255 /* A nexthop is created when a path (imported from an EVPN type-2 route)
256 * is added to the VRF route table using that nexthop.
257 * It is added on first pi reference and removed on last pi deref.
258 */
259 struct bgp_evpn_nh {
260 /* backpointer to the VRF */
261 struct bgp *bgp_vrf;
262 /* nexthop/VTEP IP */
263 struct ipaddr ip;
264 /* description for easy logging */
265 char nh_str[INET6_ADDRSTRLEN];
266 struct ethaddr rmac;
267 /* pi from which we are pulling the nh RMAC */
268 struct bgp_path_info *ref_pi;
269 /* List of VRF paths using this nexthop */
270 struct list *pi_list;
271 uint8_t flags;
272 #define BGP_EVPN_NH_READY_FOR_ZEBRA (1 << 0)
273 };
274
275 /* multihoming information stored in bgp_master */
276 #define bgp_mh_info (bm->mh_info)
277 struct bgp_evpn_mh_info {
278 /* RB tree of Ethernet segments (used for EVPN-MH) */
279 struct bgp_es_rb_head es_rb_tree;
280 /* List of local ESs */
281 struct list *local_es_list;
282 /* List of ESs with pending/periodic processing */
283 struct list *pend_es_list;
284 /* periodic timer for running background consistency checks */
285 struct thread *t_cons_check;
286
287 /* config knobs for optimizing or interop */
288 /* Generate EAD-EVI routes even if the ES is oper-down. This can be
289 * enabled as an optimization to avoid a storm of updates when an ES
290 * link flaps.
291 */
292 bool ead_evi_adv_for_down_links;
293 /* Enable ES consistency checking */
294 bool consistency_checking;
295 /* Use L3 NHGs for host routes in symmetric IRB */
296 bool install_l3nhg;
297 bool host_routes_use_l3nhg;
298 /* Some vendors are not generating the EAD-per-EVI route. This knob
299 * can be turned off to activate a remote ES-PE when the EAD-per-ES
300 * route is rxed i.e. not wait on the EAD-per-EVI route
301 */
302 bool ead_evi_rx;
303 #define BGP_EVPN_MH_EAD_EVI_RX_DEF true
304 /* Skip EAD-EVI advertisements by turning off this knob */
305 bool ead_evi_tx;
306 #define BGP_EVPN_MH_EAD_EVI_TX_DEF true
307 /* If the Local ES is inactive we advertise the MAC-IP without the
308 * L3 ecomm
309 */
310 bool suppress_l3_ecomm_on_inactive_es;
311 /* Setup EVPN PE nexthops and their RMAC in bgpd */
312 bool bgp_evpn_nh_setup;
313 };
314
315 /****************************************************************************/
316 static inline int bgp_evpn_is_es_local(struct bgp_evpn_es *es)
317 {
318 return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ? 1 : 0;
319 }
320
321 extern esi_t *zero_esi;
322 static inline bool bgp_evpn_is_esi_valid(esi_t *esi)
323 {
324 return !!memcmp(esi, zero_esi, sizeof(esi_t));
325 }
326
327 static inline esi_t *bgp_evpn_attr_get_esi(struct attr *attr)
328 {
329 return attr ? &attr->esi : zero_esi;
330 }
331
332 static inline bool bgp_evpn_attr_is_sync(struct attr *attr)
333 {
334 return attr ? !!(attr->es_flags &
335 (ATTR_ES_PEER_PROXY | ATTR_ES_PEER_ACTIVE)) : false;
336 }
337
338 static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr *attr)
339 {
340 return attr ? attr->mm_sync_seqnum : 0;
341 }
342
343 static inline bool bgp_evpn_attr_is_active_on_peer(struct attr *attr)
344 {
345 return attr ?
346 !!(attr->es_flags & ATTR_ES_PEER_ACTIVE) : false;
347 }
348
349 static inline bool bgp_evpn_attr_is_router_on_peer(struct attr *attr)
350 {
351 return attr ?
352 !!(attr->es_flags & ATTR_ES_PEER_ROUTER) : false;
353 }
354
355 static inline bool bgp_evpn_attr_is_proxy(struct attr *attr)
356 {
357 return attr ? !!(attr->es_flags & ATTR_ES_PROXY_ADVERT) : false;
358 }
359
360 static inline bool bgp_evpn_attr_is_local_es(struct attr *attr)
361 {
362 return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false;
363 }
364
365 static inline uint32_t bgp_evpn_attr_get_df_pref(struct attr *attr)
366 {
367 return (attr) ? attr->df_pref : 0;
368 }
369
370 static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es)
371 {
372 return (es->flags & BGP_EVPNES_OPER_UP)
373 && !(es->flags & BGP_EVPNES_BYPASS);
374 }
375
376 /****************************************************************************/
377 extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp,
378 struct bgp_evpn_es *es, afi_t afi, safi_t safi,
379 struct prefix_evpn *evp, struct bgp_path_info *pi,
380 int install);
381 extern void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn);
382 extern int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn);
383 extern int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
384 struct bgpevpn *vpn, afi_t afi, safi_t safi,
385 struct bgp_dest *dest, struct attr *attr,
386 int add, struct bgp_path_info **ri,
387 int *route_changed);
388 int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
389 struct attr *attr, uint8_t *pfx, int psize,
390 uint32_t addpath_id);
391 int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
392 struct attr *attr, uint8_t *pfx, int psize,
393 uint32_t addpath_id);
394 extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
395 struct in_addr originator_ip, bool oper_up,
396 uint16_t df_pref, bool bypass);
397 extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi);
398 extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni);
399 extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni);
400 extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
401 const struct prefix_evpn *p);
402 extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
403 const struct prefix_evpn *p);
404 extern void bgp_evpn_mh_init(void);
405 extern void bgp_evpn_mh_finish(void);
406 void bgp_evpn_vni_es_init(struct bgpevpn *vpn);
407 void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn);
408 void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj);
409 void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail);
410 void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
411 bool uj, bool detail);
412 void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail);
413 struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi);
414 extern void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf);
415 extern bool bgp_evpn_is_esi_local_and_non_bypass(esi_t *esi);
416 extern void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi);
417 extern void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi,
418 struct bgp *bgp_vrf);
419 extern void bgp_evpn_path_mh_info_free(struct bgp_path_mh_info *mh_info);
420 extern void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni,
421 esi_t *esi);
422 extern bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf,
423 struct bgp_path_info *pi, uint32_t *nhg_p);
424 extern void bgp_evpn_es_vrf_show(struct vty *vty, bool uj,
425 struct bgp_evpn_es *es);
426 extern void bgp_evpn_es_vrf_show_esi(struct vty *vty, esi_t *esi, bool uj);
427 extern void bgp_evpn_switch_ead_evi_rx(void);
428 extern bool bgp_evpn_es_add_l3_ecomm_ok(esi_t *esi);
429 extern void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi,
430 bool *use_l3nhg, bool *is_l3nhg_active,
431 struct bgp_evpn_es_vrf **es_vrf_p);
432 extern void bgp_evpn_nh_init(struct bgp *bgp_vrf);
433 extern void bgp_evpn_nh_finish(struct bgp *bgp_vrf);
434 extern void bgp_evpn_nh_show(struct vty *vty, bool uj);
435 extern void bgp_evpn_path_nh_add(struct bgp *bgp_vrf, struct bgp_path_info *pi);
436 extern void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi);
437
438 #endif /* _FRR_BGP_EVPN_MH_H */