1 /* EVPN header for multihoming procedures
3 * Copyright (C) 2019 Cumulus Networks
6 * This file is part of FRRouting.
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
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.
20 #ifndef _FRR_BGP_EVPN_MH_H
21 #define _FRR_BGP_EVPN_MH_H
26 #include "bgp_evpn_private.h"
28 #define BGP_EVPN_AD_ES_ETH_TAG 0xffffffff
29 #define BGP_EVPN_AD_EVI_ETH_TAG 0
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)
35 #define BGP_EVPN_CONS_CHECK_INTERVAL 60
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
44 * - An ES can be simulatenously LOCAL and REMOTE; infact all LOCAL ESs are
45 * expected to have REMOTE ES peers.
48 /* Ethernet Segment Identifier */
50 char esi_str
[ESI_STR_LEN
];
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)
65 /* memory used for adding the es to bgp->es_rb_tree */
66 RB_ENTRY(bgp_evpn_es
) rb_node
;
68 /* [EVPNES_LOCAL] memory used for linking the es to
69 * bgp_mh_info->local_es_list
71 struct listnode es_listnode
;
73 /* memory used for linking the es to "processing" pending list
74 * bgp_mh_info->pend_es_list
76 struct listnode pend_es_listnode
;
78 /* [EVPNES_LOCAL] Id for deriving the RD automatically for this ESI */
81 /* [EVPNES_LOCAL] RD for this ES */
84 /* [EVPNES_LOCAL] originator ip address */
85 struct in_addr originator_ip
;
87 /* [EVPNES_LOCAL] Route table for EVPN routes for this ESI-
88 * - Type-4 local and remote routes
89 * - Type-1 local routes
91 struct bgp_table
*route_table
;
93 /* list of PEs (bgp_evpn_es_vtep) attached to the ES */
94 struct list
*es_vtep_list
;
96 /* List of ES-EVIs associated with this ES */
97 struct list
*es_evi_list
;
99 /* Number of remote VNIs referencing this ES */
100 uint32_t remote_es_evi_cnt
;
102 uint32_t inconsistencies
;
103 /* there are one or more EVIs whose VTEP list doesn't match
104 * with the ES's VTEP list
106 #define BGP_EVPNES_INCONS_VTEP_LIST (1 << 0)
108 /* number of es-evi entries whose VTEP list doesn't match
111 uint32_t incons_evi_vtep_cnt
;
115 DECLARE_QOBJ_TYPE(bgp_evpn_es
)
116 RB_HEAD(bgp_es_rb_head
, bgp_evpn_es
);
117 RB_PROTOTYPE(bgp_es_rb_head
, bgp_evpn_es
, rb_node
, bgp_es_rb_cmp
);
119 /* PE attached to an ES */
120 struct bgp_evpn_es_vtep
{
121 struct bgp_evpn_es
*es
; /* parent ES */
122 struct in_addr vtep_ip
;
125 /* Rxed a Type4 route from this PE */
126 #define BGP_EVPNES_VTEP_ESR (1 << 0)
127 /* Active (rxed EAD-ES and EAD-EVI) and can be included as
130 #define BGP_EVPNES_VTEP_ACTIVE (1 << 1)
132 uint32_t evi_cnt
; /* es_evis referencing this vtep as an active path */
134 /* memory used for adding the entry to es->es_vtep_list */
135 struct listnode es_listnode
;
139 * - ES-EVIs are maintained per-L2-VNI (vpn->es_evi_rb_tree)
140 * - ES-EVIs are also linked to the parent ES (es->es_evi_list)
141 * - Local ES-EVIs are created by zebra (via config). They are linked to a
142 * per-VNI list (vpn->local_es_evi_list) for quick access
143 * - Remote ES-EVIs are created implicitly when a bgp_evpn_es_evi_vtep
146 struct bgp_evpn_es_evi
{
147 struct bgp_evpn_es
*es
;
152 /* local ES-EVI, created by zebra */
153 #define BGP_EVPNES_EVI_LOCAL (1 << 0)
154 /* created via a remote VTEP imported by BGP */
155 #define BGP_EVPNES_EVI_REMOTE (1 << 1)
156 #define BGP_EVPNES_EVI_INCONS_VTEP_LIST (1 << 2)
158 /* memory used for adding the es_evi to es_evi->vpn->es_evi_rb_tree */
159 RB_ENTRY(bgp_evpn_es_evi
) rb_node
;
160 /* memory used for linking the es_evi to
161 * es_evi->vpn->local_es_evi_list
163 struct listnode l2vni_listnode
;
164 /* memory used for linking the es_evi to
165 * es_evi->es->es_evi_list
167 struct listnode es_listnode
;
169 /* list of PEs (bgp_evpn_es_evi_vtep) attached to the ES for this VNI */
170 struct list
*es_evi_vtep_list
;
173 /* PE attached to an ES for a VNI. This entry is created when an EAD-per-ES
174 * or EAD-per-EVI Type1 route is imported into the VNI.
176 struct bgp_evpn_es_evi_vtep
{
177 struct bgp_evpn_es_evi
*es_evi
; /* parent ES-EVI */
178 struct in_addr vtep_ip
;
181 /* Rxed an EAD-per-ES route from the PE */
182 #define BGP_EVPN_EVI_VTEP_EAD_PER_ES (1 << 0) /* rxed EAD-per-ES */
183 /* Rxed an EAD-per-EVI route from the PE */
184 #define BGP_EVPN_EVI_VTEP_EAD_PER_EVI (1 << 1) /* rxed EAD-per-EVI */
185 /* VTEP is active i.e. will result in the creation of an es-vtep */
186 #define BGP_EVPN_EVI_VTEP_ACTIVE (1 << 2)
187 #define BGP_EVPN_EVI_VTEP_EAD (BGP_EVPN_EVI_VTEP_EAD_PER_ES |\
188 BGP_EVPN_EVI_VTEP_EAD_PER_EVI)
190 /* memory used for adding the entry to es_evi->es_evi_vtep_list */
191 struct listnode es_evi_listnode
;
192 struct bgp_evpn_es_vtep
*es_vtep
;
195 /* multihoming information stored in bgp_master */
196 #define bgp_mh_info (bm->mh_info)
197 struct bgp_evpn_mh_info
{
198 /* RB tree of Ethernet segments (used for EVPN-MH) */
199 struct bgp_es_rb_head es_rb_tree
;
200 /* List of local ESs */
201 struct list
*local_es_list
;
202 /* List of ESs with pending/periodic processing */
203 struct list
*pend_es_list
;
204 /* periodic timer for running background consistency checks */
205 struct thread
*t_cons_check
;
207 /* config knobs for optimizing or interop */
208 /* Generate EAD-EVI routes even if the ES is oper-down. This can be
209 * enabled as an optimization to avoid a storm of updates when an ES
212 bool ead_evi_adv_for_down_links
;
213 /* Enable ES consistency checking */
214 bool consistency_checking
;
217 /****************************************************************************/
218 static inline int bgp_evpn_is_es_local(struct bgp_evpn_es
*es
)
220 return CHECK_FLAG(es
->flags
, BGP_EVPNES_LOCAL
) ? 1 : 0;
223 extern esi_t
*zero_esi
;
224 static inline bool bgp_evpn_is_esi_valid(esi_t
*esi
)
226 return !!memcmp(esi
, zero_esi
, sizeof(esi_t
));
229 static inline esi_t
*bgp_evpn_attr_get_esi(struct attr
*attr
)
231 return attr
? &attr
->esi
: zero_esi
;
234 static inline bool bgp_evpn_attr_is_sync(struct attr
*attr
)
236 return attr
? !!(attr
->es_flags
&
237 (ATTR_ES_PEER_PROXY
| ATTR_ES_PEER_ACTIVE
)) : false;
240 static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr
*attr
)
242 return attr
? attr
->mm_sync_seqnum
: 0;
245 static inline bool bgp_evpn_attr_is_active_on_peer(struct attr
*attr
)
248 !!(attr
->es_flags
& ATTR_ES_PEER_ACTIVE
) : false;
251 static inline bool bgp_evpn_attr_is_router_on_peer(struct attr
*attr
)
254 !!(attr
->es_flags
& ATTR_ES_PEER_ROUTER
) : false;
257 static inline bool bgp_evpn_attr_is_proxy(struct attr
*attr
)
259 return attr
? !!(attr
->es_flags
& ATTR_ES_PROXY_ADVERT
) : false;
262 static inline bool bgp_evpn_attr_is_local_es(struct attr
*attr
)
264 return attr
? !!(attr
->es_flags
& ATTR_ES_IS_LOCAL
) : false;
267 /****************************************************************************/
268 extern int bgp_evpn_es_route_install_uninstall(struct bgp
*bgp
,
269 struct bgp_evpn_es
*es
, afi_t afi
, safi_t safi
,
270 struct prefix_evpn
*evp
, struct bgp_path_info
*pi
,
272 int bgp_evpn_type1_route_process(struct peer
*peer
, afi_t afi
, safi_t safi
,
273 struct attr
*attr
, uint8_t *pfx
, int psize
,
274 uint32_t addpath_id
);
275 int bgp_evpn_type4_route_process(struct peer
*peer
, afi_t afi
, safi_t safi
,
276 struct attr
*attr
, uint8_t *pfx
, int psize
,
277 uint32_t addpath_id
);
278 extern int bgp_evpn_local_es_add(struct bgp
*bgp
, esi_t
*esi
,
279 struct in_addr originator_ip
, bool oper_up
);
280 extern int bgp_evpn_local_es_del(struct bgp
*bgp
, esi_t
*esi
);
281 extern int bgp_evpn_local_es_evi_add(struct bgp
*bgp
, esi_t
*esi
, vni_t vni
);
282 extern int bgp_evpn_local_es_evi_del(struct bgp
*bgp
, esi_t
*esi
, vni_t vni
);
283 extern int bgp_evpn_remote_es_evi_add(struct bgp
*bgp
, struct bgpevpn
*vpn
,
284 const struct prefix_evpn
*p
);
285 extern int bgp_evpn_remote_es_evi_del(struct bgp
*bgp
, struct bgpevpn
*vpn
,
286 const struct prefix_evpn
*p
);
287 extern void bgp_evpn_mh_init(void);
288 extern void bgp_evpn_mh_finish(void);
289 void bgp_evpn_vni_es_init(struct bgpevpn
*vpn
);
290 void bgp_evpn_vni_es_cleanup(struct bgpevpn
*vpn
);
291 void bgp_evpn_es_show_esi(struct vty
*vty
, esi_t
*esi
, bool uj
);
292 void bgp_evpn_es_show(struct vty
*vty
, bool uj
, bool detail
);
293 void bgp_evpn_es_evi_show_vni(struct vty
*vty
, vni_t vni
,
294 bool uj
, bool detail
);
295 void bgp_evpn_es_evi_show(struct vty
*vty
, bool uj
, bool detail
);
296 struct bgp_evpn_es
*bgp_evpn_es_find(const esi_t
*esi
);
297 extern bool bgp_evpn_is_esi_local(esi_t
*esi
);
299 #endif /* _FRR_BGP_EVPN_MH_H */