]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_evpn_mh.h
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / zebra_evpn_mh.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
ce5160c0
AK
2/*
3 * Zebra EVPN MH Data structures and definitions
4 *
5 * Copyright (C) 2019 Cumulus Networks, Inc.
6 * Anuradha Karuppiah
ce5160c0
AK
7 */
8
9#ifndef _ZEBRA_EVPN_MH_H
10#define _ZEBRA_EVPN_MH_H
11
12#include <zebra.h>
13
14#include "if.h"
15#include "linklist.h"
16#include "bitfield.h"
17#include "zebra_vxlan.h"
18#include "zebra_vxlan_private.h"
4f9bb78e 19#include "zebra_nhg.h"
ce5160c0
AK
20
21#define EVPN_MH_VTY_STR "Multihoming\n"
22
23/* Ethernet Segment entry -
24 * - Local and remote ESs are maintained in a global RB tree,
25 * zmh_info->es_rb_tree using ESI as key
26 * - Local ESs are added via zebra config (ZEBRA_EVPNES_LOCAL) when an
27 * access port is associated with an ES-ID
28 * - Remotes ESs are added by BGP based on received/remote EAD/Type-1 routes
29 * (ZEBRA_EVPNES_REMOTE)
b0b9a2fe 30 * - An ES can be simultaneously LOCAL and REMOTE; infact all LOCAL ESs are
ce5160c0
AK
31 * expected to have REMOTE ES peers.
32 */
33struct zebra_evpn_es {
34 esi_t esi;
35 char esi_str[ESI_STR_LEN];
36
37 /* ES flags */
38 uint32_t flags;
39#define ZEBRA_EVPNES_LOCAL (1 << 0) /* configured in zebra */
40#define ZEBRA_EVPNES_REMOTE (1 << 1) /* added by bgp */
41#define ZEBRA_EVPNES_OPER_UP (1 << 2) /* es->ifp is oper-up */
42#define ZEBRA_EVPNES_READY_FOR_BGP (1 << 3) /* ready to be sent to BGP */
43#define ZEBRA_EVPNES_NHG_ACTIVE (1 << 4) /* NHG has been installed */
1103c5c6
AK
44/* This flag is only applicable to local ESs and signifies that this
45 * VTEP is not the DF
46 */
47#define ZEBRA_EVPNES_NON_DF (1 << 5)
28e80a03
AK
48/* When the ES becomes a bridge port we need to activate the BUM non-DF
49 * filter, SPH filter and backup NHG for fast-failover
50 */
51#define ZEBRA_EVPNES_BR_PORT (1 << 6)
00a7710c
AK
52/* ES is in bypass mode i.e. must not be advertised. ES-bypass is set
53 * when the associated host bond goes into LACP bypass
54 */
55#define ZEBRA_EVPNES_BYPASS (1 << 7)
ce5160c0
AK
56
57 /* memory used for adding the es to zmh_info->es_rb_tree */
58 RB_ENTRY(zebra_evpn_es) rb_node;
59
60 /* [EVPNES_LOCAL] memory used for linking the es to
61 * zmh_info->local_es_list
62 */
63 struct listnode local_es_listnode;
64
65 /* [EVPNES_LOCAL] corresponding interface */
66 struct zebra_if *zif;
67
68 /* list of ES-EVIs associated with the ES */
69 struct list *es_evi_list;
70
71 /* [!EVPNES_LOCAL] List of remote VTEPs (zebra_evpn_es_vtep) */
72 struct list *es_vtep_list;
73
b169fd6f
AK
74 /* list of zebra_mac entries using this ES as destination */
75 struct list *mac_list;
ce5160c0
AK
76
77 /* Nexthop group id */
78 uint32_t nhg_id;
1103c5c6
AK
79
80 /* Preference config for BUM-DF election. Sent to BGP and
81 * advertised via the ESR
82 */
83 uint16_t df_pref;
35f5c31b
AK
84
85 /* When a new ES is configured it is held in a non-DF state
86 * for 3 seconds. This allows the peer Type-4 routes to be
87 * imported before running the DF election.
88 */
89#define ZEBRA_EVPN_MH_DF_DELAY_TIME 3 /* seconds */
90 struct thread *df_delay_timer;
ce5160c0
AK
91};
92RB_HEAD(zebra_es_rb_head, zebra_evpn_es);
93RB_PROTOTYPE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
94
95/* ES per-EVI info
87d76d54
PR
96 * - ES-EVIs are maintained per-EVPN (vni->es_evi_rb_tree)
97 * - Local ES-EVIs are linked to per-EVPN list for quick access
ce5160c0
AK
98 * - Although some infrastucture is present for remote ES-EVIs, currently
99 * BGP does NOT send remote ES-EVIs to zebra. This may change in the
100 * future (but must be changed thoughtfully and only if needed as ES-EVI
101 * can get prolific and come in the way of rapid failovers)
102 */
103struct zebra_evpn_es_evi {
104 struct zebra_evpn_es *es;
f6371c34 105 struct zebra_evpn *zevpn;
ce5160c0
AK
106
107 /* ES-EVI flags */
108 uint32_t flags;
109 /* local ES-EVI */
110#define ZEBRA_EVPNES_EVI_LOCAL (1 << 0) /* created by zebra */
111#define ZEBRA_EVPNES_EVI_READY_FOR_BGP (1 << 1) /* ready to be sent to BGP */
112
113 /* memory used for adding the es_evi to
87d76d54 114 * es_evi->zevpn->es_evi_rb_tree
ce5160c0
AK
115 */
116 RB_ENTRY(zebra_evpn_es_evi) rb_node;
117 /* memory used for linking the es_evi to
87d76d54 118 * es_evi->zevpn->local_es_evi_list
ce5160c0
AK
119 */
120 struct listnode l2vni_listnode;
121 /* memory used for linking the es_evi to
122 * es_evi->es->es_evi_list
123 */
124 struct listnode es_listnode;
125};
126
5de10c37
AK
127/* A single L2 nexthop is allocated across all ESs with the same PE/VTEP
128 * nexthop
129 */
130struct zebra_evpn_l2_nh {
131 struct in_addr vtep_ip;
132
133 /* MAC nexthop id */
134 uint32_t nh_id;
135
136 /* es_vtep entries using this nexthop */
137 uint32_t ref_cnt;
138};
139
ce5160c0
AK
140/* PE attached to an ES */
141struct zebra_evpn_es_vtep {
142 struct zebra_evpn_es *es; /* parent ES */
143 struct in_addr vtep_ip;
144
1103c5c6
AK
145 uint32_t flags;
146 /* Rxed Type-4 route from this VTEP */
147#define ZEBRA_EVPNES_VTEP_RXED_ESR (1 << 0)
28e80a03 148#define ZEBRA_EVPNES_VTEP_DEL_IN_PROG (1 << 1)
1103c5c6 149
5de10c37
AK
150 /* MAC nexthop info */
151 struct zebra_evpn_l2_nh *nh;
152
ce5160c0
AK
153 /* memory used for adding the entry to es->es_vtep_list */
154 struct listnode es_listnode;
155
1103c5c6
AK
156 /* Parameters for DF election */
157 uint8_t df_alg;
158 uint32_t df_pref;
159
c172c032 160 /* XXX - maintain a backpointer to struct zebra_vtep */
ce5160c0
AK
161};
162
163/* Local/access-side broadcast domain - zebra_evpn_access_bd is added to -
164 * zrouter->evpn_vlan_table (for VLAN aware bridges) OR
165 * zrouter->evpn_bridge_table (for VLAN unaware bridges)
166 * XXX - support for VLAN unaware bridges is yet to be flushed out
167 */
168struct zebra_evpn_access_bd {
169 vlanid_t vid;
170
239b26f9
SR
171 ifindex_t bridge_ifindex;
172 struct zebra_if *bridge_zif; /* associated bridge */
173
8d30ff3b 174 vni_t vni; /* vni associated with the vxlan device */
ce5160c0
AK
175 struct zebra_if *vxlan_zif; /* vxlan device */
176 /* list of members associated with the BD i.e. (potential) ESs */
177 struct list *mbr_zifs;
87d76d54 178 /* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
f6371c34 179 struct zebra_evpn *zevpn;
243b74ed
AK
180 /* SVI associated with the VLAN */
181 struct zebra_if *vlan_zif;
ce5160c0
AK
182};
183
184/* multihoming information stored in zrouter */
185#define zmh_info (zrouter.mh_info)
186struct zebra_evpn_mh_info {
b2ee2b71 187 uint32_t flags;
15400f95
AK
188/* If the dataplane is not capable of handling a backup NHG on an access
189 * port we will need to explicitly failover each MAC entry on
190 * local ES down
191 */
192#define ZEBRA_EVPN_MH_REDIRECT_OFF (1 << 0)
b2ee2b71
AK
193/* DAD support for EVPN-MH is yet to be added. So on detection of
194 * first local ES, DAD is turned off
195 */
196#define ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF (1 << 1)
c7bfd085
AK
197/* If EVPN MH is enabled we only advertise REACHABLE neigh entries as Type-2
198 * routes. As there is no global config knob for enabling EVPN MH we turn
199 * this flag when the first local ES is detected.
200 */
201#define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
243b74ed
AK
202/* If EVPN MH is enabled we advertise the SVI MAC address to avoid
203 * flooding of ARP replies rxed from the multi-homed host
204 */
205#define ZEBRA_EVPN_MH_ADV_SVI_MAC (1 << 3)
b2ee2b71 206
ce5160c0
AK
207 /* RB tree of Ethernet segments (used for EVPN-MH) */
208 struct zebra_es_rb_head es_rb_tree;
209 /* List of local ESs */
210 struct list *local_es_list;
211
212 /* EVPN MH broadcast domains indexed by the VID */
213 struct hash *evpn_vlan_table;
214
215 /* A base L2-VNI is maintained to derive parameters such as
216 * ES originator-IP.
217 * XXX: once single vxlan device model becomes available this will
218 * not be necessary
219 */
f6371c34 220 struct zebra_evpn *es_base_evpn;
ce5160c0
AK
221 struct in_addr es_originator_ip;
222
223 /* L2 NH and NHG ids -
4f9bb78e 224 * Most significant 4 bits is type. Lower 28 bits is the value
ce5160c0
AK
225 * allocated from the nh_id_bitmap.
226 */
227 bitfield_t nh_id_bitmap;
228#define EVPN_NH_ID_MAX (16*1024)
229#define EVPN_NH_ID_VAL_MASK 0xffffff
ce5160c0
AK
230/* The purpose of using different types for NHG and NH is NOT to manage the
231 * id space separately. It is simply to make debugging easier.
232 */
4f9bb78e
AK
233#define EVPN_NH_ID_TYPE_BIT (NHG_TYPE_L2_NH << NHG_ID_TYPE_POS)
234#define EVPN_NHG_ID_TYPE_BIT (NHG_TYPE_L2 << NHG_ID_TYPE_POS)
15400f95
AK
235 /* L2-NHG table - key: nhg_id, data: zebra_evpn_es */
236 struct hash *nhg_table;
5de10c37
AK
237 /* L2-NH table - key: vtep_up, data: zebra_evpn_nh */
238 struct hash *nh_ip_table;
b169fd6f
AK
239
240 /* XXX - re-visit the default hold timer value */
c36e442c
AK
241 int mac_hold_time;
242#define ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF (18 * 60)
243 int neigh_hold_time;
244#define ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF (18 * 60)
245
246 /* During this period access ports will be held in a protodown
247 * state
248 */
249 int startup_delay_time; /* seconds */
250#define ZEBRA_EVPN_MH_STARTUP_DELAY_DEF (3 * 60)
251 struct thread *startup_delay_timer;
252
253 /* Number of configured uplinks */
254 uint32_t uplink_cfg_cnt;
255 /* Number of operationally-up uplinks */
256 uint32_t uplink_oper_up_cnt;
257
258 /* These protodown bits are inherited by all ES bonds */
5d414138 259 uint32_t protodown_rc;
ce5160c0
AK
260};
261
e4c3ece6 262/* returns TRUE if the EVPN is ready to be sent to BGP */
f6371c34 263static inline bool zebra_evpn_send_to_client_ok(struct zebra_evpn *zevpn)
e4c3ece6
AK
264{
265 return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
266}
267
3198b2b3 268static inline bool zebra_evpn_mac_is_es_local(struct zebra_mac *mac)
ce5160c0
AK
269{
270 return mac->es && (mac->es->flags & ZEBRA_EVPNES_LOCAL);
271}
272
273/* Returns true if the id is of L2-NHG or L2-NH type */
274static inline bool zebra_evpn_mh_is_fdb_nh(uint32_t id)
275{
276 return ((id & EVPN_NHG_ID_TYPE_BIT) ||
277 (id & EVPN_NH_ID_TYPE_BIT));
278}
279
15400f95
AK
280static inline bool
281zebra_evpn_es_local_mac_via_network_port(struct zebra_evpn_es *es)
282{
283 return !(es->flags & ZEBRA_EVPNES_OPER_UP)
284 && (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF);
285}
286
b2ee2b71
AK
287static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
288{
289 return !(zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF);
290}
291
c7bfd085
AK
292static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
293{
294 return !!(zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY);
295}
296
243b74ed
AK
297static inline bool zebra_evpn_mh_do_adv_svi_mac(void)
298{
299 return zmh_info && (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC);
300}
c7bfd085 301
ce5160c0
AK
302/*****************************************************************************/
303extern esi_t *zero_esi;
304extern void zebra_evpn_mh_init(void);
305extern void zebra_evpn_mh_terminate(void);
306extern bool zebra_evpn_is_if_es_capable(struct zebra_if *zif);
307extern void zebra_evpn_if_init(struct zebra_if *zif);
308extern void zebra_evpn_if_cleanup(struct zebra_if *zif);
f6371c34
DS
309extern void zebra_evpn_es_evi_init(struct zebra_evpn *zevpn);
310extern void zebra_evpn_es_evi_cleanup(struct zebra_evpn *zevpn);
311extern void zebra_evpn_vxl_evpn_set(struct zebra_if *zif,
312 struct zebra_evpn *zevpn, bool set);
313extern void zebra_evpn_es_set_base_evpn(struct zebra_evpn *zevpn);
314extern void zebra_evpn_es_clear_base_evpn(struct zebra_evpn *zevpn);
8d30ff3b
SR
315extern void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id,
316 struct zebra_if *vxlan_zif);
317extern void zebra_evpn_vl_vxl_deref(uint16_t vid, vni_t vni_id,
318 struct zebra_if *vxlan_zif);
ce5160c0
AK
319extern void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif);
320extern void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif);
321extern void zebra_evpn_es_send_all_to_client(bool add);
322extern void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up);
323extern void zebra_evpn_es_show(struct vty *vty, bool uj);
324extern void zebra_evpn_es_show_detail(struct vty *vty, bool uj);
325extern void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi);
f6371c34 326extern void zebra_evpn_update_all_es(struct zebra_evpn *zevpn);
ce5160c0 327extern void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS);
32367e7a
MS
328int zebra_evpn_remote_es_add(const esi_t *esi, struct in_addr vtep_ip,
329 bool esr_rxed, uint8_t df_alg, uint16_t df_pref);
330int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip);
ce5160c0
AK
331extern void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail);
332extern void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj,
333 vni_t vni, int detail);
3198b2b3
DS
334extern void zebra_evpn_es_mac_deref_entry(struct zebra_mac *mac);
335extern bool zebra_evpn_es_mac_ref_entry(struct zebra_mac *mac,
1a3bd37f 336 struct zebra_evpn_es *es);
3198b2b3 337extern bool zebra_evpn_es_mac_ref(struct zebra_mac *mac, const esi_t *esi);
32367e7a 338extern struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi);
ce5160c0
AK
339extern void zebra_evpn_interface_init(void);
340extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp);
341extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj);
342extern void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj);
c15dc24f
RW
343extern void zebra_evpn_if_es_print(struct vty *vty, json_object *json,
344 struct zebra_if *zif);
239b26f9
SR
345extern struct zebra_evpn_access_bd *
346zebra_evpn_acc_vl_find(vlanid_t vid, struct interface *br_if);
347extern void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid,
348 struct interface *br_if);
ce5160c0 349extern void zebra_evpn_es_cleanup(void);
b169fd6f
AK
350extern int zebra_evpn_mh_mac_holdtime_update(struct vty *vty,
351 uint32_t duration, bool set_default);
352void zebra_evpn_mh_config_write(struct vty *vty);
353int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
354 uint32_t duration, bool set_default);
72f2674a 355void zebra_evpn_es_local_br_port_update(struct zebra_if *zif);
c36e442c
AK
356extern int zebra_evpn_mh_startup_delay_update(struct vty *vty,
357 uint32_t duration,
358 bool set_default);
359extern void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif);
360extern void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif,
361 bool clear,
362 const char *caller);
363extern bool zebra_evpn_is_es_bond(struct interface *ifp);
364extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
365extern void zebra_evpn_mh_print(struct vty *vty);
366extern void zebra_evpn_mh_json(json_object *json);
15400f95
AK
367extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
368 struct zebra_evpn_es **local_es);
369extern int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off);
5de10c37 370extern void zebra_evpn_l2_nh_show(struct vty *vty, bool uj);
243b74ed
AK
371extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
372 struct zebra_if *br_zif, bool is_up);
373extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
239b26f9
SR
374extern void
375zebra_evpn_access_bd_bridge_cleanup(vlanid_t vid, struct interface *br_if,
376 struct zebra_evpn_access_bd *acc_bd);
00a7710c
AK
377extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
378 struct interface *ifp, bool bypass);
7bfa7d02 379extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
09de6e45
AK
380extern struct zebra_evpn_es_evi *
381zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
ce5160c0
AK
382
383#endif /* _ZEBRA_EVPN_MH_H */