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