]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_evpn_mh.h
zebra: support for slow-failover of local MACs on an ES
[mirror_frr.git] / zebra / zebra_evpn_mh.h
CommitLineData
ce5160c0
AK
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
31#define EVPN_MH_VTY_STR "Multihoming\n"
32
33/* Ethernet Segment entry -
34 * - Local and remote ESs are maintained in a global RB tree,
35 * zmh_info->es_rb_tree using ESI as key
36 * - Local ESs are added via zebra config (ZEBRA_EVPNES_LOCAL) when an
37 * access port is associated with an ES-ID
38 * - Remotes ESs are added by BGP based on received/remote EAD/Type-1 routes
39 * (ZEBRA_EVPNES_REMOTE)
40 * - An ES can be simulatenously LOCAL and REMOTE; infact all LOCAL ESs are
41 * expected to have REMOTE ES peers.
42 */
43struct zebra_evpn_es {
44 esi_t esi;
45 char esi_str[ESI_STR_LEN];
46
47 /* ES flags */
48 uint32_t flags;
49#define ZEBRA_EVPNES_LOCAL (1 << 0) /* configured in zebra */
50#define ZEBRA_EVPNES_REMOTE (1 << 1) /* added by bgp */
51#define ZEBRA_EVPNES_OPER_UP (1 << 2) /* es->ifp is oper-up */
52#define ZEBRA_EVPNES_READY_FOR_BGP (1 << 3) /* ready to be sent to BGP */
53#define ZEBRA_EVPNES_NHG_ACTIVE (1 << 4) /* NHG has been installed */
1103c5c6
AK
54/* This flag is only applicable to local ESs and signifies that this
55 * VTEP is not the DF
56 */
57#define ZEBRA_EVPNES_NON_DF (1 << 5)
28e80a03
AK
58/* When the ES becomes a bridge port we need to activate the BUM non-DF
59 * filter, SPH filter and backup NHG for fast-failover
60 */
61#define ZEBRA_EVPNES_BR_PORT (1 << 6)
ce5160c0
AK
62
63 /* memory used for adding the es to zmh_info->es_rb_tree */
64 RB_ENTRY(zebra_evpn_es) rb_node;
65
66 /* [EVPNES_LOCAL] memory used for linking the es to
67 * zmh_info->local_es_list
68 */
69 struct listnode local_es_listnode;
70
71 /* [EVPNES_LOCAL] corresponding interface */
72 struct zebra_if *zif;
73
74 /* list of ES-EVIs associated with the ES */
75 struct list *es_evi_list;
76
77 /* [!EVPNES_LOCAL] List of remote VTEPs (zebra_evpn_es_vtep) */
78 struct list *es_vtep_list;
79
b169fd6f
AK
80 /* list of zebra_mac entries using this ES as destination */
81 struct list *mac_list;
ce5160c0
AK
82
83 /* Nexthop group id */
84 uint32_t nhg_id;
1103c5c6
AK
85
86 /* Preference config for BUM-DF election. Sent to BGP and
87 * advertised via the ESR
88 */
89 uint16_t df_pref;
ce5160c0
AK
90};
91RB_HEAD(zebra_es_rb_head, zebra_evpn_es);
92RB_PROTOTYPE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
93
94/* ES per-EVI info
87d76d54
PR
95 * - ES-EVIs are maintained per-EVPN (vni->es_evi_rb_tree)
96 * - Local ES-EVIs are linked to per-EVPN list for quick access
ce5160c0
AK
97 * - Although some infrastucture is present for remote ES-EVIs, currently
98 * BGP does NOT send remote ES-EVIs to zebra. This may change in the
99 * future (but must be changed thoughtfully and only if needed as ES-EVI
100 * can get prolific and come in the way of rapid failovers)
101 */
102struct zebra_evpn_es_evi {
103 struct zebra_evpn_es *es;
87d76d54 104 zebra_evpn_t *zevpn;
ce5160c0
AK
105
106 /* ES-EVI flags */
107 uint32_t flags;
108 /* local ES-EVI */
109#define ZEBRA_EVPNES_EVI_LOCAL (1 << 0) /* created by zebra */
110#define ZEBRA_EVPNES_EVI_READY_FOR_BGP (1 << 1) /* ready to be sent to BGP */
111
112 /* memory used for adding the es_evi to
87d76d54 113 * es_evi->zevpn->es_evi_rb_tree
ce5160c0
AK
114 */
115 RB_ENTRY(zebra_evpn_es_evi) rb_node;
116 /* memory used for linking the es_evi to
87d76d54 117 * es_evi->zevpn->local_es_evi_list
ce5160c0
AK
118 */
119 struct listnode l2vni_listnode;
120 /* memory used for linking the es_evi to
121 * es_evi->es->es_evi_list
122 */
123 struct listnode es_listnode;
124};
125
126/* PE attached to an ES */
127struct zebra_evpn_es_vtep {
128 struct zebra_evpn_es *es; /* parent ES */
129 struct in_addr vtep_ip;
130
1103c5c6
AK
131 uint32_t flags;
132 /* Rxed Type-4 route from this VTEP */
133#define ZEBRA_EVPNES_VTEP_RXED_ESR (1 << 0)
28e80a03 134#define ZEBRA_EVPNES_VTEP_DEL_IN_PROG (1 << 1)
1103c5c6 135
ce5160c0
AK
136 /* memory used for adding the entry to es->es_vtep_list */
137 struct listnode es_listnode;
138
139 /* MAC nexthop */
140 uint32_t nh_id;
141
1103c5c6
AK
142 /* Parameters for DF election */
143 uint8_t df_alg;
144 uint32_t df_pref;
145
ce5160c0
AK
146 /* XXX - maintain a backpointer to zebra_vtep_t */
147};
148
149/* Local/access-side broadcast domain - zebra_evpn_access_bd is added to -
150 * zrouter->evpn_vlan_table (for VLAN aware bridges) OR
151 * zrouter->evpn_bridge_table (for VLAN unaware bridges)
152 * XXX - support for VLAN unaware bridges is yet to be flushed out
153 */
154struct zebra_evpn_access_bd {
155 vlanid_t vid;
156
157 struct zebra_if *vxlan_zif; /* vxlan device */
158 /* list of members associated with the BD i.e. (potential) ESs */
159 struct list *mbr_zifs;
87d76d54
PR
160 /* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
161 zebra_evpn_t *zevpn;
ce5160c0
AK
162};
163
164/* multihoming information stored in zrouter */
165#define zmh_info (zrouter.mh_info)
166struct zebra_evpn_mh_info {
b2ee2b71 167 uint32_t flags;
15400f95
AK
168/* If the dataplane is not capable of handling a backup NHG on an access
169 * port we will need to explicitly failover each MAC entry on
170 * local ES down
171 */
172#define ZEBRA_EVPN_MH_REDIRECT_OFF (1 << 0)
b2ee2b71
AK
173/* DAD support for EVPN-MH is yet to be added. So on detection of
174 * first local ES, DAD is turned off
175 */
176#define ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF (1 << 1)
177
ce5160c0
AK
178 /* RB tree of Ethernet segments (used for EVPN-MH) */
179 struct zebra_es_rb_head es_rb_tree;
180 /* List of local ESs */
181 struct list *local_es_list;
182
183 /* EVPN MH broadcast domains indexed by the VID */
184 struct hash *evpn_vlan_table;
185
186 /* A base L2-VNI is maintained to derive parameters such as
187 * ES originator-IP.
188 * XXX: once single vxlan device model becomes available this will
189 * not be necessary
190 */
87d76d54 191 zebra_evpn_t *es_base_evpn;
ce5160c0
AK
192 struct in_addr es_originator_ip;
193
194 /* L2 NH and NHG ids -
195 * Most significant 8 bits is type. Lower 24 bits is the value
196 * allocated from the nh_id_bitmap.
197 */
198 bitfield_t nh_id_bitmap;
199#define EVPN_NH_ID_MAX (16*1024)
200#define EVPN_NH_ID_VAL_MASK 0xffffff
201#define EVPN_NH_ID_TYPE_POS 24
202/* The purpose of using different types for NHG and NH is NOT to manage the
203 * id space separately. It is simply to make debugging easier.
204 */
205#define EVPN_NH_ID_TYPE_BIT (1 << EVPN_NH_ID_TYPE_POS)
206#define EVPN_NHG_ID_TYPE_BIT (2 << EVPN_NH_ID_TYPE_POS)
15400f95
AK
207 /* L2-NHG table - key: nhg_id, data: zebra_evpn_es */
208 struct hash *nhg_table;
b169fd6f
AK
209
210 /* XXX - re-visit the default hold timer value */
c36e442c
AK
211 int mac_hold_time;
212#define ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF (18 * 60)
213 int neigh_hold_time;
214#define ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF (18 * 60)
215
216 /* During this period access ports will be held in a protodown
217 * state
218 */
219 int startup_delay_time; /* seconds */
220#define ZEBRA_EVPN_MH_STARTUP_DELAY_DEF (3 * 60)
221 struct thread *startup_delay_timer;
222
223 /* Number of configured uplinks */
224 uint32_t uplink_cfg_cnt;
225 /* Number of operationally-up uplinks */
226 uint32_t uplink_oper_up_cnt;
227
228 /* These protodown bits are inherited by all ES bonds */
229 enum protodown_reasons protodown_rc;
ce5160c0
AK
230};
231
232static inline bool zebra_evpn_mac_is_es_local(zebra_mac_t *mac)
233{
234 return mac->es && (mac->es->flags & ZEBRA_EVPNES_LOCAL);
235}
236
237/* Returns true if the id is of L2-NHG or L2-NH type */
238static inline bool zebra_evpn_mh_is_fdb_nh(uint32_t id)
239{
240 return ((id & EVPN_NHG_ID_TYPE_BIT) ||
241 (id & EVPN_NH_ID_TYPE_BIT));
242}
243
15400f95
AK
244static inline bool
245zebra_evpn_es_local_mac_via_network_port(struct zebra_evpn_es *es)
246{
247 return !(es->flags & ZEBRA_EVPNES_OPER_UP)
248 && (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF);
249}
250
b2ee2b71
AK
251static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
252{
253 return !(zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF);
254}
255
ce5160c0
AK
256/*****************************************************************************/
257extern esi_t *zero_esi;
258extern void zebra_evpn_mh_init(void);
259extern void zebra_evpn_mh_terminate(void);
260extern bool zebra_evpn_is_if_es_capable(struct zebra_if *zif);
261extern void zebra_evpn_if_init(struct zebra_if *zif);
262extern void zebra_evpn_if_cleanup(struct zebra_if *zif);
945ee7b2
AK
263extern void zebra_evpn_es_evi_init(zebra_evpn_t *zevpn);
264extern void zebra_evpn_es_evi_cleanup(zebra_evpn_t *zevpn);
87d76d54 265extern void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, zebra_evpn_t *zevpn,
ce5160c0 266 bool set);
87d76d54
PR
267extern void zebra_evpn_es_set_base_evpn(zebra_evpn_t *zevpn);
268extern void zebra_evpn_es_clear_base_evpn(zebra_evpn_t *zevpn);
ce5160c0
AK
269extern void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif);
270extern void zebra_evpn_vl_vxl_deref(uint16_t vid, struct zebra_if *vxlan_zif);
271extern void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif);
272extern void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif);
273extern void zebra_evpn_es_send_all_to_client(bool add);
274extern void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up);
275extern void zebra_evpn_es_show(struct vty *vty, bool uj);
276extern void zebra_evpn_es_show_detail(struct vty *vty, bool uj);
277extern void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi);
87d76d54 278extern void zebra_evpn_update_all_es(zebra_evpn_t *zevpn);
ce5160c0
AK
279extern void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS);
280extern void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail);
281extern void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj,
282 vni_t vni, int detail);
283extern void zebra_evpn_es_mac_deref_entry(zebra_mac_t *mac);
284extern bool zebra_evpn_es_mac_ref_entry(zebra_mac_t *mac,
285 struct zebra_evpn_es *es);
b169fd6f 286extern bool zebra_evpn_es_mac_ref(zebra_mac_t *mac, esi_t *esi);
ce5160c0
AK
287extern struct zebra_evpn_es *zebra_evpn_es_find(esi_t *esi);
288extern void zebra_evpn_interface_init(void);
289extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp);
290extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj);
291extern void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj);
292extern void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid);
293extern void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif);
294extern void zebra_evpn_es_cleanup(void);
b169fd6f
AK
295extern int zebra_evpn_mh_mac_holdtime_update(struct vty *vty,
296 uint32_t duration, bool set_default);
297void zebra_evpn_mh_config_write(struct vty *vty);
298int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
299 uint32_t duration, bool set_default);
72f2674a 300void zebra_evpn_es_local_br_port_update(struct zebra_if *zif);
c36e442c
AK
301extern int zebra_evpn_mh_startup_delay_update(struct vty *vty,
302 uint32_t duration,
303 bool set_default);
304extern void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif);
305extern void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif,
306 bool clear,
307 const char *caller);
308extern bool zebra_evpn_is_es_bond(struct interface *ifp);
309extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
310extern void zebra_evpn_mh_print(struct vty *vty);
311extern void zebra_evpn_mh_json(json_object *json);
15400f95
AK
312extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
313 struct zebra_evpn_es **local_es);
314extern int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off);
ce5160c0
AK
315
316#endif /* _ZEBRA_EVPN_MH_H */