1 /*
2  * Zebra EVPN multihoming code
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 #include <zebra.h>
21 
22 #include "command.h"
23 #include "hash.h"
24 #include "if.h"
25 #include "jhash.h"
26 #include "linklist.h"
27 #include "log.h"
28 #include "memory.h"
29 #include "prefix.h"
30 #include "stream.h"
31 #include "table.h"
32 #include "vlan.h"
33 #include "vxlan.h"
34 
35 #include "zebra/zebra_router.h"
36 #include "zebra/debug.h"
37 #include "zebra/interface.h"
38 #include "zebra/rib.h"
39 #include "zebra/rt.h"
40 #include "zebra/rt_netlink.h"
41 #include "zebra/zebra_errors.h"
42 #include "zebra/zebra_l2.h"
43 #include "zebra/zebra_memory.h"
44 #include "zebra/zebra_ns.h"
45 #include "zebra/zebra_vrf.h"
46 #include "zebra/zebra_vxlan.h"
47 #include "zebra/zebra_evpn.h"
48 #include "zebra/zebra_evpn_mac.h"
49 #include "zebra/zebra_vxlan_private.h"
50 #include "zebra/zebra_router.h"
51 #include "zebra/zebra_evpn_mh.h"
52 #include "zebra/zebra_nhg.h"
53 
54 DEFINE_MTYPE_STATIC(ZEBRA, ZACC_BD, "Access Broadcast Domain");
55 DEFINE_MTYPE_STATIC(ZEBRA, ZES, "Ethernet Segment");
56 DEFINE_MTYPE_STATIC(ZEBRA, ZES_EVI, "ES info per-EVI");
57 DEFINE_MTYPE_STATIC(ZEBRA, ZMH_INFO, "MH global info");
58 DEFINE_MTYPE_STATIC(ZEBRA, ZES_VTEP, "VTEP attached to the ES");
59 
60 static void zebra_evpn_es_get_one_base_evpn(void);
61 static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
62 		zebra_evpn_t *zevpn, bool add);
63 static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp);
64 static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid,
65 		struct ethaddr *sysmac);
66 
67 esi_t zero_esi_buf, *zero_esi = &zero_esi_buf;
68 
69 /*****************************************************************************/
70 /* Ethernet Segment to EVI association -
71  * 1. The ES-EVI entry is maintained as a RB tree per L2-VNI
72  * (zebra_evpn_t.es_evi_rb_tree).
73  * 2. Each local ES-EVI entry is sent to BGP which advertises it as an
74  * EAD-EVI (Type-1 EVPN) route
75  * 3. Local ES-EVI setup is re-evaluated on the following triggers -
76  *    a. When an ESI is set or cleared on an access port.
77  *    b. When an access port associated with an ESI is deleted.
78  *    c. When VLAN member ship changes on an access port.
79  *    d. When a VXLAN_IF is set or cleared on an access broadcast domain.
80  *    e. When a L2-VNI is added or deleted for a VxLAN_IF.
81  * 4. Currently zebra doesn't remote ES-EVIs. Those are managed and maintained
82  * entirely in BGP which consolidates them into a remote ES. The remote ES
83  * is then sent to zebra which allocates a NHG for it.
84  */
85 
86 /* compare ES-IDs for the ES-EVI RB tree maintained per-EVPN */
zebra_es_evi_rb_cmp(const struct zebra_evpn_es_evi * es_evi1,const struct zebra_evpn_es_evi * es_evi2)87 static int zebra_es_evi_rb_cmp(const struct zebra_evpn_es_evi *es_evi1,
88 		const struct zebra_evpn_es_evi *es_evi2)
89 {
90 	return memcmp(&es_evi1->es->esi, &es_evi2->es->esi, ESI_BYTES);
91 }
92 RB_GENERATE(zebra_es_evi_rb_head, zebra_evpn_es_evi,
93 		rb_node, zebra_es_evi_rb_cmp);
94 
95 /* allocate a new ES-EVI and insert it into the per-L2-VNI and per-ES
96  * tables.
97  */
zebra_evpn_es_evi_new(struct zebra_evpn_es * es,zebra_evpn_t * zevpn)98 static struct zebra_evpn_es_evi *zebra_evpn_es_evi_new(struct zebra_evpn_es *es,
99 		zebra_evpn_t *zevpn)
100 {
101 	struct zebra_evpn_es_evi *es_evi;
102 
103 	es_evi = XCALLOC(MTYPE_ZES_EVI, sizeof(struct zebra_evpn_es_evi));
104 
105 	es_evi->es = es;
106 	es_evi->zevpn = zevpn;
107 
108 	/* insert into the EVPN-ESI rb tree */
109 	if (RB_INSERT(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree, es_evi)) {
110 		XFREE(MTYPE_ZES_EVI, es_evi);
111 		return NULL;
112 	}
113 
114 	/* add to the ES's VNI list */
115 	listnode_init(&es_evi->es_listnode, es_evi);
116 	listnode_add(es->es_evi_list, &es_evi->es_listnode);
117 
118 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
119 		zlog_debug("es %s evi %d new",
120 				es_evi->es->esi_str, es_evi->zevpn->vni);
121 
122 	return es_evi;
123 }
124 
125 /* returns TRUE if the EVPN is ready to be sent to BGP */
zebra_evpn_send_to_client_ok(zebra_evpn_t * zevpn)126 static inline bool zebra_evpn_send_to_client_ok(zebra_evpn_t *zevpn)
127 {
128 	return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
129 }
130 
131 /* Evaluate if the es_evi is ready to be sent BGP -
132  * 1. If it is ready an add is sent to BGP
133  * 2. If it is not ready a del is sent (if the ES had been previously added
134  *   to BGP).
135  */
zebra_evpn_es_evi_re_eval_send_to_client(struct zebra_evpn_es_evi * es_evi)136 static void zebra_evpn_es_evi_re_eval_send_to_client(
137 		struct zebra_evpn_es_evi *es_evi)
138 {
139 	bool old_ready;
140 	bool new_ready;
141 
142 	old_ready = !!(es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP);
143 
144 	/* ES and L2-VNI have to be individually ready for BGP */
145 	if ((es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL) &&
146 			(es_evi->es->flags & ZEBRA_EVPNES_READY_FOR_BGP) &&
147 			zebra_evpn_send_to_client_ok(es_evi->zevpn))
148 		es_evi->flags |= ZEBRA_EVPNES_EVI_READY_FOR_BGP;
149 	else
150 		es_evi->flags &= ~ZEBRA_EVPNES_EVI_READY_FOR_BGP;
151 
152 	new_ready = !!(es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP);
153 
154 	if (old_ready == new_ready)
155 		return;
156 
157 	if (new_ready)
158 		zebra_evpn_es_evi_send_to_client(es_evi->es, es_evi->zevpn,
159 				true /* add */);
160 	else
161 		zebra_evpn_es_evi_send_to_client(es_evi->es, es_evi->zevpn,
162 				false /* add */);
163 }
164 
165 /* remove the ES-EVI from the per-L2-VNI and per-ES tables and free
166  * up the memory.
167  */
zebra_evpn_es_evi_free(struct zebra_evpn_es_evi * es_evi)168 static void zebra_evpn_es_evi_free(struct zebra_evpn_es_evi *es_evi)
169 {
170 	struct zebra_evpn_es *es = es_evi->es;
171 	zebra_evpn_t *zevpn = es_evi->zevpn;
172 
173 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
174 		zlog_debug("es %s evi %d free",
175 				es_evi->es->esi_str, es_evi->zevpn->vni);
176 
177 	/* remove from the ES's VNI list */
178 	list_delete_node(es->es_evi_list, &es_evi->es_listnode);
179 
180 	/* remove from the VNI-ESI rb tree */
181 	RB_REMOVE(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree, es_evi);
182 
183 	/* remove from the VNI-ESI rb tree */
184 	XFREE(MTYPE_ZES_EVI, es_evi);
185 }
186 
187 /* find the ES-EVI in the per-L2-VNI RB tree */
zebra_evpn_es_evi_find(struct zebra_evpn_es * es,zebra_evpn_t * zevpn)188 static struct zebra_evpn_es_evi *zebra_evpn_es_evi_find(
189 		struct zebra_evpn_es *es, zebra_evpn_t *zevpn)
190 {
191 	struct zebra_evpn_es_evi es_evi;
192 
193 	es_evi.es = es;
194 
195 	return RB_FIND(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree, &es_evi);
196 }
197 
198 /* Tell BGP about an ES-EVI deletion and then delete it */
zebra_evpn_local_es_evi_do_del(struct zebra_evpn_es_evi * es_evi)199 static void zebra_evpn_local_es_evi_do_del(struct zebra_evpn_es_evi *es_evi)
200 {
201 	if (!(es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL))
202 		return;
203 
204 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
205 		zlog_debug("local es %s evi %d del",
206 				es_evi->es->esi_str, es_evi->zevpn->vni);
207 
208 	if (es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP) {
209 		/* send a del only if add was sent for it earlier */
210 		zebra_evpn_es_evi_send_to_client(es_evi->es,
211 				es_evi->zevpn, false /* add */);
212 	}
213 
214 	/* delete it from the EVPN's local list */
215 	list_delete_node(es_evi->zevpn->local_es_evi_list,
216 			&es_evi->l2vni_listnode);
217 
218 	es_evi->flags &= ~ZEBRA_EVPNES_EVI_LOCAL;
219 	zebra_evpn_es_evi_free(es_evi);
220 }
zebra_evpn_local_es_evi_del(struct zebra_evpn_es * es,zebra_evpn_t * zevpn)221 static void zebra_evpn_local_es_evi_del(struct zebra_evpn_es *es,
222 		zebra_evpn_t *zevpn)
223 {
224 	struct zebra_evpn_es_evi *es_evi;
225 
226 	es_evi = zebra_evpn_es_evi_find(es, zevpn);
227 	if (es_evi)
228 		zebra_evpn_local_es_evi_do_del(es_evi);
229 }
230 
231 /* Create an ES-EVI if it doesn't already exist and tell BGP */
zebra_evpn_local_es_evi_add(struct zebra_evpn_es * es,zebra_evpn_t * zevpn)232 static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es,
233 		zebra_evpn_t *zevpn)
234 {
235 	struct zebra_evpn_es_evi *es_evi;
236 
237 	es_evi = zebra_evpn_es_evi_find(es, zevpn);
238 	if (!es_evi) {
239 		es_evi = zebra_evpn_es_evi_new(es, zevpn);
240 		if (!es_evi)
241 			return;
242 
243 		if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
244 			zlog_debug("local es %s evi %d add",
245 					es_evi->es->esi_str, es_evi->zevpn->vni);
246 		es_evi->flags |= ZEBRA_EVPNES_EVI_LOCAL;
247 		/* add to the EVPN's local list */
248 		listnode_init(&es_evi->l2vni_listnode, es_evi);
249 		listnode_add(zevpn->local_es_evi_list, &es_evi->l2vni_listnode);
250 
251 		zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
252 	}
253 }
254 
zebra_evpn_es_evi_show_entry(struct vty * vty,struct zebra_evpn_es_evi * es_evi,json_object * json)255 static void zebra_evpn_es_evi_show_entry(struct vty *vty,
256 		struct zebra_evpn_es_evi *es_evi, json_object *json)
257 {
258 	char type_str[4];
259 
260 	if (json) {
261 		/* XXX */
262 	} else {
263 		type_str[0] = '\0';
264 		if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL)
265 			strlcat(type_str, "L", sizeof(type_str));
266 
267 		vty_out(vty, "%-8d %-30s %-4s\n",
268 				es_evi->zevpn->vni, es_evi->es->esi_str,
269 				type_str);
270 	}
271 }
272 
zebra_evpn_es_evi_show_entry_detail(struct vty * vty,struct zebra_evpn_es_evi * es_evi,json_object * json)273 static void zebra_evpn_es_evi_show_entry_detail(struct vty *vty,
274 		struct zebra_evpn_es_evi *es_evi, json_object *json)
275 {
276 	char type_str[4];
277 
278 	if (json) {
279 		/* XXX */
280 	} else {
281 		type_str[0] = '\0';
282 		if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL)
283 			strlcat(type_str, "L", sizeof(type_str));
284 
285 		vty_out(vty, "VNI %d ESI: %s\n",
286 				es_evi->zevpn->vni, es_evi->es->esi_str);
287 		vty_out(vty, " Type: %s\n", type_str);
288 		vty_out(vty, " Ready for BGP: %s\n",
289 				(es_evi->flags &
290 				 ZEBRA_EVPNES_EVI_READY_FOR_BGP) ?
291 				"yes" : "no");
292 		vty_out(vty, "\n");
293 	}
294 }
295 
zebra_evpn_es_evi_show_one_evpn(zebra_evpn_t * zevpn,struct vty * vty,json_object * json,int detail)296 static void zebra_evpn_es_evi_show_one_evpn(zebra_evpn_t *zevpn,
297 		struct vty *vty, json_object *json, int detail)
298 {
299 	struct zebra_evpn_es_evi *es_evi;
300 
301 	RB_FOREACH(es_evi, zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree) {
302 		if (detail)
303 			zebra_evpn_es_evi_show_entry_detail(vty, es_evi, json);
304 		else
305 			zebra_evpn_es_evi_show_entry(vty, es_evi, json);
306 	}
307 }
308 
309 struct evpn_mh_show_ctx {
310 	struct vty *vty;
311 	json_object *json;
312 	int detail;
313 };
314 
zebra_evpn_es_evi_show_one_evpn_hash_cb(struct hash_bucket * bucket,void * ctxt)315 static void zebra_evpn_es_evi_show_one_evpn_hash_cb(struct hash_bucket *bucket,
316 		void *ctxt)
317 {
318 	zebra_evpn_t *zevpn = (zebra_evpn_t *)bucket->data;
319 	struct evpn_mh_show_ctx *wctx = (struct evpn_mh_show_ctx *)ctxt;
320 
321 	zebra_evpn_es_evi_show_one_evpn(zevpn, wctx->vty,
322 			wctx->json, wctx->detail);
323 }
324 
zebra_evpn_es_evi_show(struct vty * vty,bool uj,int detail)325 void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail)
326 {
327 	json_object *json = NULL;
328 	struct zebra_vrf *zvrf;
329 	struct evpn_mh_show_ctx wctx;
330 
331 	zvrf = zebra_vrf_get_evpn();
332 
333 	memset(&wctx, 0, sizeof(wctx));
334 	wctx.vty = vty;
335 	wctx.json = json;
336 	wctx.detail = detail;
337 
338 	if (!detail && !json) {
339 		vty_out(vty, "Type: L local, R remote\n");
340 		vty_out(vty, "%-8s %-30s %-4s\n", "VNI", "ESI", "Type");
341 	}
342 	/* Display all L2-VNIs */
343 	hash_iterate(zvrf->evpn_table, zebra_evpn_es_evi_show_one_evpn_hash_cb,
344 			&wctx);
345 }
346 
zebra_evpn_es_evi_show_vni(struct vty * vty,bool uj,vni_t vni,int detail)347 void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj, vni_t vni, int detail)
348 {
349 	json_object *json = NULL;
350 	zebra_evpn_t *zevpn;
351 
352 	zevpn = zebra_evpn_lookup(vni);
353 	if (zevpn) {
354 		if (!detail && !json) {
355 			vty_out(vty, "Type: L local, R remote\n");
356 			vty_out(vty, "%-8s %-30s %-4s\n", "VNI", "ESI", "Type");
357 		}
358 	} else {
359 		if (!uj)
360 			vty_out(vty, "VNI %d doesn't exist\n", vni);
361 	}
362 	zebra_evpn_es_evi_show_one_evpn(zevpn, vty, json, detail);
363 }
364 
365 /* Initialize the ES tables maintained per-L2_VNI */
zebra_evpn_evpn_es_init(zebra_evpn_t * zevpn)366 void zebra_evpn_evpn_es_init(zebra_evpn_t *zevpn)
367 {
368 	/* Initialize the ES-EVI RB tree */
369 	RB_INIT(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree);
370 
371 	/* Initialize the local and remote ES lists maintained for quick
372 	 * walks by type
373 	 */
374 	zevpn->local_es_evi_list = list_new();
375 	listset_app_node_mem(zevpn->local_es_evi_list);
376 }
377 
378 /* Cleanup the ES info maintained per- EVPN */
zebra_evpn_evpn_es_cleanup(zebra_evpn_t * zevpn)379 void zebra_evpn_evpn_es_cleanup(zebra_evpn_t *zevpn)
380 {
381 	struct zebra_evpn_es_evi *es_evi;
382 	struct zebra_evpn_es_evi *es_evi_next;
383 
384 	RB_FOREACH_SAFE(es_evi, zebra_es_evi_rb_head,
385 			&zevpn->es_evi_rb_tree, es_evi_next) {
386 		zebra_evpn_local_es_evi_do_del(es_evi);
387 	}
388 
389 	list_delete(&zevpn->local_es_evi_list);
390 	zebra_evpn_es_clear_base_evpn(zevpn);
391 }
392 
393 /* called when the oper state or bridge membership changes for the
394  * vxlan device
395  */
zebra_evpn_update_all_es(zebra_evpn_t * zevpn)396 void zebra_evpn_update_all_es(zebra_evpn_t *zevpn)
397 {
398 	struct zebra_evpn_es_evi *es_evi;
399 	struct listnode *node;
400 
401 	/* the EVPN is now elgible as a base for EVPN-MH */
402 	if (zebra_evpn_send_to_client_ok(zevpn))
403 		zebra_evpn_es_set_base_evpn(zevpn);
404 	else
405 		zebra_evpn_es_clear_base_evpn(zevpn);
406 
407 	for (ALL_LIST_ELEMENTS_RO(zevpn->local_es_evi_list, node, es_evi))
408 		zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
409 }
410 
411 /*****************************************************************************/
412 /* Access broadcast domains (BD)
413  * 1. These broadcast domains can be VLAN aware (in which case
414  * the key is VID) or VLAN unaware (in which case the key is
415  * 2. A VID-BD is created when a VLAN is associated with an access port or
416  *    when the VLAN is associated with VXLAN_IF
417  * 3. A BD is translated into ES-EVI entries when a VNI is associated
418  *  with the broadcast domain
419  */
420 /* Hash key for VLAN based broadcast domains */
zebra_evpn_acc_vl_hash_keymake(const void * p)421 static unsigned int zebra_evpn_acc_vl_hash_keymake(const void *p)
422 {
423 	const struct zebra_evpn_access_bd *acc_bd = p;
424 
425 	return jhash_1word(acc_bd->vid, 0);
426 }
427 
428 /* Compare two VLAN based broadcast domains */
zebra_evpn_acc_vl_cmp(const void * p1,const void * p2)429 static bool zebra_evpn_acc_vl_cmp(const void *p1, const void *p2)
430 {
431 	const struct zebra_evpn_access_bd *acc_bd1 = p1;
432 	const struct zebra_evpn_access_bd *acc_bd2 = p2;
433 
434 	if (acc_bd1 == NULL && acc_bd2 == NULL)
435 		return true;
436 
437 	if (acc_bd1 == NULL || acc_bd2 == NULL)
438 		return false;
439 
440 	return (acc_bd1->vid == acc_bd2->vid);
441 }
442 
443 /* Lookup VLAN based broadcast domain */
zebra_evpn_acc_vl_find(vlanid_t vid)444 static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid)
445 {
446 	struct zebra_evpn_access_bd *acc_bd;
447 	struct zebra_evpn_access_bd tmp;
448 
449 	tmp.vid = vid;
450 	acc_bd = hash_lookup(zmh_info->evpn_vlan_table, &tmp);
451 
452 	return acc_bd;
453 }
454 
455 /* A new broadcast domain can be created when a VLAN member or VLAN<=>VxLAN_IF
456  * mapping is added.
457  */
zebra_evpn_acc_vl_new(vlanid_t vid)458 static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_new(vlanid_t vid)
459 {
460 	struct zebra_evpn_access_bd *acc_bd;
461 
462 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
463 		zlog_debug("access vlan %d add", vid);
464 
465 	acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd));
466 
467 	acc_bd->vid = vid;
468 
469 	/* Initialize the mbr list */
470 	acc_bd->mbr_zifs = list_new();
471 
472 	/* Add to hash */
473 	if (!hash_get(zmh_info->evpn_vlan_table, acc_bd, hash_alloc_intern)) {
474 		XFREE(MTYPE_ZACC_BD, acc_bd);
475 		return NULL;
476 	}
477 
478 	return acc_bd;
479 }
480 
481 /* Free VLAN based broadcast domain -
482  * This just frees appropriate memory, caller should have taken other
483  * needed actions.
484  */
zebra_evpn_acc_vl_free(struct zebra_evpn_access_bd * acc_bd)485 static void zebra_evpn_acc_vl_free(struct zebra_evpn_access_bd *acc_bd)
486 {
487 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
488 		zlog_debug("access vlan %d del", acc_bd->vid);
489 
490 	/* cleanup resources maintained against the ES */
491 	list_delete(&acc_bd->mbr_zifs);
492 
493 	/* remove EVI from various tables */
494 	hash_release(zmh_info->evpn_vlan_table, acc_bd);
495 
496 	XFREE(MTYPE_ZACC_BD, acc_bd);
497 }
498 
zebra_evpn_acc_vl_cleanup_all(struct hash_bucket * bucket,void * arg)499 static void zebra_evpn_acc_vl_cleanup_all(struct hash_bucket *bucket, void *arg)
500 {
501 	struct zebra_evpn_access_bd *acc_bd = bucket->data;
502 
503 	zebra_evpn_acc_vl_free(acc_bd);
504 }
505 
506 /* called when a bd mbr is removed or VxLAN_IF is diassociated from the access
507  * VLAN
508  */
zebra_evpn_acc_bd_free_on_deref(struct zebra_evpn_access_bd * acc_bd)509 static void zebra_evpn_acc_bd_free_on_deref(struct zebra_evpn_access_bd *acc_bd)
510 {
511 	if (!list_isempty(acc_bd->mbr_zifs) || acc_bd->vxlan_zif)
512 		return;
513 
514 	/* if there are no references free the EVI */
515 	zebra_evpn_acc_vl_free(acc_bd);
516 }
517 
518 /* called when a EVPN-L2VNI is set or cleared against a BD */
zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd * acc_bd,zebra_evpn_t * zevpn,zebra_evpn_t * old_zevpn)519 static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
520 		zebra_evpn_t *zevpn, zebra_evpn_t *old_zevpn)
521 {
522 	struct zebra_if *zif;
523 	struct listnode *node;
524 
525 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
526 		zlog_debug("access vlan %d l2-vni %u set",
527 				acc_bd->vid, zevpn ? zevpn->vni : 0);
528 
529 	for (ALL_LIST_ELEMENTS_RO(acc_bd->mbr_zifs, node, zif)) {
530 		if (!zif->es_info.es)
531 			continue;
532 
533 		if (zevpn)
534 			zebra_evpn_local_es_evi_add(zif->es_info.es, zevpn);
535 		else if (old_zevpn)
536 			zebra_evpn_local_es_evi_del(zif->es_info.es, old_zevpn);
537 	}
538 }
539 
540 /* handle VLAN->VxLAN_IF association */
zebra_evpn_vl_vxl_ref(uint16_t vid,struct zebra_if * vxlan_zif)541 void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif)
542 {
543 	struct zebra_evpn_access_bd *acc_bd;
544 	struct zebra_if *old_vxlan_zif;
545 	zebra_evpn_t *old_zevpn;
546 
547 	if (!vid)
548 		return;
549 
550 	acc_bd = zebra_evpn_acc_vl_find(vid);
551 	if (!acc_bd)
552 		acc_bd = zebra_evpn_acc_vl_new(vid);
553 
554 	old_vxlan_zif = acc_bd->vxlan_zif;
555 	acc_bd->vxlan_zif = vxlan_zif;
556 	if (vxlan_zif == old_vxlan_zif)
557 		return;
558 
559 	old_zevpn = acc_bd->zevpn;
560 	acc_bd->zevpn = zebra_evpn_lookup(vxlan_zif->l2info.vxl.vni);
561 	if (acc_bd->zevpn == old_zevpn)
562 		return;
563 
564 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
565 		zlog_debug("access vlan %d vni %u ref",
566 				acc_bd->vid, vxlan_zif->l2info.vxl.vni);
567 
568 	if (old_zevpn)
569 		zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
570 
571 	if (acc_bd->zevpn)
572 		zebra_evpn_acc_bd_evpn_set(acc_bd, acc_bd->zevpn, NULL);
573 }
574 
575 /* handle VLAN->VxLAN_IF deref */
zebra_evpn_vl_vxl_deref(uint16_t vid,struct zebra_if * vxlan_zif)576 void zebra_evpn_vl_vxl_deref(uint16_t vid, struct zebra_if *vxlan_zif)
577 {
578 	struct zebra_evpn_access_bd *acc_bd;
579 
580 	if (!vid)
581 		return;
582 
583 	acc_bd = zebra_evpn_acc_vl_find(vid);
584 	if (!acc_bd)
585 		return;
586 
587 	/* clear vxlan_if only if it matches */
588 	if (acc_bd->vxlan_zif != vxlan_zif)
589 		return;
590 
591 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
592 		zlog_debug("access vlan %d vni %u deref",
593 				acc_bd->vid, vxlan_zif->l2info.vxl.vni);
594 
595 	if (acc_bd->zevpn)
596 		zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, acc_bd->zevpn);
597 
598 	acc_bd->zevpn = NULL;
599 	acc_bd->vxlan_zif = NULL;
600 
601 	/* if there are no other references the access_bd can be freed */
602 	zebra_evpn_acc_bd_free_on_deref(acc_bd);
603 }
604 
605 /* handle EVPN add/del */
zebra_evpn_vxl_evpn_set(struct zebra_if * zif,zebra_evpn_t * zevpn,bool set)606 void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, zebra_evpn_t *zevpn,
607 		bool set)
608 {
609 	struct zebra_l2info_vxlan *vxl;
610 	struct zebra_evpn_access_bd *acc_bd;
611 
612 	if (!zif)
613 		return;
614 
615 	/* locate access_bd associated with the vxlan device */
616 	vxl = &zif->l2info.vxl;
617 	acc_bd = zebra_evpn_acc_vl_find(vxl->access_vlan);
618 	if (!acc_bd)
619 		return;
620 
621 	if (set) {
622 		zebra_evpn_es_set_base_evpn(zevpn);
623 		if (acc_bd->zevpn != zevpn) {
624 			acc_bd->zevpn = zevpn;
625 			zebra_evpn_acc_bd_evpn_set(acc_bd, zevpn, NULL);
626 		}
627 	} else {
628 		if (acc_bd->zevpn) {
629 			zebra_evpn_t *old_zevpn = acc_bd->zevpn;
630 			acc_bd->zevpn = NULL;
631 			zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
632 		}
633 	}
634 }
635 
636 /* handle addition of new VLAN members */
zebra_evpn_vl_mbr_ref(uint16_t vid,struct zebra_if * zif)637 void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif)
638 {
639 	struct zebra_evpn_access_bd *acc_bd;
640 
641 	if (!vid)
642 		return;
643 
644 	acc_bd = zebra_evpn_acc_vl_find(vid);
645 	if (!acc_bd)
646 		acc_bd = zebra_evpn_acc_vl_new(vid);
647 
648 	if (listnode_lookup(acc_bd->mbr_zifs, zif))
649 		return;
650 
651 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
652 		zlog_debug("access vlan %d mbr %s ref",
653 				vid, zif->ifp->name);
654 
655 	listnode_add(acc_bd->mbr_zifs, zif);
656 	if (acc_bd->zevpn && zif->es_info.es)
657 		zebra_evpn_local_es_evi_add(zif->es_info.es, acc_bd->zevpn);
658 }
659 
660 /* handle deletion of VLAN members */
zebra_evpn_vl_mbr_deref(uint16_t vid,struct zebra_if * zif)661 void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif)
662 {
663 	struct zebra_evpn_access_bd *acc_bd;
664 	struct listnode *node;
665 
666 	if (!vid)
667 		return;
668 
669 	acc_bd = zebra_evpn_acc_vl_find(vid);
670 	if (!acc_bd)
671 		return;
672 
673 	node = listnode_lookup(acc_bd->mbr_zifs, zif);
674 	if (!node)
675 		return;
676 
677 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
678 		zlog_debug("access vlan %d mbr %s deref",
679 				vid, zif->ifp->name);
680 
681 	list_delete_node(acc_bd->mbr_zifs, node);
682 
683 	if (acc_bd->zevpn && zif->es_info.es)
684 		zebra_evpn_local_es_evi_del(zif->es_info.es, acc_bd->zevpn);
685 
686 	/* if there are no other references the access_bd can be freed */
687 	zebra_evpn_acc_bd_free_on_deref(acc_bd);
688 }
689 
zebra_evpn_acc_vl_show_entry_detail(struct vty * vty,struct zebra_evpn_access_bd * acc_bd,json_object * json)690 static void zebra_evpn_acc_vl_show_entry_detail(struct vty *vty,
691 		struct zebra_evpn_access_bd *acc_bd, json_object *json)
692 {
693 	struct zebra_if *zif;
694 	struct listnode	*node;
695 
696 	if (json) {
697 		/* XXX */
698 	} else {
699 		vty_out(vty, "VLAN: %u\n", acc_bd->vid);
700 		vty_out(vty, " VxLAN Interface: %s\n",
701 				acc_bd->vxlan_zif ?
702 				acc_bd->vxlan_zif->ifp->name : "-");
703 		vty_out(vty, " L2-VNI: %d\n",
704 				acc_bd->zevpn ? acc_bd->zevpn->vni : 0);
705 		vty_out(vty, " Member Count: %d\n",
706 				listcount(acc_bd->mbr_zifs));
707 		vty_out(vty, " Members: \n");
708 		for (ALL_LIST_ELEMENTS_RO(acc_bd->mbr_zifs, node, zif))
709 			vty_out(vty, "    %s\n", zif->ifp->name);
710 		vty_out(vty, "\n");
711 	}
712 }
713 
zebra_evpn_acc_vl_show_entry(struct vty * vty,struct zebra_evpn_access_bd * acc_bd,json_object * json)714 static void zebra_evpn_acc_vl_show_entry(struct vty *vty,
715 		struct zebra_evpn_access_bd *acc_bd, json_object *json)
716 {
717 	if (!json)
718 		vty_out(vty, "%-5u %21s %-8d %u\n",
719 				acc_bd->vid,
720 				acc_bd->vxlan_zif ?
721 				acc_bd->vxlan_zif->ifp->name : "-",
722 				acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
723 				listcount(acc_bd->mbr_zifs));
724 }
725 
zebra_evpn_acc_vl_show_hash(struct hash_bucket * bucket,void * ctxt)726 static void zebra_evpn_acc_vl_show_hash(struct hash_bucket *bucket, void *ctxt)
727 {
728 	struct evpn_mh_show_ctx *wctx = ctxt;
729 	struct zebra_evpn_access_bd *acc_bd = bucket->data;
730 
731 	if (wctx->detail)
732 		zebra_evpn_acc_vl_show_entry_detail(wctx->vty,
733 				acc_bd, wctx->json);
734 	else
735 		zebra_evpn_acc_vl_show_entry(wctx->vty,
736 				acc_bd, wctx->json);
737 }
738 
zebra_evpn_acc_vl_show(struct vty * vty,bool uj)739 void zebra_evpn_acc_vl_show(struct vty *vty, bool uj)
740 {
741 	json_object *json = NULL;
742 	struct evpn_mh_show_ctx wctx;
743 
744 	memset(&wctx, 0, sizeof(wctx));
745 	wctx.vty = vty;
746 	wctx.json = json;
747 	wctx.detail = false;
748 
749 	if (!json)
750 		vty_out(vty, "%-5s %21s %-8s %s\n",
751 				"VLAN", "VxLAN-IF", "L2-VNI", "# Members");
752 
753 	hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
754 			&wctx);
755 }
756 
zebra_evpn_acc_vl_show_detail(struct vty * vty,bool uj)757 void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj)
758 {
759 	json_object *json = NULL;
760 	struct evpn_mh_show_ctx wctx;
761 
762 	memset(&wctx, 0, sizeof(wctx));
763 	wctx.vty = vty;
764 	wctx.json = json;
765 	wctx.detail = true;
766 
767 	hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
768 			&wctx);
769 }
770 
zebra_evpn_acc_vl_show_vid(struct vty * vty,bool uj,vlanid_t vid)771 void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid)
772 {
773 	json_object *json = NULL;
774 	struct zebra_evpn_access_bd *acc_bd;
775 
776 	acc_bd = zebra_evpn_acc_vl_find(vid);
777 	if (!acc_bd) {
778 		if (!json) {
779 			vty_out(vty, "VLAN %u not present\n", vid);
780 			return;
781 		}
782 	}
783 	zebra_evpn_acc_vl_show_entry_detail(vty, acc_bd, json);
784 }
785 
786 /* Initialize VLAN member bitmap on an interface. Although VLAN membership
787  * is independent of EVPN we only process it if its of interest to EVPN-MH
788  * i.e. on access ports that can be setup as Ethernet Segments. And that is
789  * intended as an optimization.
790  */
zebra_evpn_if_init(struct zebra_if * zif)791 void zebra_evpn_if_init(struct zebra_if *zif)
792 {
793 	if (!zebra_evpn_is_if_es_capable(zif))
794 		return;
795 
796 	if (!bf_is_inited(zif->vlan_bitmap))
797 		bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX);
798 
799 	/* if an es_id and sysmac are already present against the interface
800 	 * activate it
801 	 */
802 	zebra_evpn_local_es_update(zif, zif->es_info.lid, &zif->es_info.sysmac);
803 }
804 
805 /* handle deletion of an access port by removing it from all associated
806  * broadcast domains.
807  */
zebra_evpn_if_cleanup(struct zebra_if * zif)808 void zebra_evpn_if_cleanup(struct zebra_if *zif)
809 {
810 	vlanid_t vid;
811 	struct zebra_evpn_es *es;
812 
813 	if (!bf_is_inited(zif->vlan_bitmap))
814 		return;
815 
816 	bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) {
817 		zebra_evpn_vl_mbr_deref(vid, zif);
818 	}
819 
820 	bf_free(zif->vlan_bitmap);
821 
822 	/* Delete associated Ethernet Segment */
823 	es = zif->es_info.es;
824 	if (es)
825 		zebra_evpn_local_es_del(&es);
826 }
827 
828 /*****************************************************************************
829  * L2 NH/NHG Management
830  *   A L2 NH entry is programmed in the kernel for every ES-VTEP entry. This
831  * NH is then added to the L2-ECMP-NHG associated with the ES.
832  */
zebra_evpn_nhid_alloc(bool is_nhg)833 static uint32_t zebra_evpn_nhid_alloc(bool is_nhg)
834 {
835 	uint32_t id;
836 	int type;
837 
838 	bf_assign_index(zmh_info->nh_id_bitmap, id);
839 
840 	if (!id)
841 		return 0;
842 
843 	type = is_nhg ? EVPN_NHG_ID_TYPE_BIT : EVPN_NH_ID_TYPE_BIT;
844 	return (id | type);
845 }
846 
zebra_evpn_nhid_free(uint32_t nh_id)847 static void zebra_evpn_nhid_free(uint32_t nh_id)
848 {
849 	uint32_t id = (nh_id & EVPN_NH_ID_VAL_MASK);
850 
851 	if (!id)
852 		return;
853 
854 	bf_release_index(zmh_info->nh_id_bitmap, id);
855 }
856 
857 /* The MAC ECMP group is activated on the first VTEP */
zebra_evpn_nhg_update(struct zebra_evpn_es * es)858 static void zebra_evpn_nhg_update(struct zebra_evpn_es *es)
859 {
860 	uint32_t nh_cnt = 0;
861 	struct nh_grp nh_ids[ES_VTEP_MAX_CNT];
862 	struct zebra_evpn_es_vtep *es_vtep;
863 	struct listnode	*node;
864 
865 	if (!es->nhg_id)
866 		return;
867 
868 	for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
869 		if (!es_vtep->nh_id)
870 			continue;
871 
872 		if (nh_cnt >= ES_VTEP_MAX_CNT)
873 			break;
874 
875 		memset(&nh_ids[nh_cnt], 0, sizeof(struct nh_grp));
876 		nh_ids[nh_cnt].id = es_vtep->nh_id;
877 		++nh_cnt;
878 	}
879 
880 	if (nh_cnt) {
881 		if (IS_ZEBRA_DEBUG_EVPN_MH_NH) {
882 			char nh_str[ES_VTEP_LIST_STR_SZ];
883 			uint32_t i;
884 			char nh_buf[16];
885 
886 			nh_str[0] = '\0';
887 			for (i = 0; i < nh_cnt; ++i) {
888 				snprintf(nh_buf, sizeof(nh_buf), "%u ",
889 					 nh_ids[i].id);
890 				strlcat(nh_str, nh_buf, sizeof(nh_str));
891 			}
892 			zlog_debug("es %s nhg 0x%x add %s",
893 					es->esi_str, es->nhg_id, nh_str);
894 		}
895 
896 		es->flags |= ZEBRA_EVPNES_NHG_ACTIVE;
897 		kernel_upd_mac_nhg(es->nhg_id, nh_cnt, nh_ids);
898 	} else {
899 		if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) {
900 			if (IS_ZEBRA_DEBUG_EVPN_MH_NH)
901 				zlog_debug("es %s nhg 0x%x del",
902 						es->esi_str, es->nhg_id);
903 			es->flags &= ~ZEBRA_EVPNES_NHG_ACTIVE;
904 			kernel_del_mac_nhg(es->nhg_id);
905 		}
906 	}
907 
908 	/* XXX - update remote macs associated with the ES */
909 }
910 
zebra_evpn_nh_add(struct zebra_evpn_es_vtep * es_vtep)911 static void zebra_evpn_nh_add(struct zebra_evpn_es_vtep *es_vtep)
912 {
913 	if (es_vtep->nh_id)
914 		return;
915 
916 	es_vtep->nh_id = zebra_evpn_nhid_alloc(false);
917 
918 	if (!es_vtep->nh_id)
919 		return;
920 
921 	if (IS_ZEBRA_DEBUG_EVPN_MH_NH)
922 		zlog_debug("es %s vtep %s nh 0x%x add",
923 				es_vtep->es->esi_str,
924 				inet_ntoa(es_vtep->vtep_ip), es_vtep->nh_id);
925 	/* install the NH */
926 	kernel_upd_mac_nh(es_vtep->nh_id, es_vtep->vtep_ip);
927 	/* add the NH to the parent NHG */
928 	zebra_evpn_nhg_update(es_vtep->es);
929 }
930 
zebra_evpn_nh_del(struct zebra_evpn_es_vtep * es_vtep)931 static void zebra_evpn_nh_del(struct zebra_evpn_es_vtep *es_vtep)
932 {
933 	uint32_t nh_id;
934 
935 	if (!es_vtep->nh_id)
936 		return;
937 
938 	if (IS_ZEBRA_DEBUG_EVPN_MH_NH)
939 		zlog_debug("es %s vtep %s nh 0x%x del",
940 				es_vtep->es->esi_str,
941 				inet_ntoa(es_vtep->vtep_ip), es_vtep->nh_id);
942 
943 	nh_id = es_vtep->nh_id;
944 	es_vtep->nh_id = 0;
945 
946 	/* remove the NH from the parent NHG */
947 	zebra_evpn_nhg_update(es_vtep->es);
948 	/* uninstall the NH */
949 	kernel_del_mac_nh(nh_id);
950 	zebra_evpn_nhid_free(nh_id);
951 
952 }
953 
954 /*****************************************************************************/
955 /* Ethernet Segment Management
956  * 1. Ethernet Segment is a collection of links attached to the same
957  *    server (MHD) or switch (MHN)
958  * 2. An Ethernet Segment can span multiple PEs and is identified by the
959  *    10-byte ES-ID.
960  * 3. Zebra manages the local ESI configuration.
961  * 4. It also maintains the aliasing that maps an ESI (local or remote)
962  *    to one or more PEs/VTEPs.
963  * 5. remote ESs are added by BGP (on rxing EAD Type-1 routes)
964  */
965 /* A list of remote VTEPs is maintained for each ES. This list includes -
966  * 1. VTEPs for which we have imported the ESR i.e. ES-peers
967  * 2. VTEPs that have an "active" ES-EVI VTEP i.e. EAD-per-ES and EAD-per-EVI
968  *    have been imported into one or more EVPNs
969  */
zebra_evpn_es_vtep_cmp(void * p1,void * p2)970 static int zebra_evpn_es_vtep_cmp(void *p1, void *p2)
971 {
972 	const struct zebra_evpn_es_vtep *es_vtep1 = p1;
973 	const struct zebra_evpn_es_vtep *es_vtep2 = p2;
974 
975 	return es_vtep1->vtep_ip.s_addr - es_vtep2->vtep_ip.s_addr;
976 }
977 
zebra_evpn_es_vtep_new(struct zebra_evpn_es * es,struct in_addr vtep_ip)978 static struct zebra_evpn_es_vtep *zebra_evpn_es_vtep_new(
979 		struct zebra_evpn_es *es, struct in_addr vtep_ip)
980 {
981 	struct zebra_evpn_es_vtep *es_vtep;
982 
983 	es_vtep = XCALLOC(MTYPE_ZES_VTEP, sizeof(*es_vtep));
984 
985 	es_vtep->es = es;
986 	es_vtep->vtep_ip.s_addr = vtep_ip.s_addr;
987 	listnode_init(&es_vtep->es_listnode, es_vtep);
988 	listnode_add_sort(es->es_vtep_list, &es_vtep->es_listnode);
989 
990 	return es_vtep;
991 }
992 
zebra_evpn_es_vtep_free(struct zebra_evpn_es_vtep * es_vtep)993 static void zebra_evpn_es_vtep_free(struct zebra_evpn_es_vtep *es_vtep)
994 {
995 	struct zebra_evpn_es *es = es_vtep->es;
996 
997 	list_delete_node(es->es_vtep_list, &es_vtep->es_listnode);
998 	/* update the L2-NHG associated with the ES */
999 	zebra_evpn_nh_del(es_vtep);
1000 	XFREE(MTYPE_ZES_VTEP, es_vtep);
1001 }
1002 
1003 
1004 /* check if VTEP is already part of the list */
zebra_evpn_es_vtep_find(struct zebra_evpn_es * es,struct in_addr vtep_ip)1005 static struct zebra_evpn_es_vtep *zebra_evpn_es_vtep_find(
1006 		struct zebra_evpn_es *es, struct in_addr vtep_ip)
1007 {
1008 	struct listnode *node = NULL;
1009 	struct zebra_evpn_es_vtep *es_vtep;
1010 
1011 	for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1012 		if (es_vtep->vtep_ip.s_addr == vtep_ip.s_addr)
1013 			return es_vtep;
1014 	}
1015 	return NULL;
1016 }
1017 
zebra_evpn_es_vtep_add(struct zebra_evpn_es * es,struct in_addr vtep_ip)1018 static void zebra_evpn_es_vtep_add(struct zebra_evpn_es *es,
1019 		struct in_addr vtep_ip)
1020 {
1021 	struct zebra_evpn_es_vtep *es_vtep;
1022 
1023 	es_vtep = zebra_evpn_es_vtep_find(es, vtep_ip);
1024 
1025 	if (!es_vtep) {
1026 		if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1027 			zlog_debug("es %s vtep %s add",
1028 					es->esi_str, inet_ntoa(vtep_ip));
1029 		es_vtep = zebra_evpn_es_vtep_new(es, vtep_ip);
1030 		/* update the L2-NHG associated with the ES */
1031 		zebra_evpn_nh_add(es_vtep);
1032 	}
1033 }
1034 
zebra_evpn_es_vtep_del(struct zebra_evpn_es * es,struct in_addr vtep_ip)1035 static void zebra_evpn_es_vtep_del(struct zebra_evpn_es *es,
1036 		struct in_addr vtep_ip)
1037 {
1038 	struct zebra_evpn_es_vtep *es_vtep;
1039 
1040 	es_vtep = zebra_evpn_es_vtep_find(es, vtep_ip);
1041 
1042 	if (es_vtep) {
1043 		if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1044 			zlog_debug("es %s vtep %s del",
1045 					es->esi_str, inet_ntoa(vtep_ip));
1046 		zebra_evpn_es_vtep_free(es_vtep);
1047 	}
1048 }
1049 
1050 /* compare ES-IDs for the global ES RB tree */
zebra_es_rb_cmp(const struct zebra_evpn_es * es1,const struct zebra_evpn_es * es2)1051 static int zebra_es_rb_cmp(const struct zebra_evpn_es *es1,
1052 		const struct zebra_evpn_es *es2)
1053 {
1054 	return memcmp(&es1->esi, &es2->esi, ESI_BYTES);
1055 }
1056 RB_GENERATE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
1057 
1058 /* Lookup ES */
zebra_evpn_es_find(esi_t * esi)1059 struct zebra_evpn_es *zebra_evpn_es_find(esi_t *esi)
1060 {
1061 	struct zebra_evpn_es tmp;
1062 
1063 	memcpy(&tmp.esi, esi, sizeof(esi_t));
1064 	return RB_FIND(zebra_es_rb_head, &zmh_info->es_rb_tree, &tmp);
1065 }
1066 
1067 /* A new local es is created when a local-es-id and sysmac is configured
1068  * against an interface.
1069  */
zebra_evpn_es_new(esi_t * esi)1070 static struct zebra_evpn_es *zebra_evpn_es_new(esi_t *esi)
1071 {
1072 	struct zebra_evpn_es *es;
1073 
1074 	es = XCALLOC(MTYPE_ZES, sizeof(struct zebra_evpn_es));
1075 
1076 	/* fill in ESI */
1077 	memcpy(&es->esi, esi, sizeof(esi_t));
1078 	esi_to_str(&es->esi, es->esi_str, sizeof(es->esi_str));
1079 
1080 	/* Add to rb_tree */
1081 	if (RB_INSERT(zebra_es_rb_head, &zmh_info->es_rb_tree, es)) {
1082 		XFREE(MTYPE_ZES, es);
1083 		return NULL;
1084 	}
1085 
1086 	/* Initialise the ES-EVI list */
1087 	es->es_evi_list = list_new();
1088 	listset_app_node_mem(es->es_evi_list);
1089 
1090 	/* Initialise the VTEP list */
1091 	es->es_vtep_list = list_new();
1092 	listset_app_node_mem(es->es_vtep_list);
1093 	es->es_vtep_list->cmp = zebra_evpn_es_vtep_cmp;
1094 
1095 	/* mac entries associated with the ES */
1096 	es->mac_list = list_new();
1097 	listset_app_node_mem(es->mac_list);
1098 
1099 	/* reserve a NHG  */
1100 	es->nhg_id = zebra_evpn_nhid_alloc(true);
1101 
1102 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1103 		zlog_debug("es %s nhg 0x%x new", es->esi_str, es->nhg_id);
1104 
1105 	return es;
1106 }
1107 
1108 /* Free a given ES -
1109  * This just frees appropriate memory, caller should have taken other
1110  * needed actions.
1111  */
zebra_evpn_es_free(struct zebra_evpn_es ** esp)1112 static void zebra_evpn_es_free(struct zebra_evpn_es **esp)
1113 {
1114 	struct zebra_evpn_es *es = *esp;
1115 
1116 	/* If the ES has a local or remote reference it cannot be freed.
1117 	 * Free is also prevented if there are MAC entries referencing
1118 	 * it.
1119 	 */
1120 	if ((es->flags & (ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_REMOTE)) ||
1121 			listcount(es->mac_list))
1122 		return;
1123 
1124 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1125 		zlog_debug("es %s free", es->esi_str);
1126 
1127 	/* If the NHG is still installed uninstall it and free the id */
1128 	if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) {
1129 		es->flags &= ~ZEBRA_EVPNES_NHG_ACTIVE;
1130 		kernel_del_mac_nhg(es->nhg_id);
1131 	}
1132 	zebra_evpn_nhid_free(es->nhg_id);
1133 
1134 	/* cleanup resources maintained against the ES */
1135 	list_delete(&es->es_evi_list);
1136 	list_delete(&es->es_vtep_list);
1137 	list_delete(&es->mac_list);
1138 
1139 	/* remove from the VNI-ESI rb tree */
1140 	RB_REMOVE(zebra_es_rb_head, &zmh_info->es_rb_tree, es);
1141 
1142 	XFREE(MTYPE_ZES, es);
1143 
1144 	*esp = NULL;
1145 }
1146 
1147 /* Inform BGP about local ES addition */
zebra_evpn_es_send_add_to_client(struct zebra_evpn_es * es)1148 static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
1149 {
1150 	struct zserv *client;
1151 	struct stream *s;
1152 	uint8_t oper_up;
1153 
1154 	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1155 	/* BGP may not be running. */
1156 	if (!client)
1157 		return 0;
1158 
1159 	s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1160 
1161 	zclient_create_header(s, ZEBRA_LOCAL_ES_ADD, zebra_vrf_get_evpn_id());
1162 	stream_put(s, &es->esi, sizeof(esi_t));
1163 	stream_put_ipv4(s, zmh_info->es_originator_ip.s_addr);
1164 	oper_up = !!(es->flags & ZEBRA_EVPNES_OPER_UP);
1165 	stream_putc(s, oper_up);
1166 
1167 	/* Write packet size. */
1168 	stream_putw_at(s, 0, stream_get_endp(s));
1169 
1170 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1171 		zlog_debug("send add local es %s %s to %s",
1172 				es->esi_str,
1173 				inet_ntoa(zmh_info->es_originator_ip),
1174 				zebra_route_string(client->proto));
1175 
1176 	client->local_es_add_cnt++;
1177 	return zserv_send_message(client, s);
1178 }
1179 
1180 /* Inform BGP about local ES deletion */
zebra_evpn_es_send_del_to_client(struct zebra_evpn_es * es)1181 static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es)
1182 {
1183 	struct zserv *client;
1184 	struct stream *s;
1185 
1186 	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1187 	/* BGP may not be running. */
1188 	if (!client)
1189 		return 0;
1190 
1191 	s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1192 	stream_reset(s);
1193 
1194 	zclient_create_header(s, ZEBRA_LOCAL_ES_DEL, zebra_vrf_get_evpn_id());
1195 	stream_put(s, &es->esi, sizeof(esi_t));
1196 
1197 	/* Write packet size. */
1198 	stream_putw_at(s, 0, stream_get_endp(s));
1199 
1200 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1201 		zlog_debug("send del local es %s to %s", es->esi_str,
1202 				zebra_route_string(client->proto));
1203 
1204 	client->local_es_del_cnt++;
1205 	return zserv_send_message(client, s);
1206 }
1207 
zebra_evpn_es_re_eval_send_to_client(struct zebra_evpn_es * es,bool es_evi_re_reval)1208 static void zebra_evpn_es_re_eval_send_to_client(struct zebra_evpn_es *es,
1209 		bool es_evi_re_reval)
1210 {
1211 	bool old_ready;
1212 	bool new_ready;
1213 	struct listnode *node;
1214 	struct zebra_evpn_es_evi *es_evi;
1215 
1216 	old_ready = !!(es->flags & ZEBRA_EVPNES_READY_FOR_BGP);
1217 
1218 	if ((es->flags & ZEBRA_EVPNES_LOCAL) &&
1219 			zmh_info->es_originator_ip.s_addr)
1220 		es->flags |= ZEBRA_EVPNES_READY_FOR_BGP;
1221 	else
1222 		es->flags &= ~ZEBRA_EVPNES_READY_FOR_BGP;
1223 
1224 	new_ready = !!(es->flags & ZEBRA_EVPNES_READY_FOR_BGP);
1225 	if (old_ready == new_ready)
1226 		return;
1227 
1228 	if (new_ready)
1229 		zebra_evpn_es_send_add_to_client(es);
1230 	else
1231 		zebra_evpn_es_send_del_to_client(es);
1232 
1233 	/* re-eval associated EVIs */
1234 	if (es_evi_re_reval) {
1235 		for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, node, es_evi)) {
1236 			if (!(es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL))
1237 				continue;
1238 			zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
1239 		}
1240 	}
1241 }
1242 
zebra_evpn_es_send_all_to_client(bool add)1243 void zebra_evpn_es_send_all_to_client(bool add)
1244 {
1245 	struct listnode *es_node;
1246 	struct listnode *evi_node;
1247 	struct zebra_evpn_es *es;
1248 	struct zebra_evpn_es_evi *es_evi;
1249 
1250 	if (!zmh_info)
1251 		return;
1252 
1253 	for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, es_node, es)) {
1254 		if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP) {
1255 			if (add)
1256 				zebra_evpn_es_send_add_to_client(es);
1257 			for (ALL_LIST_ELEMENTS_RO(es->es_evi_list,
1258 						evi_node, es_evi)) {
1259 				if (!(es_evi->flags &
1260 					ZEBRA_EVPNES_EVI_READY_FOR_BGP))
1261 					continue;
1262 
1263 				if (add)
1264 					zebra_evpn_es_evi_send_to_client(
1265 						es, es_evi->zevpn,
1266 						true /* add */);
1267 				else
1268 					zebra_evpn_es_evi_send_to_client(
1269 						es, es_evi->zevpn,
1270 						false /* add */);
1271 			}
1272 			if (!add)
1273 				zebra_evpn_es_send_del_to_client(es);
1274 		}
1275 	}
1276 }
1277 
1278 /* walk the vlan bitmap associated with the zif and create or delete
1279  * es_evis for all vlans associated with a VNI.
1280  * XXX: This API is really expensive. optimize later if possible.
1281  */
zebra_evpn_es_setup_evis(struct zebra_evpn_es * es)1282 static void zebra_evpn_es_setup_evis(struct zebra_evpn_es *es)
1283 {
1284 	struct zebra_if *zif = es->zif;
1285 	uint16_t vid;
1286 	struct zebra_evpn_access_bd *acc_bd;
1287 
1288 
1289 	bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) {
1290 		acc_bd = zebra_evpn_acc_vl_find(vid);
1291 		if (acc_bd->zevpn)
1292 			zebra_evpn_local_es_evi_add(es, acc_bd->zevpn);
1293 	}
1294 }
1295 
zebra_evpn_es_local_mac_update(struct zebra_evpn_es * es,bool force_clear_static)1296 static void zebra_evpn_es_local_mac_update(struct zebra_evpn_es *es,
1297 		bool force_clear_static)
1298 {
1299 	zebra_mac_t *mac;
1300 	struct listnode	*node;
1301 
1302 	for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
1303 		if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)) {
1304 			zebra_evpn_sync_mac_dp_install(
1305 				mac, false /* set_inactive */,
1306 				force_clear_static, __func__);
1307 		}
1308 	}
1309 }
1310 
zebra_evpn_es_local_info_set(struct zebra_evpn_es * es,struct zebra_if * zif)1311 static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
1312 		struct zebra_if *zif)
1313 {
1314 	if (es->flags & ZEBRA_EVPNES_LOCAL)
1315 		return;
1316 
1317 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1318 		zlog_debug("local es %s add; nhg 0x%x if %s",
1319 				es->esi_str, es->nhg_id, zif->ifp->name);
1320 
1321 	es->flags |= ZEBRA_EVPNES_LOCAL;
1322 	listnode_init(&es->local_es_listnode, es);
1323 	listnode_add(zmh_info->local_es_list, &es->local_es_listnode);
1324 
1325 	/* attach es to interface */
1326 	zif->es_info.es = es;
1327 
1328 	/* attach interface to es */
1329 	es->zif = zif;
1330 	if (if_is_operative(zif->ifp))
1331 		es->flags |= ZEBRA_EVPNES_OPER_UP;
1332 
1333 	/* setup base-vni if one doesn't already exist; the ES will get sent
1334 	 * to BGP as a part of that process
1335 	 */
1336 	if (!zmh_info->es_base_evpn)
1337 		zebra_evpn_es_get_one_base_evpn();
1338 	else
1339 		/* send notification to bgp */
1340 		zebra_evpn_es_re_eval_send_to_client(es,
1341 			false /* es_evi_re_reval */);
1342 
1343 	/* Setup ES-EVIs for all VxLAN stretched VLANs associated with
1344 	 * the zif
1345 	 */
1346 	zebra_evpn_es_setup_evis(es);
1347 	/* if there any local macs referring to the ES as dest we
1348 	 * need to set the static reference on them if the MAC is
1349 	 * synced from an ES peer
1350 	 */
1351 	zebra_evpn_es_local_mac_update(es,
1352 			false /* force_clear_static */);
1353 }
1354 
zebra_evpn_es_local_info_clear(struct zebra_evpn_es ** esp)1355 static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp)
1356 {
1357 	struct zebra_if *zif;
1358 	struct zebra_evpn_es *es = *esp;
1359 
1360 	if (!(es->flags & ZEBRA_EVPNES_LOCAL))
1361 		return;
1362 
1363 	es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP);
1364 
1365 	/* if there any local macs referring to the ES as dest we
1366 	 * need to clear the static reference on them
1367 	 */
1368 	zebra_evpn_es_local_mac_update(es,
1369 			true /* force_clear_static */);
1370 
1371 	/* clear the es from the parent interface */
1372 	zif = es->zif;
1373 	zif->es_info.es = NULL;
1374 	es->zif = NULL;
1375 
1376 	/* remove from the ES list */
1377 	list_delete_node(zmh_info->local_es_list, &es->local_es_listnode);
1378 
1379 	/* free up the ES if there is no remote reference */
1380 	zebra_evpn_es_free(esp);
1381 }
1382 
1383 /* Delete an ethernet segment and inform BGP */
zebra_evpn_local_es_del(struct zebra_evpn_es ** esp)1384 static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp)
1385 {
1386 	struct zebra_evpn_es_evi *es_evi;
1387 	struct listnode *node = NULL;
1388 	struct listnode *nnode = NULL;
1389 	struct zebra_if *zif;
1390 	struct zebra_evpn_es *es = *esp;
1391 
1392 	if (!CHECK_FLAG(es->flags, ZEBRA_EVPNES_LOCAL))
1393 		return;
1394 
1395 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES) {
1396 		zif = es->zif;
1397 		zlog_debug("local es %s del; nhg 0x%x if %s",
1398 				es->esi_str, es->nhg_id,
1399 				zif ? zif->ifp->name : "-");
1400 	}
1401 
1402 	/* remove all ES-EVIs associated with the ES */
1403 	for (ALL_LIST_ELEMENTS(es->es_evi_list, node, nnode, es_evi))
1404 		zebra_evpn_local_es_evi_do_del(es_evi);
1405 
1406 	/* send a del if the ES had been sent to BGP earlier */
1407 	if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
1408 		zebra_evpn_es_send_del_to_client(es);
1409 
1410 	zebra_evpn_es_local_info_clear(esp);
1411 }
1412 
1413 /* eval remote info associated with the ES */
zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es ** esp)1414 static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp)
1415 {
1416 	struct zebra_evpn_es *es = *esp;
1417 
1418 	/* if there are remote VTEPs the ES-EVI is classified as "remote" */
1419 	if (listcount(es->es_vtep_list)) {
1420 		if (!(es->flags & ZEBRA_EVPNES_REMOTE)) {
1421 			es->flags |= ZEBRA_EVPNES_REMOTE;
1422 			if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1423 				zlog_debug("remote es %s add; nhg 0x%x",
1424 						es->esi_str, es->nhg_id);
1425 		}
1426 	} else {
1427 		if (es->flags & ZEBRA_EVPNES_REMOTE) {
1428 			es->flags &= ~ZEBRA_EVPNES_REMOTE;
1429 			if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1430 				zlog_debug("remote es %s del; nhg 0x%x",
1431 						es->esi_str, es->nhg_id);
1432 			zebra_evpn_es_free(esp);
1433 		}
1434 	}
1435 }
1436 
1437 /* A new local es is created when a local-es-id and sysmac is configured
1438  * against an interface.
1439  */
zebra_evpn_local_es_update(struct zebra_if * zif,uint32_t lid,struct ethaddr * sysmac)1440 static int zebra_evpn_local_es_update(struct zebra_if *zif, uint32_t lid,
1441 		struct ethaddr *sysmac)
1442 {
1443 	struct zebra_evpn_es *old_es = zif->es_info.es;
1444 	struct zebra_evpn_es *es;
1445 	esi_t esi;
1446 	int offset = 0;
1447 	int field_bytes = 0;
1448 
1449 	/* Complete config of the ES-ID bootstraps the ES */
1450 	if (!lid || is_zero_mac(sysmac)) {
1451 		/* if in ES is attached to zif delete it */
1452 		if (old_es)
1453 			zebra_evpn_local_es_del(&old_es);
1454 		return 0;
1455 	}
1456 
1457 	/* build 10-byte type-3-ESI -
1458 	 * Type(1-byte), MAC(6-bytes), ES-LID (3-bytes)
1459 	 */
1460 	field_bytes = 1;
1461 	esi.val[offset] = ESI_TYPE_MAC;
1462 	offset += field_bytes;
1463 
1464 	field_bytes = ETH_ALEN;
1465 	memcpy(&esi.val[offset], (uint8_t *)sysmac, field_bytes);
1466 	offset += field_bytes;
1467 
1468 	esi.val[offset++] = (uint8_t)(lid >> 16);
1469 	esi.val[offset++] = (uint8_t)(lid >> 8);
1470 	esi.val[offset++] = (uint8_t)lid;
1471 
1472 	if (old_es && !memcmp(&old_es->esi, &esi, sizeof(esi_t)))
1473 		/* dup - nothing to be done */
1474 		return 0;
1475 
1476 	/* release the old_es against the zif */
1477 	if (old_es)
1478 		zebra_evpn_local_es_del(&old_es);
1479 
1480 	es = zebra_evpn_es_find(&esi);
1481 	if (es) {
1482 		/* if it exists against another interface flag an error */
1483 		if (es->zif && es->zif != zif)
1484 			return -1;
1485 	} else {
1486 		/* create new es */
1487 		es = zebra_evpn_es_new(&esi);
1488 	}
1489 
1490 	zebra_evpn_es_local_info_set(es, zif);
1491 
1492 	return 0;
1493 }
1494 
zebra_evpn_remote_es_del(esi_t * esi,struct in_addr vtep_ip)1495 static int zebra_evpn_remote_es_del(esi_t *esi, struct in_addr vtep_ip)
1496 {
1497 	char buf[ESI_STR_LEN];
1498 	struct zebra_evpn_es *es;
1499 
1500 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1501 		zlog_debug("remote es %s vtep %s del",
1502 				esi_to_str(esi, buf, sizeof(buf)),
1503 				inet_ntoa(vtep_ip));
1504 
1505 	es = zebra_evpn_es_find(esi);
1506 	if (!es) {
1507 		zlog_warn("remote es %s vtep %pI4 del failed, es missing",
1508 			  esi_to_str(esi, buf, sizeof(buf)), &vtep_ip);
1509 		return -1;
1510 	}
1511 
1512 	zebra_evpn_es_vtep_del(es, vtep_ip);
1513 	zebra_evpn_es_remote_info_re_eval(&es);
1514 
1515 	return 0;
1516 }
1517 
1518 /* force delete a remote ES on the way down */
zebra_evpn_remote_es_flush(struct zebra_evpn_es ** esp)1519 static void zebra_evpn_remote_es_flush(struct zebra_evpn_es **esp)
1520 {
1521 	struct zebra_evpn_es_vtep *es_vtep;
1522 	struct listnode	*node;
1523 	struct listnode	*nnode;
1524 	struct zebra_evpn_es *es = *esp;
1525 
1526 	for (ALL_LIST_ELEMENTS(es->es_vtep_list, node, nnode, es_vtep)) {
1527 		if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1528 			zlog_debug("es %s vtep %s flush",
1529 					es->esi_str,
1530 					inet_ntoa(es_vtep->vtep_ip));
1531 		zebra_evpn_es_vtep_free(es_vtep);
1532 	}
1533 	zebra_evpn_es_remote_info_re_eval(esp);
1534 }
1535 
zebra_evpn_remote_es_add(esi_t * esi,struct in_addr vtep_ip)1536 static int zebra_evpn_remote_es_add(esi_t *esi, struct in_addr vtep_ip)
1537 {
1538 	char buf[ESI_STR_LEN];
1539 	struct zebra_evpn_es *es;
1540 
1541 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1542 		zlog_debug("remote es %s vtep %s add",
1543 				esi_to_str(esi, buf, sizeof(buf)),
1544 				inet_ntoa(vtep_ip));
1545 
1546 	es = zebra_evpn_es_find(esi);
1547 	if (!es) {
1548 		es = zebra_evpn_es_new(esi);
1549 		if (!es) {
1550 			zlog_warn(
1551 				"remote es %s vtep %pI4 add failed, es missing",
1552 				esi_to_str(esi, buf, sizeof(buf)), &vtep_ip);
1553 			return -1;
1554 		}
1555 	}
1556 
1557 	zebra_evpn_es_vtep_add(es, vtep_ip);
1558 	zebra_evpn_es_remote_info_re_eval(&es);
1559 
1560 	return 0;
1561 }
1562 
zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS)1563 void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS)
1564 {
1565 	struct stream *s;
1566 	struct in_addr vtep_ip;
1567 	esi_t esi;
1568 
1569 	if (!is_evpn_enabled()) {
1570 		zlog_debug(
1571 				"%s: EVPN not enabled yet we received a es_add zapi call",
1572 				__PRETTY_FUNCTION__);
1573 		return;
1574 	}
1575 
1576 	memset(&esi, 0, sizeof(esi_t));
1577 	s = msg;
1578 
1579 	stream_get(&esi, s, sizeof(esi_t));
1580 	vtep_ip.s_addr = stream_get_ipv4(s);
1581 
1582 	if (hdr->command == ZEBRA_REMOTE_ES_VTEP_ADD)
1583 		zebra_evpn_remote_es_add(&esi, vtep_ip);
1584 	else
1585 		zebra_evpn_remote_es_del(&esi, vtep_ip);
1586 }
1587 
zebra_evpn_es_mac_deref_entry(zebra_mac_t * mac)1588 void zebra_evpn_es_mac_deref_entry(zebra_mac_t *mac)
1589 {
1590 	struct zebra_evpn_es *es = mac->es;
1591 
1592 	mac->es = NULL;
1593 	if (!es)
1594 		return;
1595 
1596 	list_delete_node(es->mac_list, &mac->es_listnode);
1597 	if (!listcount(es->mac_list))
1598 		zebra_evpn_es_free(&es);
1599 }
1600 
1601 /* Associate a MAC entry with a local or remote ES. Returns false if there
1602  * was no ES change.
1603  */
zebra_evpn_es_mac_ref_entry(zebra_mac_t * mac,struct zebra_evpn_es * es)1604 bool zebra_evpn_es_mac_ref_entry(zebra_mac_t *mac, struct zebra_evpn_es *es)
1605 {
1606 	if (mac->es == es)
1607 		return false;
1608 
1609 	if (mac->es)
1610 		zebra_evpn_es_mac_deref_entry(mac);
1611 
1612 	if (!es)
1613 		return true;
1614 
1615 	mac->es = es;
1616 	listnode_init(&mac->es_listnode, mac);
1617 	listnode_add(es->mac_list, &mac->es_listnode);
1618 
1619 	return true;
1620 }
1621 
zebra_evpn_es_mac_ref(zebra_mac_t * mac,esi_t * esi)1622 bool zebra_evpn_es_mac_ref(zebra_mac_t *mac, esi_t *esi)
1623 {
1624 	struct zebra_evpn_es *es;
1625 
1626 	es = zebra_evpn_es_find(esi);
1627 	if (!es) {
1628 		/* If non-zero esi implicitly create a new ES */
1629 		if (memcmp(esi, zero_esi, sizeof(esi_t))) {
1630 			es = zebra_evpn_es_new(esi);
1631 			if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1632 				zlog_debug("auto es %s add on mac ref",
1633 					   es->esi_str);
1634 		}
1635 	}
1636 
1637 	return zebra_evpn_es_mac_ref_entry(mac, es);
1638 }
1639 
1640 /* Inform BGP about local ES-EVI add or del */
zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es * es,zebra_evpn_t * zevpn,bool add)1641 static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
1642 		zebra_evpn_t *zevpn, bool add)
1643 {
1644 	struct zserv *client;
1645 	struct stream *s;
1646 
1647 	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1648 	/* BGP may not be running. */
1649 	if (!client)
1650 		return 0;
1651 
1652 	s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1653 
1654 	zclient_create_header(s,
1655 			add ? ZEBRA_LOCAL_ES_EVI_ADD : ZEBRA_LOCAL_ES_EVI_DEL,
1656 			zebra_vrf_get_evpn_id());
1657 	stream_put(s, &es->esi, sizeof(esi_t));
1658 	stream_putl(s, zevpn->vni);
1659 
1660 	/* Write packet size. */
1661 	stream_putw_at(s, 0, stream_get_endp(s));
1662 
1663 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1664 		zlog_debug("send %s local es %s evi %u to %s",
1665 				add ? "add" : "del",
1666 				es->esi_str, zevpn->vni,
1667 				zebra_route_string(client->proto));
1668 
1669 	client->local_es_add_cnt++;
1670 	return zserv_send_message(client, s);
1671 }
1672 
1673 /* sysmac part of a local ESI has changed */
zebra_evpn_es_sys_mac_update(struct zebra_if * zif,struct ethaddr * sysmac)1674 static int zebra_evpn_es_sys_mac_update(struct zebra_if *zif,
1675 		struct ethaddr *sysmac)
1676 {
1677 	int rv;
1678 
1679 	rv = zebra_evpn_local_es_update(zif, zif->es_info.lid, sysmac);
1680 	if (!rv)
1681 		memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
1682 
1683 	return rv;
1684 }
1685 
1686 /* local-ID part of ESI has changed */
zebra_evpn_es_lid_update(struct zebra_if * zif,uint32_t lid)1687 static int zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
1688 {
1689 	int rv;
1690 
1691 	rv = zebra_evpn_local_es_update(zif, lid, &zif->es_info.sysmac);
1692 	if (!rv)
1693 		zif->es_info.lid = lid;
1694 
1695 	return rv;
1696 }
1697 
zebra_evpn_es_cleanup(void)1698 void zebra_evpn_es_cleanup(void)
1699 {
1700 	struct zebra_evpn_es *es;
1701 	struct zebra_evpn_es *es_next;
1702 
1703 	RB_FOREACH_SAFE(es, zebra_es_rb_head,
1704 			&zmh_info->es_rb_tree, es_next) {
1705 		zebra_evpn_local_es_del(&es);
1706 		if (es)
1707 			zebra_evpn_remote_es_flush(&es);
1708 	}
1709 }
1710 
1711 /* Only certain types of access ports can be setup as an Ethernet Segment */
zebra_evpn_is_if_es_capable(struct zebra_if * zif)1712 bool zebra_evpn_is_if_es_capable(struct zebra_if *zif)
1713 {
1714 	if (zif->zif_type == ZEBRA_IF_BOND)
1715 		return true;
1716 
1717 	/* XXX: allow swpX i.e. a regular ethernet port to be an ES link too */
1718 	return false;
1719 }
1720 
zebra_evpn_if_es_print(struct vty * vty,struct zebra_if * zif)1721 void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif)
1722 {
1723 	char buf[ETHER_ADDR_STRLEN];
1724 
1725 	if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac))
1726 		vty_out(vty, "  EVPN MH: ES id %u ES sysmac %s\n",
1727 				zif->es_info.lid,
1728 				prefix_mac2str(&zif->es_info.sysmac,
1729 					buf, sizeof(buf)));
1730 }
1731 
zebra_evpn_es_if_oper_state_change(struct zebra_if * zif,bool up)1732 void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up)
1733 {
1734 	struct zebra_evpn_es *es = zif->es_info.es;
1735 	bool old_up = !!(es->flags & ZEBRA_EVPNES_OPER_UP);
1736 
1737 	if (old_up == up)
1738 		return;
1739 
1740 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1741 		zlog_debug("es %s state changed to %s ",
1742 				es->esi_str,
1743 				up ? "up" : "down");
1744 	if (up)
1745 		es->flags |= ZEBRA_EVPNES_OPER_UP;
1746 	else
1747 		es->flags &= ~ZEBRA_EVPNES_OPER_UP;
1748 
1749 	/* inform BGP of the ES oper state change */
1750 	if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
1751 		zebra_evpn_es_send_add_to_client(es);
1752 }
1753 
zebra_evpn_es_vtep_str(char * vtep_str,struct zebra_evpn_es * es,uint8_t vtep_str_size)1754 static char *zebra_evpn_es_vtep_str(char *vtep_str, struct zebra_evpn_es *es,
1755 				    uint8_t vtep_str_size)
1756 {
1757 	struct zebra_evpn_es_vtep *zvtep;
1758 	struct listnode	*node;
1759 	bool first = true;
1760 
1761 	vtep_str[0] = '\0';
1762 	for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, zvtep)) {
1763 		if (first) {
1764 			first = false;
1765 			strlcat(vtep_str, inet_ntoa(zvtep->vtep_ip),
1766 				vtep_str_size);
1767 		} else {
1768 			strlcat(vtep_str, ",", vtep_str_size);
1769 			strlcat(vtep_str, inet_ntoa(zvtep->vtep_ip),
1770 				vtep_str_size);
1771 		}
1772 	}
1773 	return vtep_str;
1774 }
1775 
zebra_evpn_es_show_entry(struct vty * vty,struct zebra_evpn_es * es,json_object * json)1776 static void zebra_evpn_es_show_entry(struct vty *vty,
1777 		struct zebra_evpn_es *es, json_object *json)
1778 {
1779 	char type_str[4];
1780 	char vtep_str[ES_VTEP_LIST_STR_SZ];
1781 
1782 	if (json) {
1783 		/* XXX */
1784 	} else {
1785 		type_str[0] = '\0';
1786 		if (es->flags & ZEBRA_EVPNES_LOCAL)
1787 			strlcat(type_str, "L", sizeof(type_str));
1788 		if (es->flags & ZEBRA_EVPNES_REMOTE)
1789 			strlcat(type_str, "R", sizeof(type_str));
1790 
1791 		zebra_evpn_es_vtep_str(vtep_str, es, sizeof(vtep_str));
1792 
1793 		vty_out(vty, "%-30s %-4s %-21s %s\n",
1794 				es->esi_str, type_str,
1795 				es->zif ? es->zif->ifp->name : "-",
1796 				vtep_str);
1797 	}
1798 }
1799 
zebra_evpn_es_show_entry_detail(struct vty * vty,struct zebra_evpn_es * es,json_object * json)1800 static void zebra_evpn_es_show_entry_detail(struct vty *vty,
1801 		struct zebra_evpn_es *es, json_object *json)
1802 {
1803 	char type_str[80];
1804 	struct zebra_evpn_es_vtep *zvtep;
1805 	struct listnode	*node;
1806 
1807 	if (json) {
1808 		/* XXX */
1809 	} else {
1810 		type_str[0] = '\0';
1811 		if (es->flags & ZEBRA_EVPNES_LOCAL)
1812 			strlcat(type_str, "Local", sizeof(type_str));
1813 		if (es->flags & ZEBRA_EVPNES_REMOTE) {
1814 			if (strnlen(type_str, sizeof(type_str)))
1815 				strlcat(type_str, ",", sizeof(type_str));
1816 			strlcat(type_str, "Remote", sizeof(type_str));
1817 		}
1818 
1819 		vty_out(vty, "ESI: %s\n", es->esi_str);
1820 		vty_out(vty, " Type: %s\n", type_str);
1821 		vty_out(vty, " Interface: %s\n",
1822 				(es->zif) ?
1823 				es->zif->ifp->name : "-");
1824 		vty_out(vty, " State: %s\n",
1825 				(es->flags & ZEBRA_EVPNES_OPER_UP) ?
1826 				"up" : "down");
1827 		vty_out(vty, " Ready for BGP: %s\n",
1828 				(es->flags & ZEBRA_EVPNES_READY_FOR_BGP) ?
1829 				"yes" : "no");
1830 		vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
1831 		vty_out(vty, " MAC Count: %d\n", listcount(es->mac_list));
1832 		vty_out(vty, " Nexthop group: 0x%x\n", es->nhg_id);
1833 		vty_out(vty, " VTEPs:\n");
1834 		for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, zvtep))
1835 			vty_out(vty, "     %s nh: 0x%x\n",
1836 					inet_ntoa(zvtep->vtep_ip),
1837 					zvtep->nh_id);
1838 
1839 		vty_out(vty, "\n");
1840 	}
1841 }
1842 
zebra_evpn_es_show(struct vty * vty,bool uj)1843 void zebra_evpn_es_show(struct vty *vty, bool uj)
1844 {
1845 	struct zebra_evpn_es *es;
1846 	json_object *json = NULL;
1847 
1848 	if (uj) {
1849 		/* XXX */
1850 	} else {
1851 		vty_out(vty, "Type: L local, R remote\n");
1852 		vty_out(vty, "%-30s %-4s %-21s %s\n",
1853 				"ESI", "Type", "ES-IF", "VTEPs");
1854 	}
1855 
1856 	RB_FOREACH(es, zebra_es_rb_head, &zmh_info->es_rb_tree)
1857 		zebra_evpn_es_show_entry(vty, es, json);
1858 }
1859 
zebra_evpn_es_show_detail(struct vty * vty,bool uj)1860 void zebra_evpn_es_show_detail(struct vty *vty, bool uj)
1861 {
1862 	struct zebra_evpn_es *es;
1863 	json_object *json = NULL;
1864 
1865 	RB_FOREACH(es, zebra_es_rb_head, &zmh_info->es_rb_tree)
1866 		zebra_evpn_es_show_entry_detail(vty, es, json);
1867 }
1868 
zebra_evpn_es_show_esi(struct vty * vty,bool uj,esi_t * esi)1869 void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi)
1870 {
1871 	struct zebra_evpn_es *es;
1872 	char esi_str[ESI_STR_LEN];
1873 	json_object *json = NULL;
1874 
1875 	es = zebra_evpn_es_find(esi);
1876 
1877 	if (!es) {
1878 		esi_to_str(esi, esi_str, sizeof(esi_str));
1879 		vty_out(vty, "ESI %s does not exist\n", esi_str);
1880 		return;
1881 	}
1882 
1883 	zebra_evpn_es_show_entry_detail(vty, es, json);
1884 }
1885 
zebra_evpn_mh_if_write(struct vty * vty,struct interface * ifp)1886 int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp)
1887 {
1888 	struct zebra_if *zif = ifp->info;
1889 	char buf[ETHER_ADDR_STRLEN];
1890 
1891 	if (zif->es_info.lid)
1892 		vty_out(vty, " evpn mh es-id %u\n", zif->es_info.lid);
1893 
1894 	if (!is_zero_mac(&zif->es_info.sysmac))
1895 		vty_out(vty, " evpn mh es-sys-mac %s\n",
1896 				prefix_mac2str(&zif->es_info.sysmac,
1897 					buf, sizeof(buf)));
1898 	return 0;
1899 }
1900 
1901 #ifndef VTYSH_EXTRACT_PL
1902 #include "zebra/zebra_evpn_mh_clippy.c"
1903 #endif
1904 /* CLI for setting up sysmac part of ESI on an access port */
1905 DEFPY(zebra_evpn_es_sys_mac,
1906       zebra_evpn_es_sys_mac_cmd,
1907       "[no$no] evpn mh es-sys-mac [X:X:X:X:X:X$mac]",
1908       NO_STR
1909       "EVPN\n"
1910       EVPN_MH_VTY_STR
1911       "Ethernet segment system MAC\n"
1912       MAC_STR
1913 )
1914 {
1915 	VTY_DECLVAR_CONTEXT(interface, ifp);
1916 	struct zebra_if *zif;
1917 	int ret = 0;
1918 
1919 	zif = ifp->info;
1920 
1921 	if (no) {
1922 		static struct ethaddr zero_mac;
1923 
1924 		ret = zebra_evpn_es_sys_mac_update(zif, &zero_mac);
1925 		if (ret == -1) {
1926 			vty_out(vty, "%%Failed to clear ES sysmac\n");
1927 			return CMD_WARNING;
1928 		}
1929 	} else {
1930 
1931 		if (!zebra_evpn_is_if_es_capable(zif)) {
1932 			vty_out(vty,
1933 				"%%ESI cannot be associated with this interface type\n");
1934 			return CMD_WARNING;
1935 		}
1936 
1937 		if  (!mac || is_zero_mac(&mac->eth_addr)) {
1938 			vty_out(vty, "%%ES sysmac value is invalid\n");
1939 			return CMD_WARNING;
1940 		}
1941 
1942 		ret = zebra_evpn_es_sys_mac_update(zif, &mac->eth_addr);
1943 		if (ret == -1) {
1944 			vty_out(vty, "%%ESI already exists on a different interface\n");
1945 			return CMD_WARNING;
1946 		}
1947 	}
1948 	return CMD_SUCCESS;
1949 }
1950 
1951 /* CLI for setting up local-ID part of ESI on an access port */
1952 DEFPY(zebra_evpn_es_id,
1953       zebra_evpn_es_id_cmd,
1954       "[no$no] evpn mh es-id [(1-16777215)$es_lid]",
1955       NO_STR
1956       "EVPN\n"
1957       EVPN_MH_VTY_STR
1958       "Ethernet segment local identifier\n"
1959       "ID\n"
1960 )
1961 {
1962 	VTY_DECLVAR_CONTEXT(interface, ifp);
1963 	struct zebra_if *zif;
1964 	int ret;
1965 
1966 	zif = ifp->info;
1967 
1968 	if (no) {
1969 		ret = zebra_evpn_es_lid_update(zif, 0);
1970 		if (ret == -1) {
1971 			vty_out(vty, "%%Failed to clear ES local id\n");
1972 			return CMD_WARNING;
1973 		}
1974 	} else {
1975 		if (!zebra_evpn_is_if_es_capable(zif)) {
1976 			vty_out(vty,
1977 				"%%ESI cannot be associated with this interface type\n");
1978 			return CMD_WARNING;
1979 		}
1980 
1981 		if  (!es_lid) {
1982 			vty_out(vty, "%%Specify local ES ID\n");
1983 			return CMD_WARNING;
1984 		}
1985 		ret = zebra_evpn_es_lid_update(zif, es_lid);
1986 		if (ret == -1) {
1987 			vty_out(vty,
1988 				"%%ESI already exists on a different interface\n");
1989 			return CMD_WARNING;
1990 		}
1991 	}
1992 	return CMD_SUCCESS;
1993 }
1994 
1995 /*****************************************************************************/
1996 /* A base L2-VNI is maintained to derive parameters such as ES originator-IP.
1997  * XXX: once single vxlan device model becomes available this will not be
1998  * necessary
1999  */
2000 /* called when a new vni is added or becomes oper up or becomes a bridge port */
zebra_evpn_es_set_base_evpn(zebra_evpn_t * zevpn)2001 void zebra_evpn_es_set_base_evpn(zebra_evpn_t *zevpn)
2002 {
2003 	struct listnode *node;
2004 	struct zebra_evpn_es *es;
2005 
2006 	if (zmh_info->es_base_evpn) {
2007 		if (zmh_info->es_base_evpn != zevpn) {
2008 			/* unrelated EVPN; ignore it */
2009 			return;
2010 		}
2011 		/* check if the local vtep-ip has changed */
2012 	} else {
2013 		/* check if the EVPN can be used as base EVPN */
2014 		if (!zebra_evpn_send_to_client_ok(zevpn))
2015 			return;
2016 
2017 		if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2018 			zlog_debug("es base vni set to %d",
2019 					zevpn->vni);
2020 		zmh_info->es_base_evpn = zevpn;
2021 	}
2022 
2023 	/* update local VTEP-IP */
2024 	if (zmh_info->es_originator_ip.s_addr ==
2025 			zmh_info->es_base_evpn->local_vtep_ip.s_addr)
2026 		return;
2027 
2028 	zmh_info->es_originator_ip.s_addr =
2029 		zmh_info->es_base_evpn->local_vtep_ip.s_addr;
2030 
2031 	if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2032 		zlog_debug("es originator ip set to %s",
2033 			inet_ntoa(zmh_info->es_base_evpn->local_vtep_ip));
2034 
2035 	/* if originator ip changes we need to update bgp */
2036 	for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, node, es)) {
2037 		if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
2038 			zebra_evpn_es_send_add_to_client(es);
2039 		else
2040 			zebra_evpn_es_re_eval_send_to_client(es,
2041 					true /* es_evi_re_reval */);
2042 	}
2043 }
2044 
2045 /* called when a vni is removed or becomes oper down or is removed from a
2046  * bridge
2047  */
zebra_evpn_es_clear_base_evpn(zebra_evpn_t * zevpn)2048 void zebra_evpn_es_clear_base_evpn(zebra_evpn_t *zevpn)
2049 {
2050 	struct listnode *node;
2051 	struct zebra_evpn_es *es;
2052 
2053 	if (zmh_info->es_base_evpn != zevpn)
2054 		return;
2055 
2056 	zmh_info->es_base_evpn = NULL;
2057 	/* lost current base EVPN; try to find a new one */
2058 	zebra_evpn_es_get_one_base_evpn();
2059 
2060 	/* couldn't locate an eligible base evpn */
2061 	if (!zmh_info->es_base_evpn && zmh_info->es_originator_ip.s_addr) {
2062 		if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2063 			zlog_debug("es originator ip cleared");
2064 
2065 		zmh_info->es_originator_ip.s_addr = 0;
2066 		/* lost originator ip */
2067 		for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, node, es)) {
2068 			zebra_evpn_es_re_eval_send_to_client(es,
2069 					true /* es_evi_re_reval */);
2070 		}
2071 	}
2072 }
2073 
2074 /* Locate an "eligible" L2-VNI to follow */
zebra_evpn_es_get_one_base_evpn_cb(struct hash_bucket * b,void * data)2075 static int zebra_evpn_es_get_one_base_evpn_cb(struct hash_bucket *b, void *data)
2076 {
2077 	zebra_evpn_t *zevpn = b->data;
2078 
2079 	zebra_evpn_es_set_base_evpn(zevpn);
2080 
2081 	if (zmh_info->es_base_evpn)
2082 		return HASHWALK_ABORT;
2083 
2084 	return HASHWALK_CONTINUE;
2085 }
2086 
2087 /* locate a base_evpn to follow for the purposes of common params like
2088  * originator IP
2089  */
zebra_evpn_es_get_one_base_evpn(void)2090 static void zebra_evpn_es_get_one_base_evpn(void)
2091 {
2092 	struct zebra_vrf *zvrf;
2093 
2094 	zvrf = zebra_vrf_get_evpn();
2095 	hash_walk(zvrf->evpn_table, zebra_evpn_es_get_one_base_evpn_cb, NULL);
2096 }
2097 
2098 /*****************************************************************************/
zebra_evpn_mh_config_write(struct vty * vty)2099 void zebra_evpn_mh_config_write(struct vty *vty)
2100 {
2101 	if (zmh_info->mac_hold_time != EVPN_MH_MAC_HOLD_TIME_DEF)
2102 		vty_out(vty, "evpn mh mac-holdtime %ld\n",
2103 			zmh_info->mac_hold_time);
2104 
2105 	if (zmh_info->neigh_hold_time != EVPN_MH_NEIGH_HOLD_TIME_DEF)
2106 		vty_out(vty, "evpn mh neigh-holdtime %ld\n",
2107 			zmh_info->neigh_hold_time);
2108 }
2109 
zebra_evpn_mh_neigh_holdtime_update(struct vty * vty,uint32_t duration,bool set_default)2110 int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
2111 		uint32_t duration, bool set_default)
2112 {
2113 	if (set_default)
2114 		duration = EVPN_MH_NEIGH_HOLD_TIME_DEF;
2115 
2116 	zmh_info->neigh_hold_time = duration;
2117 
2118 	return 0;
2119 }
2120 
zebra_evpn_mh_mac_holdtime_update(struct vty * vty,uint32_t duration,bool set_default)2121 int zebra_evpn_mh_mac_holdtime_update(struct vty *vty,
2122 		uint32_t duration, bool set_default)
2123 {
2124 	if (set_default)
2125 		duration = EVPN_MH_MAC_HOLD_TIME_DEF;
2126 
2127 	zmh_info->mac_hold_time = duration;
2128 
2129 	return 0;
2130 }
2131 
zebra_evpn_interface_init(void)2132 void zebra_evpn_interface_init(void)
2133 {
2134 	install_element(INTERFACE_NODE, &zebra_evpn_es_id_cmd);
2135 	install_element(INTERFACE_NODE, &zebra_evpn_es_sys_mac_cmd);
2136 }
2137 
zebra_evpn_mh_init(void)2138 void zebra_evpn_mh_init(void)
2139 {
2140 	zrouter.mh_info = XCALLOC(MTYPE_ZMH_INFO, sizeof(*zrouter.mh_info));
2141 
2142 	zmh_info->mac_hold_time = EVPN_MH_MAC_HOLD_TIME_DEF;
2143 	zmh_info->neigh_hold_time = EVPN_MH_NEIGH_HOLD_TIME_DEF;
2144 	/* setup ES tables */
2145 	RB_INIT(zebra_es_rb_head, &zmh_info->es_rb_tree);
2146 	zmh_info->local_es_list = list_new();
2147 	listset_app_node_mem(zmh_info->local_es_list);
2148 
2149 	bf_init(zmh_info->nh_id_bitmap, EVPN_NH_ID_MAX);
2150 	bf_assign_zero_index(zmh_info->nh_id_bitmap);
2151 
2152 	/* setup broadcast domain tables */
2153 	zmh_info->evpn_vlan_table = hash_create(zebra_evpn_acc_vl_hash_keymake,
2154 			zebra_evpn_acc_vl_cmp, "access VLAN hash table");
2155 }
2156 
zebra_evpn_mh_terminate(void)2157 void zebra_evpn_mh_terminate(void)
2158 {
2159 	list_delete(&zmh_info->local_es_list);
2160 
2161 	hash_iterate(zmh_info->evpn_vlan_table,
2162 			zebra_evpn_acc_vl_cleanup_all, NULL);
2163 	hash_free(zmh_info->evpn_vlan_table);
2164 }
2165