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