Line data Source code
1 : /*
2 : * Zebra EVPN MH Data structures and definitions
3 : *
4 : * Copyright (C) 2019 Cumulus Networks, Inc.
5 : * Anuradha Karuppiah
6 : *
7 : * This file is part of FRR.
8 : *
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
12 : * later version.
13 : *
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.
18 : */
19 :
20 : #ifndef _ZEBRA_EVPN_MH_H
21 : #define _ZEBRA_EVPN_MH_H
22 :
23 : #include <zebra.h>
24 :
25 : #include "if.h"
26 : #include "linklist.h"
27 : #include "bitfield.h"
28 : #include "zebra_vxlan.h"
29 : #include "zebra_vxlan_private.h"
30 : #include "zebra_nhg.h"
31 :
32 : #define EVPN_MH_VTY_STR "Multihoming\n"
33 :
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.
43 : */
44 : struct zebra_evpn_es {
45 : esi_t esi;
46 : char esi_str[ESI_STR_LEN];
47 :
48 : /* ES flags */
49 : uint32_t flags;
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
56 : * VTEP is not the DF
57 : */
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
61 : */
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
65 : */
66 : #define ZEBRA_EVPNES_BYPASS (1 << 7)
67 :
68 : /* memory used for adding the es to zmh_info->es_rb_tree */
69 : RB_ENTRY(zebra_evpn_es) rb_node;
70 :
71 : /* [EVPNES_LOCAL] memory used for linking the es to
72 : * zmh_info->local_es_list
73 : */
74 : struct listnode local_es_listnode;
75 :
76 : /* [EVPNES_LOCAL] corresponding interface */
77 : struct zebra_if *zif;
78 :
79 : /* list of ES-EVIs associated with the ES */
80 : struct list *es_evi_list;
81 :
82 : /* [!EVPNES_LOCAL] List of remote VTEPs (zebra_evpn_es_vtep) */
83 : struct list *es_vtep_list;
84 :
85 : /* list of zebra_mac entries using this ES as destination */
86 : struct list *mac_list;
87 :
88 : /* Nexthop group id */
89 : uint32_t nhg_id;
90 :
91 : /* Preference config for BUM-DF election. Sent to BGP and
92 : * advertised via the ESR
93 : */
94 : uint16_t df_pref;
95 :
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.
99 : */
100 : #define ZEBRA_EVPN_MH_DF_DELAY_TIME 3 /* seconds */
101 : struct thread *df_delay_timer;
102 : };
103 : RB_HEAD(zebra_es_rb_head, zebra_evpn_es);
104 6 : RB_PROTOTYPE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
105 :
106 : /* ES per-EVI info
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)
113 : */
114 : struct zebra_evpn_es_evi {
115 : struct zebra_evpn_es *es;
116 : struct zebra_evpn *zevpn;
117 :
118 : /* ES-EVI flags */
119 : uint32_t flags;
120 : /* local ES-EVI */
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 */
123 :
124 : /* memory used for adding the es_evi to
125 : * es_evi->zevpn->es_evi_rb_tree
126 : */
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
130 : */
131 : struct listnode l2vni_listnode;
132 : /* memory used for linking the es_evi to
133 : * es_evi->es->es_evi_list
134 : */
135 : struct listnode es_listnode;
136 : };
137 :
138 : /* A single L2 nexthop is allocated across all ESs with the same PE/VTEP
139 : * nexthop
140 : */
141 : struct zebra_evpn_l2_nh {
142 : struct in_addr vtep_ip;
143 :
144 : /* MAC nexthop id */
145 : uint32_t nh_id;
146 :
147 : /* es_vtep entries using this nexthop */
148 : uint32_t ref_cnt;
149 : };
150 :
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;
155 :
156 : uint32_t flags;
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)
160 :
161 : /* MAC nexthop info */
162 : struct zebra_evpn_l2_nh *nh;
163 :
164 : /* memory used for adding the entry to es->es_vtep_list */
165 : struct listnode es_listnode;
166 :
167 : /* Parameters for DF election */
168 : uint8_t df_alg;
169 : uint32_t df_pref;
170 :
171 : /* XXX - maintain a backpointer to struct zebra_vtep */
172 : };
173 :
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
178 : */
179 : struct zebra_evpn_access_bd {
180 : vlanid_t vid;
181 :
182 : struct zebra_if *vxlan_zif; /* vxlan device */
183 : /* list of members associated with the BD i.e. (potential) ESs */
184 : struct list *mbr_zifs;
185 : /* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
186 : struct zebra_evpn *zevpn;
187 : /* SVI associated with the VLAN */
188 : struct zebra_if *vlan_zif;
189 : };
190 :
191 : /* multihoming information stored in zrouter */
192 : #define zmh_info (zrouter.mh_info)
193 : struct zebra_evpn_mh_info {
194 : uint32_t flags;
195 : /* If the dataplane is not capable of handling a backup NHG on an access
196 : * port we will need to explicitly failover each MAC entry on
197 : * local ES down
198 : */
199 : #define ZEBRA_EVPN_MH_REDIRECT_OFF (1 << 0)
200 : /* DAD support for EVPN-MH is yet to be added. So on detection of
201 : * first local ES, DAD is turned off
202 : */
203 : #define ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF (1 << 1)
204 : /* If EVPN MH is enabled we only advertise REACHABLE neigh entries as Type-2
205 : * routes. As there is no global config knob for enabling EVPN MH we turn
206 : * this flag when the first local ES is detected.
207 : */
208 : #define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
209 : /* If EVPN MH is enabled we advertise the SVI MAC address to avoid
210 : * flooding of ARP replies rxed from the multi-homed host
211 : */
212 : #define ZEBRA_EVPN_MH_ADV_SVI_MAC (1 << 3)
213 :
214 : /* RB tree of Ethernet segments (used for EVPN-MH) */
215 : struct zebra_es_rb_head es_rb_tree;
216 : /* List of local ESs */
217 : struct list *local_es_list;
218 :
219 : /* EVPN MH broadcast domains indexed by the VID */
220 : struct hash *evpn_vlan_table;
221 :
222 : /* A base L2-VNI is maintained to derive parameters such as
223 : * ES originator-IP.
224 : * XXX: once single vxlan device model becomes available this will
225 : * not be necessary
226 : */
227 : struct zebra_evpn *es_base_evpn;
228 : struct in_addr es_originator_ip;
229 :
230 : /* L2 NH and NHG ids -
231 : * Most significant 4 bits is type. Lower 28 bits is the value
232 : * allocated from the nh_id_bitmap.
233 : */
234 : bitfield_t nh_id_bitmap;
235 : #define EVPN_NH_ID_MAX (16*1024)
236 : #define EVPN_NH_ID_VAL_MASK 0xffffff
237 : /* The purpose of using different types for NHG and NH is NOT to manage the
238 : * id space separately. It is simply to make debugging easier.
239 : */
240 : #define EVPN_NH_ID_TYPE_BIT (NHG_TYPE_L2_NH << NHG_ID_TYPE_POS)
241 : #define EVPN_NHG_ID_TYPE_BIT (NHG_TYPE_L2 << NHG_ID_TYPE_POS)
242 : /* L2-NHG table - key: nhg_id, data: zebra_evpn_es */
243 : struct hash *nhg_table;
244 : /* L2-NH table - key: vtep_up, data: zebra_evpn_nh */
245 : struct hash *nh_ip_table;
246 :
247 : /* XXX - re-visit the default hold timer value */
248 : int mac_hold_time;
249 : #define ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF (18 * 60)
250 : int neigh_hold_time;
251 : #define ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF (18 * 60)
252 :
253 : /* During this period access ports will be held in a protodown
254 : * state
255 : */
256 : int startup_delay_time; /* seconds */
257 : #define ZEBRA_EVPN_MH_STARTUP_DELAY_DEF (3 * 60)
258 : struct thread *startup_delay_timer;
259 :
260 : /* Number of configured uplinks */
261 : uint32_t uplink_cfg_cnt;
262 : /* Number of operationally-up uplinks */
263 : uint32_t uplink_oper_up_cnt;
264 :
265 : /* These protodown bits are inherited by all ES bonds */
266 : uint32_t protodown_rc;
267 : };
268 :
269 : /* returns TRUE if the EVPN is ready to be sent to BGP */
270 0 : static inline bool zebra_evpn_send_to_client_ok(struct zebra_evpn *zevpn)
271 : {
272 0 : return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
273 : }
274 :
275 : static inline bool zebra_evpn_mac_is_es_local(struct zebra_mac *mac)
276 : {
277 : return mac->es && (mac->es->flags & ZEBRA_EVPNES_LOCAL);
278 : }
279 :
280 : /* Returns true if the id is of L2-NHG or L2-NH type */
281 0 : static inline bool zebra_evpn_mh_is_fdb_nh(uint32_t id)
282 : {
283 0 : return ((id & EVPN_NHG_ID_TYPE_BIT) ||
284 : (id & EVPN_NH_ID_TYPE_BIT));
285 : }
286 :
287 : static inline bool
288 0 : zebra_evpn_es_local_mac_via_network_port(struct zebra_evpn_es *es)
289 : {
290 0 : return !(es->flags & ZEBRA_EVPNES_OPER_UP)
291 0 : && (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF);
292 : }
293 :
294 0 : static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
295 : {
296 0 : return !(zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF);
297 : }
298 :
299 0 : static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
300 : {
301 0 : return !!(zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY);
302 : }
303 :
304 0 : static inline bool zebra_evpn_mh_do_adv_svi_mac(void)
305 : {
306 0 : return zmh_info && (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC);
307 : }
308 :
309 : /*****************************************************************************/
310 : extern esi_t *zero_esi;
311 : extern void zebra_evpn_mh_init(void);
312 : extern void zebra_evpn_mh_terminate(void);
313 : extern bool zebra_evpn_is_if_es_capable(struct zebra_if *zif);
314 : extern void zebra_evpn_if_init(struct zebra_if *zif);
315 : extern void zebra_evpn_if_cleanup(struct zebra_if *zif);
316 : extern void zebra_evpn_es_evi_init(struct zebra_evpn *zevpn);
317 : extern void zebra_evpn_es_evi_cleanup(struct zebra_evpn *zevpn);
318 : extern void zebra_evpn_vxl_evpn_set(struct zebra_if *zif,
319 : struct zebra_evpn *zevpn, bool set);
320 : extern void zebra_evpn_es_set_base_evpn(struct zebra_evpn *zevpn);
321 : extern void zebra_evpn_es_clear_base_evpn(struct zebra_evpn *zevpn);
322 : extern void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif);
323 : extern void zebra_evpn_vl_vxl_deref(uint16_t vid, struct zebra_if *vxlan_zif);
324 : extern void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif);
325 : extern void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif);
326 : extern void zebra_evpn_es_send_all_to_client(bool add);
327 : extern void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up);
328 : extern void zebra_evpn_es_show(struct vty *vty, bool uj);
329 : extern void zebra_evpn_es_show_detail(struct vty *vty, bool uj);
330 : extern void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi);
331 : extern void zebra_evpn_update_all_es(struct zebra_evpn *zevpn);
332 : extern void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS);
333 : int zebra_evpn_remote_es_add(const esi_t *esi, struct in_addr vtep_ip,
334 : bool esr_rxed, uint8_t df_alg, uint16_t df_pref);
335 : int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip);
336 : extern void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail);
337 : extern void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj,
338 : vni_t vni, int detail);
339 : extern void zebra_evpn_es_mac_deref_entry(struct zebra_mac *mac);
340 : extern bool zebra_evpn_es_mac_ref_entry(struct zebra_mac *mac,
341 : struct zebra_evpn_es *es);
342 : extern bool zebra_evpn_es_mac_ref(struct zebra_mac *mac, const esi_t *esi);
343 : extern struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi);
344 : extern void zebra_evpn_interface_init(void);
345 : extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp);
346 : extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj);
347 : extern void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj);
348 : extern void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid);
349 : extern void zebra_evpn_if_es_print(struct vty *vty, json_object *json,
350 : struct zebra_if *zif);
351 : extern void zebra_evpn_es_cleanup(void);
352 : extern int zebra_evpn_mh_mac_holdtime_update(struct vty *vty,
353 : uint32_t duration, bool set_default);
354 : void zebra_evpn_mh_config_write(struct vty *vty);
355 : int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
356 : uint32_t duration, bool set_default);
357 : void zebra_evpn_es_local_br_port_update(struct zebra_if *zif);
358 : extern int zebra_evpn_mh_startup_delay_update(struct vty *vty,
359 : uint32_t duration,
360 : bool set_default);
361 : extern void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif);
362 : extern void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif,
363 : bool clear,
364 : const char *caller);
365 : extern bool zebra_evpn_is_es_bond(struct interface *ifp);
366 : extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
367 : extern void zebra_evpn_mh_print(struct vty *vty);
368 : extern void zebra_evpn_mh_json(json_object *json);
369 : extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
370 : struct zebra_evpn_es **local_es);
371 : extern int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off);
372 : extern void zebra_evpn_l2_nh_show(struct vty *vty, bool uj);
373 : extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
374 : struct zebra_if *br_zif, bool is_up);
375 : extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
376 : extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
377 : struct interface *ifp, bool bypass);
378 : extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
379 : extern struct zebra_evpn_es_evi *
380 : zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
381 :
382 : #endif /* _ZEBRA_EVPN_MH_H */
|