]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_mh.h
bgpd: correct a few comments for evpn-mh
[mirror_frr.git] / bgpd / bgp_evpn_mh.h
CommitLineData
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
c44ab6f1
AK
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
a92764da 36#define BGP_EVPN_MH_USE_ES_L3NHG_DEF true
c44ab6f1 37
7b0db0e4
AK
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 */
44struct 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
fff7545a 53 /* Memory used for linking bgp_evpn_es_frag to
54 * bgp_evpn_es->es_frag_list
55 */
7b0db0e4
AK
56 struct listnode es_listnode;
57
58 /* List of ES-EVIs associated with this fragment */
59 struct list *es_evi_frag_list;
60};
61
c44ab6f1
AK
62/* Ethernet Segment entry -
63 * - Local and remote ESs are maintained in a global RB tree,
fff7545a 64 * bgp_mh_info->es_rb_tree using ESI as key
c44ab6f1
AK
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)
fff7545a 68 * - An ES can be simultaneously LOCAL and REMOTE; infact all LOCAL ESs are
c44ab6f1
AK
69 * expected to have REMOTE ES peers.
70 */
71struct 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)
74be8313
AK
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
c44ab6f1
AK
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
fff7545a 106 /* [EVPNES_LOCAL] List of RDs for this ES (bgp_evpn_es_frag) */
7b0db0e4
AK
107 struct list *es_frag_list;
108 struct bgp_evpn_es_frag *es_base_frag;
c44ab6f1
AK
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
c589d847
AK
125 /* List of ES-VRFs associated with this ES */
126 struct list *es_vrf_list;
127
2eef4f20 128 /* List of MAC-IP VNI paths using this ES as destination -
26c03e43 129 * element is bgp_path_info_extra->es_info
58bff4d1
AK
130 * Note: Only local/zebra-added MACIP paths in the VNI
131 * routing table are linked to this list
26c03e43 132 */
d656e0ae 133 struct list *macip_evi_path_list;
26c03e43 134
58bff4d1
AK
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
c44ab6f1
AK
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
74e2bd89
AK
156 /* preference config for BUM-DF election. advertised via the ESR. */
157 uint16_t df_pref;
158
96244aca 159 QOBJ_FIELDS;
c44ab6f1 160};
96244aca 161DECLARE_QOBJ_TYPE(bgp_evpn_es);
c44ab6f1
AK
162RB_HEAD(bgp_es_rb_head, bgp_evpn_es);
163RB_PROTOTYPE(bgp_es_rb_head, bgp_evpn_es, rb_node, bgp_es_rb_cmp);
164
165/* PE attached to an ES */
166struct bgp_evpn_es_vtep {
167 struct bgp_evpn_es *es; /* parent ES */
168 struct in_addr vtep_ip;
169
23aa35ad
AK
170 char vtep_str[INET6_ADDRSTRLEN];
171
c44ab6f1
AK
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
74e2bd89
AK
182 /* Algorithm and preference for DF election. Rxed via the ESR */
183 uint8_t df_alg;
184 uint16_t df_pref;
185
c44ab6f1
AK
186 /* memory used for adding the entry to es->es_vtep_list */
187 struct listnode es_listnode;
188};
189
c589d847
AK
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 */
193struct 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;
6348981a 212 uint32_t v6_nhg_id;
c589d847
AK
213
214 /* Number of ES-EVI entries associated with this ES-VRF */
215 uint32_t ref_cnt;
216};
217
c44ab6f1
AK
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 */
226struct bgp_evpn_es_evi {
227 struct bgp_evpn_es *es;
7b0db0e4
AK
228 /* Only applicableif EVI_LOCAL */
229 struct bgp_evpn_es_frag *es_frag;
c44ab6f1
AK
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
7b0db0e4
AK
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;
c44ab6f1
AK
255 /* list of PEs (bgp_evpn_es_evi_vtep) attached to the ES for this VNI */
256 struct list *es_evi_vtep_list;
c589d847
AK
257
258 struct bgp_evpn_es_vrf *es_vrf;
c44ab6f1
AK
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 */
264struct 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
090efa2f
AK
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 */
287struct 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
c44ab6f1
AK
303/* multihoming information stored in bgp_master */
304#define bgp_mh_info (bm->mh_info)
305struct 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;
8bcb09a1
AK
323 /* Use L3 NHGs for host routes in symmetric IRB */
324 bool install_l3nhg;
6348981a 325 bool host_routes_use_l3nhg;
fe8293c3
AK
326 /* Some vendors are not generating the EAD-per-EVI route. This knob
327 * can be turned off to activate a remote ES-PE when the EAD-per-ES
328 * route is rxed i.e. not wait on the EAD-per-EVI route
329 */
330 bool ead_evi_rx;
331#define BGP_EVPN_MH_EAD_EVI_RX_DEF true
332 /* Skip EAD-EVI advertisements by turning off this knob */
333 bool ead_evi_tx;
334#define BGP_EVPN_MH_EAD_EVI_TX_DEF true
70524092
AK
335 /* If the Local ES is inactive we advertise the MAC-IP without the
336 * L3 ecomm
337 */
338 bool suppress_l3_ecomm_on_inactive_es;
090efa2f
AK
339 /* Setup EVPN PE nexthops and their RMAC in bgpd */
340 bool bgp_evpn_nh_setup;
f4a5218d
AK
341
342 /* If global export-rts are configured that is used for sending
343 * sending the ead-per-es route instead of the L2-VNI(s) RTs
344 */
345 struct list *ead_es_export_rtl;
bb37eabe
AK
346
347 /* Number of EVIs in an ES fragment - used of EAD-per-ES route
348 * construction
349 */
350 uint32_t evi_per_es_frag;
c44ab6f1
AK
351};
352
353/****************************************************************************/
7904e9fd 354static inline int bgp_evpn_is_es_local(struct bgp_evpn_es *es)
c44ab6f1
AK
355{
356 return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ? 1 : 0;
357}
358
359extern esi_t *zero_esi;
7904e9fd
AK
360static inline bool bgp_evpn_is_esi_valid(esi_t *esi)
361{
362 return !!memcmp(esi, zero_esi, sizeof(esi_t));
363}
364
c44ab6f1
AK
365static inline esi_t *bgp_evpn_attr_get_esi(struct attr *attr)
366{
7904e9fd
AK
367 return attr ? &attr->esi : zero_esi;
368}
369
370static inline bool bgp_evpn_attr_is_sync(struct attr *attr)
371{
372 return attr ? !!(attr->es_flags &
373 (ATTR_ES_PEER_PROXY | ATTR_ES_PEER_ACTIVE)) : false;
374}
375
376static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr *attr)
377{
378 return attr ? attr->mm_sync_seqnum : 0;
379}
380
381static inline bool bgp_evpn_attr_is_active_on_peer(struct attr *attr)
382{
383 return attr ?
384 !!(attr->es_flags & ATTR_ES_PEER_ACTIVE) : false;
385}
386
387static inline bool bgp_evpn_attr_is_router_on_peer(struct attr *attr)
388{
389 return attr ?
390 !!(attr->es_flags & ATTR_ES_PEER_ROUTER) : false;
391}
392
393static inline bool bgp_evpn_attr_is_proxy(struct attr *attr)
394{
395 return attr ? !!(attr->es_flags & ATTR_ES_PROXY_ADVERT) : false;
396}
397
398static inline bool bgp_evpn_attr_is_local_es(struct attr *attr)
399{
400 return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false;
c44ab6f1
AK
401}
402
74e2bd89
AK
403static inline uint32_t bgp_evpn_attr_get_df_pref(struct attr *attr)
404{
405 return (attr) ? attr->df_pref : 0;
406}
407
70524092
AK
408static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es)
409{
410 return (es->flags & BGP_EVPNES_OPER_UP)
411 && !(es->flags & BGP_EVPNES_BYPASS);
412}
413
c44ab6f1
AK
414/****************************************************************************/
415extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp,
416 struct bgp_evpn_es *es, afi_t afi, safi_t safi,
417 struct prefix_evpn *evp, struct bgp_path_info *pi,
418 int install);
9c49ac74 419extern void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn);
d60f63f0
AD
420extern int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn);
421extern int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
422 struct bgpevpn *vpn, afi_t afi, safi_t safi,
423 struct bgp_dest *dest, struct attr *attr,
424 int add, struct bgp_path_info **ri,
425 int *route_changed);
c44ab6f1
AK
426int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
427 struct attr *attr, uint8_t *pfx, int psize,
428 uint32_t addpath_id);
429int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
430 struct attr *attr, uint8_t *pfx, int psize,
431 uint32_t addpath_id);
185fb14a 432extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
74e2bd89 433 struct in_addr originator_ip, bool oper_up,
74be8313 434 uint16_t df_pref, bool bypass);
c44ab6f1
AK
435extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi);
436extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni);
437extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni);
438extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
439 const struct prefix_evpn *p);
440extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
441 const struct prefix_evpn *p);
442extern void bgp_evpn_mh_init(void);
443extern void bgp_evpn_mh_finish(void);
444void bgp_evpn_vni_es_init(struct bgpevpn *vpn);
445void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn);
446void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj);
447void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail);
448void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
449 bool uj, bool detail);
450void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail);
451struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi);
c589d847 452extern void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf);
74efb822 453extern bool bgp_evpn_is_esi_local_and_non_bypass(esi_t *esi);
c589d847
AK
454extern void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi);
455extern void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi,
456 struct bgp *bgp_vrf);
60605cbc 457extern void bgp_evpn_path_mh_info_free(struct bgp_path_mh_info *mh_info);
26c03e43
AK
458extern void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni,
459 esi_t *esi);
6348981a
AK
460extern bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf,
461 struct bgp_path_info *pi, uint32_t *nhg_p);
229587fb
AK
462extern void bgp_evpn_es_vrf_show(struct vty *vty, bool uj,
463 struct bgp_evpn_es *es);
464extern void bgp_evpn_es_vrf_show_esi(struct vty *vty, esi_t *esi, bool uj);
acd1d9bc 465extern void bgp_evpn_switch_ead_evi_rx(void);
70524092 466extern bool bgp_evpn_es_add_l3_ecomm_ok(esi_t *esi);
58bff4d1
AK
467extern void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi,
468 bool *use_l3nhg, bool *is_l3nhg_active,
469 struct bgp_evpn_es_vrf **es_vrf_p);
090efa2f
AK
470extern void bgp_evpn_nh_init(struct bgp *bgp_vrf);
471extern void bgp_evpn_nh_finish(struct bgp *bgp_vrf);
472extern void bgp_evpn_nh_show(struct vty *vty, bool uj);
473extern void bgp_evpn_path_nh_add(struct bgp *bgp_vrf, struct bgp_path_info *pi);
474extern void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi);
f4a5218d
AK
475extern void bgp_evpn_mh_config_ead_export_rt(struct bgp *bgp,
476 struct ecommunity *ecom, bool del);
c44ab6f1 477
185fb14a 478#endif /* _FRR_BGP_EVPN_MH_H */