2 * Zebra EVPN MH Data structures and definitions
4 * Copyright (C) 2019 Cumulus Networks, Inc.
7 * This file is part of FRR.
9 * FRR is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
14 * FRR is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
20 #ifndef _ZEBRA_EVPN_MH_H
21 #define _ZEBRA_EVPN_MH_H
28 #include "zebra_vxlan.h"
29 #include "zebra_vxlan_private.h"
30 #include "zebra_nhg.h"
32 #define EVPN_MH_VTY_STR "Multihoming\n"
34 /* Ethernet Segment entry -
35 * - Local and remote ESs are maintained in a global RB tree,
36 * zmh_info->es_rb_tree using ESI as key
37 * - Local ESs are added via zebra config (ZEBRA_EVPNES_LOCAL) when an
38 * access port is associated with an ES-ID
39 * - Remotes ESs are added by BGP based on received/remote EAD/Type-1 routes
40 * (ZEBRA_EVPNES_REMOTE)
41 * - An ES can be simultaneously LOCAL and REMOTE; infact all LOCAL ESs are
42 * expected to have REMOTE ES peers.
44 struct zebra_evpn_es
{
46 char esi_str
[ESI_STR_LEN
];
50 #define ZEBRA_EVPNES_LOCAL (1 << 0) /* configured in zebra */
51 #define ZEBRA_EVPNES_REMOTE (1 << 1) /* added by bgp */
52 #define ZEBRA_EVPNES_OPER_UP (1 << 2) /* es->ifp is oper-up */
53 #define ZEBRA_EVPNES_READY_FOR_BGP (1 << 3) /* ready to be sent to BGP */
54 #define ZEBRA_EVPNES_NHG_ACTIVE (1 << 4) /* NHG has been installed */
55 /* This flag is only applicable to local ESs and signifies that this
58 #define ZEBRA_EVPNES_NON_DF (1 << 5)
59 /* When the ES becomes a bridge port we need to activate the BUM non-DF
60 * filter, SPH filter and backup NHG for fast-failover
62 #define ZEBRA_EVPNES_BR_PORT (1 << 6)
63 /* ES is in bypass mode i.e. must not be advertised. ES-bypass is set
64 * when the associated host bond goes into LACP bypass
66 #define ZEBRA_EVPNES_BYPASS (1 << 7)
68 /* memory used for adding the es to zmh_info->es_rb_tree */
69 RB_ENTRY(zebra_evpn_es
) rb_node
;
71 /* [EVPNES_LOCAL] memory used for linking the es to
72 * zmh_info->local_es_list
74 struct listnode local_es_listnode
;
76 /* [EVPNES_LOCAL] corresponding interface */
79 /* list of ES-EVIs associated with the ES */
80 struct list
*es_evi_list
;
82 /* [!EVPNES_LOCAL] List of remote VTEPs (zebra_evpn_es_vtep) */
83 struct list
*es_vtep_list
;
85 /* list of zebra_mac entries using this ES as destination */
86 struct list
*mac_list
;
88 /* Nexthop group id */
91 /* Preference config for BUM-DF election. Sent to BGP and
92 * advertised via the ESR
96 /* When a new ES is configured it is held in a non-DF state
97 * for 3 seconds. This allows the peer Type-4 routes to be
98 * imported before running the DF election.
100 #define ZEBRA_EVPN_MH_DF_DELAY_TIME 3 /* seconds */
101 struct thread
*df_delay_timer
;
103 RB_HEAD(zebra_es_rb_head
, zebra_evpn_es
);
104 RB_PROTOTYPE(zebra_es_rb_head
, zebra_evpn_es
, rb_node
, zebra_es_rb_cmp
);
107 * - ES-EVIs are maintained per-EVPN (vni->es_evi_rb_tree)
108 * - Local ES-EVIs are linked to per-EVPN list for quick access
109 * - Although some infrastucture is present for remote ES-EVIs, currently
110 * BGP does NOT send remote ES-EVIs to zebra. This may change in the
111 * future (but must be changed thoughtfully and only if needed as ES-EVI
112 * can get prolific and come in the way of rapid failovers)
114 struct zebra_evpn_es_evi
{
115 struct zebra_evpn_es
*es
;
116 struct zebra_evpn
*zevpn
;
121 #define ZEBRA_EVPNES_EVI_LOCAL (1 << 0) /* created by zebra */
122 #define ZEBRA_EVPNES_EVI_READY_FOR_BGP (1 << 1) /* ready to be sent to BGP */
124 /* memory used for adding the es_evi to
125 * es_evi->zevpn->es_evi_rb_tree
127 RB_ENTRY(zebra_evpn_es_evi
) rb_node
;
128 /* memory used for linking the es_evi to
129 * es_evi->zevpn->local_es_evi_list
131 struct listnode l2vni_listnode
;
132 /* memory used for linking the es_evi to
133 * es_evi->es->es_evi_list
135 struct listnode es_listnode
;
138 /* A single L2 nexthop is allocated across all ESs with the same PE/VTEP
141 struct zebra_evpn_l2_nh
{
142 struct in_addr vtep_ip
;
147 /* es_vtep entries using this nexthop */
151 /* PE attached to an ES */
152 struct zebra_evpn_es_vtep
{
153 struct zebra_evpn_es
*es
; /* parent ES */
154 struct in_addr vtep_ip
;
157 /* Rxed Type-4 route from this VTEP */
158 #define ZEBRA_EVPNES_VTEP_RXED_ESR (1 << 0)
159 #define ZEBRA_EVPNES_VTEP_DEL_IN_PROG (1 << 1)
161 /* MAC nexthop info */
162 struct zebra_evpn_l2_nh
*nh
;
164 /* memory used for adding the entry to es->es_vtep_list */
165 struct listnode es_listnode
;
167 /* Parameters for DF election */
171 /* XXX - maintain a backpointer to struct zebra_vtep */
174 /* Local/access-side broadcast domain - zebra_evpn_access_bd is added to -
175 * zrouter->evpn_vlan_table (for VLAN aware bridges) OR
176 * zrouter->evpn_bridge_table (for VLAN unaware bridges)
177 * XXX - support for VLAN unaware bridges is yet to be flushed out
179 struct zebra_evpn_access_bd
{
182 ifindex_t bridge_ifindex
;
183 struct zebra_if
*bridge_zif
; /* associated bridge */
185 vni_t vni
; /* vni associated with the vxlan device */
186 struct zebra_if
*vxlan_zif
; /* vxlan device */
187 /* list of members associated with the BD i.e. (potential) ESs */
188 struct list
*mbr_zifs
;
189 /* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
190 struct zebra_evpn
*zevpn
;
191 /* SVI associated with the VLAN */
192 struct zebra_if
*vlan_zif
;
195 /* multihoming information stored in zrouter */
196 #define zmh_info (zrouter.mh_info)
197 struct zebra_evpn_mh_info
{
199 /* If the dataplane is not capable of handling a backup NHG on an access
200 * port we will need to explicitly failover each MAC entry on
203 #define ZEBRA_EVPN_MH_REDIRECT_OFF (1 << 0)
204 /* DAD support for EVPN-MH is yet to be added. So on detection of
205 * first local ES, DAD is turned off
207 #define ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF (1 << 1)
208 /* If EVPN MH is enabled we only advertise REACHABLE neigh entries as Type-2
209 * routes. As there is no global config knob for enabling EVPN MH we turn
210 * this flag when the first local ES is detected.
212 #define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
213 /* If EVPN MH is enabled we advertise the SVI MAC address to avoid
214 * flooding of ARP replies rxed from the multi-homed host
216 #define ZEBRA_EVPN_MH_ADV_SVI_MAC (1 << 3)
218 /* RB tree of Ethernet segments (used for EVPN-MH) */
219 struct zebra_es_rb_head es_rb_tree
;
220 /* List of local ESs */
221 struct list
*local_es_list
;
223 /* EVPN MH broadcast domains indexed by the VID */
224 struct hash
*evpn_vlan_table
;
226 /* A base L2-VNI is maintained to derive parameters such as
228 * XXX: once single vxlan device model becomes available this will
231 struct zebra_evpn
*es_base_evpn
;
232 struct in_addr es_originator_ip
;
234 /* L2 NH and NHG ids -
235 * Most significant 4 bits is type. Lower 28 bits is the value
236 * allocated from the nh_id_bitmap.
238 bitfield_t nh_id_bitmap
;
239 #define EVPN_NH_ID_MAX (16*1024)
240 #define EVPN_NH_ID_VAL_MASK 0xffffff
241 /* The purpose of using different types for NHG and NH is NOT to manage the
242 * id space separately. It is simply to make debugging easier.
244 #define EVPN_NH_ID_TYPE_BIT (NHG_TYPE_L2_NH << NHG_ID_TYPE_POS)
245 #define EVPN_NHG_ID_TYPE_BIT (NHG_TYPE_L2 << NHG_ID_TYPE_POS)
246 /* L2-NHG table - key: nhg_id, data: zebra_evpn_es */
247 struct hash
*nhg_table
;
248 /* L2-NH table - key: vtep_up, data: zebra_evpn_nh */
249 struct hash
*nh_ip_table
;
251 /* XXX - re-visit the default hold timer value */
253 #define ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF (18 * 60)
255 #define ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF (18 * 60)
257 /* During this period access ports will be held in a protodown
260 int startup_delay_time
; /* seconds */
261 #define ZEBRA_EVPN_MH_STARTUP_DELAY_DEF (3 * 60)
262 struct thread
*startup_delay_timer
;
264 /* Number of configured uplinks */
265 uint32_t uplink_cfg_cnt
;
266 /* Number of operationally-up uplinks */
267 uint32_t uplink_oper_up_cnt
;
269 /* These protodown bits are inherited by all ES bonds */
270 uint32_t protodown_rc
;
273 /* returns TRUE if the EVPN is ready to be sent to BGP */
274 static inline bool zebra_evpn_send_to_client_ok(struct zebra_evpn
*zevpn
)
276 return !!(zevpn
->flags
& ZEVPN_READY_FOR_BGP
);
279 static inline bool zebra_evpn_mac_is_es_local(struct zebra_mac
*mac
)
281 return mac
->es
&& (mac
->es
->flags
& ZEBRA_EVPNES_LOCAL
);
284 /* Returns true if the id is of L2-NHG or L2-NH type */
285 static inline bool zebra_evpn_mh_is_fdb_nh(uint32_t id
)
287 return ((id
& EVPN_NHG_ID_TYPE_BIT
) ||
288 (id
& EVPN_NH_ID_TYPE_BIT
));
292 zebra_evpn_es_local_mac_via_network_port(struct zebra_evpn_es
*es
)
294 return !(es
->flags
& ZEBRA_EVPNES_OPER_UP
)
295 && (zmh_info
->flags
& ZEBRA_EVPN_MH_REDIRECT_OFF
);
298 static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
300 return !(zmh_info
->flags
& ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF
);
303 static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
305 return !!(zmh_info
->flags
& ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY
);
308 static inline bool zebra_evpn_mh_do_adv_svi_mac(void)
310 return zmh_info
&& (zmh_info
->flags
& ZEBRA_EVPN_MH_ADV_SVI_MAC
);
313 /*****************************************************************************/
314 extern esi_t
*zero_esi
;
315 extern void zebra_evpn_mh_init(void);
316 extern void zebra_evpn_mh_terminate(void);
317 extern bool zebra_evpn_is_if_es_capable(struct zebra_if
*zif
);
318 extern void zebra_evpn_if_init(struct zebra_if
*zif
);
319 extern void zebra_evpn_if_cleanup(struct zebra_if
*zif
);
320 extern void zebra_evpn_es_evi_init(struct zebra_evpn
*zevpn
);
321 extern void zebra_evpn_es_evi_cleanup(struct zebra_evpn
*zevpn
);
322 extern void zebra_evpn_vxl_evpn_set(struct zebra_if
*zif
,
323 struct zebra_evpn
*zevpn
, bool set
);
324 extern void zebra_evpn_es_set_base_evpn(struct zebra_evpn
*zevpn
);
325 extern void zebra_evpn_es_clear_base_evpn(struct zebra_evpn
*zevpn
);
326 extern void zebra_evpn_vl_vxl_ref(uint16_t vid
, vni_t vni_id
,
327 struct zebra_if
*vxlan_zif
);
328 extern void zebra_evpn_vl_vxl_deref(uint16_t vid
, vni_t vni_id
,
329 struct zebra_if
*vxlan_zif
);
330 extern void zebra_evpn_vl_mbr_ref(uint16_t vid
, struct zebra_if
*zif
);
331 extern void zebra_evpn_vl_mbr_deref(uint16_t vid
, struct zebra_if
*zif
);
332 extern void zebra_evpn_es_send_all_to_client(bool add
);
333 extern void zebra_evpn_es_if_oper_state_change(struct zebra_if
*zif
, bool up
);
334 extern void zebra_evpn_es_show(struct vty
*vty
, bool uj
);
335 extern void zebra_evpn_es_show_detail(struct vty
*vty
, bool uj
);
336 extern void zebra_evpn_es_show_esi(struct vty
*vty
, bool uj
, esi_t
*esi
);
337 extern void zebra_evpn_update_all_es(struct zebra_evpn
*zevpn
);
338 extern void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS
);
339 int zebra_evpn_remote_es_add(const esi_t
*esi
, struct in_addr vtep_ip
,
340 bool esr_rxed
, uint8_t df_alg
, uint16_t df_pref
);
341 int zebra_evpn_remote_es_del(const esi_t
*esi
, struct in_addr vtep_ip
);
342 extern void zebra_evpn_es_evi_show(struct vty
*vty
, bool uj
, int detail
);
343 extern void zebra_evpn_es_evi_show_vni(struct vty
*vty
, bool uj
,
344 vni_t vni
, int detail
);
345 extern void zebra_evpn_es_mac_deref_entry(struct zebra_mac
*mac
);
346 extern bool zebra_evpn_es_mac_ref_entry(struct zebra_mac
*mac
,
347 struct zebra_evpn_es
*es
);
348 extern bool zebra_evpn_es_mac_ref(struct zebra_mac
*mac
, const esi_t
*esi
);
349 extern struct zebra_evpn_es
*zebra_evpn_es_find(const esi_t
*esi
);
350 extern void zebra_evpn_interface_init(void);
351 extern int zebra_evpn_mh_if_write(struct vty
*vty
, struct interface
*ifp
);
352 extern void zebra_evpn_acc_vl_show(struct vty
*vty
, bool uj
);
353 extern void zebra_evpn_acc_vl_show_detail(struct vty
*vty
, bool uj
);
354 extern void zebra_evpn_if_es_print(struct vty
*vty
, json_object
*json
,
355 struct zebra_if
*zif
);
356 extern struct zebra_evpn_access_bd
*
357 zebra_evpn_acc_vl_find(vlanid_t vid
, struct interface
*br_if
);
358 extern void zebra_evpn_acc_vl_show_vid(struct vty
*vty
, bool uj
, vlanid_t vid
,
359 struct interface
*br_if
);
360 extern void zebra_evpn_es_cleanup(void);
361 extern int zebra_evpn_mh_mac_holdtime_update(struct vty
*vty
,
362 uint32_t duration
, bool set_default
);
363 void zebra_evpn_mh_config_write(struct vty
*vty
);
364 int zebra_evpn_mh_neigh_holdtime_update(struct vty
*vty
,
365 uint32_t duration
, bool set_default
);
366 void zebra_evpn_es_local_br_port_update(struct zebra_if
*zif
);
367 extern int zebra_evpn_mh_startup_delay_update(struct vty
*vty
,
370 extern void zebra_evpn_mh_uplink_oper_update(struct zebra_if
*zif
);
371 extern void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if
*zif
,
374 extern bool zebra_evpn_is_es_bond(struct interface
*ifp
);
375 extern bool zebra_evpn_is_es_bond_member(struct interface
*ifp
);
376 extern void zebra_evpn_mh_print(struct vty
*vty
);
377 extern void zebra_evpn_mh_json(json_object
*json
);
378 extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id
,
379 struct zebra_evpn_es
**local_es
);
380 extern int zebra_evpn_mh_redirect_off(struct vty
*vty
, bool redirect_off
);
381 extern void zebra_evpn_l2_nh_show(struct vty
*vty
, bool uj
);
382 extern void zebra_evpn_acc_bd_svi_set(struct zebra_if
*vlan_zif
,
383 struct zebra_if
*br_zif
, bool is_up
);
384 extern void zebra_evpn_acc_bd_svi_mac_add(struct interface
*vlan_if
);
386 zebra_evpn_access_bd_bridge_cleanup(vlanid_t vid
, struct interface
*br_if
,
387 struct zebra_evpn_access_bd
*acc_bd
);
388 extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es
*es
,
389 struct interface
*ifp
, bool bypass
);
390 extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS
);
391 extern struct zebra_evpn_es_evi
*
392 zebra_evpn_es_evi_find(struct zebra_evpn_es
*es
, struct zebra_evpn
*zevpn
);
394 #endif /* _ZEBRA_EVPN_MH_H */