]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_evpn_mh.c
zebra: data structure changes for single vxlan device
[mirror_frr.git] / zebra / zebra_evpn_mh.c
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/if_netlink.h"
42 #include "zebra/zebra_errors.h"
43 #include "zebra/zebra_l2.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 DEFINE_MTYPE_STATIC(ZEBRA, L2_NH, "L2 nexthop");
60
61 static void zebra_evpn_es_get_one_base_evpn(void);
62 static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
63 struct zebra_evpn *zevpn, bool add);
64 static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp);
65 static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi);
66 static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
67 const char *caller);
68 static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set);
69 static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es,
70 bool resync_dplane);
71 static void zebra_evpn_mh_clear_protodown_es(struct zebra_evpn_es *es);
72 static void zebra_evpn_mh_startup_delay_timer_start(const char *rc);
73
74 esi_t zero_esi_buf, *zero_esi = &zero_esi_buf;
75
76 /*****************************************************************************/
77 /* Ethernet Segment to EVI association -
78 * 1. The ES-EVI entry is maintained as a RB tree per L2-VNI
79 * (struct zebra_evpn.es_evi_rb_tree).
80 * 2. Each local ES-EVI entry is sent to BGP which advertises it as an
81 * EAD-EVI (Type-1 EVPN) route
82 * 3. Local ES-EVI setup is re-evaluated on the following triggers -
83 * a. When an ESI is set or cleared on an access port.
84 * b. When an access port associated with an ESI is deleted.
85 * c. When VLAN member ship changes on an access port.
86 * d. When a VXLAN_IF is set or cleared on an access broadcast domain.
87 * e. When a L2-VNI is added or deleted for a VxLAN_IF.
88 * 4. Currently zebra doesn't remote ES-EVIs. Those are managed and maintained
89 * entirely in BGP which consolidates them into a remote ES. The remote ES
90 * is then sent to zebra which allocates a NHG for it.
91 */
92
93 /* compare ES-IDs for the ES-EVI RB tree maintained per-EVPN */
94 static int zebra_es_evi_rb_cmp(const struct zebra_evpn_es_evi *es_evi1,
95 const struct zebra_evpn_es_evi *es_evi2)
96 {
97 return memcmp(&es_evi1->es->esi, &es_evi2->es->esi, ESI_BYTES);
98 }
99 RB_GENERATE(zebra_es_evi_rb_head, zebra_evpn_es_evi,
100 rb_node, zebra_es_evi_rb_cmp);
101
102 /* allocate a new ES-EVI and insert it into the per-L2-VNI and per-ES
103 * tables.
104 */
105 static struct zebra_evpn_es_evi *zebra_evpn_es_evi_new(struct zebra_evpn_es *es,
106 struct zebra_evpn *zevpn)
107 {
108 struct zebra_evpn_es_evi *es_evi;
109
110 es_evi = XCALLOC(MTYPE_ZES_EVI, sizeof(struct zebra_evpn_es_evi));
111
112 es_evi->es = es;
113 es_evi->zevpn = zevpn;
114
115 /* insert into the EVPN-ESI rb tree */
116 RB_INSERT(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree, es_evi);
117
118 /* add to the ES's VNI list */
119 listnode_init(&es_evi->es_listnode, es_evi);
120 listnode_add(es->es_evi_list, &es_evi->es_listnode);
121
122 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
123 zlog_debug("es %s evi %d new",
124 es_evi->es->esi_str, es_evi->zevpn->vni);
125
126 return es_evi;
127 }
128
129 /* Evaluate if the es_evi is ready to be sent BGP -
130 * 1. If it is ready an add is sent to BGP
131 * 2. If it is not ready a del is sent (if the ES had been previously added
132 * to BGP).
133 */
134 static void zebra_evpn_es_evi_re_eval_send_to_client(
135 struct zebra_evpn_es_evi *es_evi)
136 {
137 bool old_ready;
138 bool new_ready;
139
140 old_ready = !!(es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP);
141
142 /* ES and L2-VNI have to be individually ready for BGP */
143 if ((es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL) &&
144 (es_evi->es->flags & ZEBRA_EVPNES_READY_FOR_BGP) &&
145 zebra_evpn_send_to_client_ok(es_evi->zevpn))
146 es_evi->flags |= ZEBRA_EVPNES_EVI_READY_FOR_BGP;
147 else
148 es_evi->flags &= ~ZEBRA_EVPNES_EVI_READY_FOR_BGP;
149
150 new_ready = !!(es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP);
151
152 if (old_ready == new_ready)
153 return;
154
155 if (new_ready)
156 zebra_evpn_es_evi_send_to_client(es_evi->es, es_evi->zevpn,
157 true /* add */);
158 else
159 zebra_evpn_es_evi_send_to_client(es_evi->es, es_evi->zevpn,
160 false /* add */);
161 }
162
163 /* remove the ES-EVI from the per-L2-VNI and per-ES tables and free
164 * up the memory.
165 */
166 static void zebra_evpn_es_evi_free(struct zebra_evpn_es_evi *es_evi)
167 {
168 struct zebra_evpn_es *es = es_evi->es;
169 struct zebra_evpn *zevpn = es_evi->zevpn;
170
171 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
172 zlog_debug("es %s evi %d free",
173 es_evi->es->esi_str, es_evi->zevpn->vni);
174
175 /* remove from the ES's VNI list */
176 list_delete_node(es->es_evi_list, &es_evi->es_listnode);
177
178 /* remove from the VNI-ESI rb tree */
179 RB_REMOVE(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree, es_evi);
180
181 /* remove from the VNI-ESI rb tree */
182 XFREE(MTYPE_ZES_EVI, es_evi);
183 }
184
185 /* find the ES-EVI in the per-L2-VNI RB tree */
186 struct zebra_evpn_es_evi *zebra_evpn_es_evi_find(struct zebra_evpn_es *es,
187 struct zebra_evpn *zevpn)
188 {
189 struct zebra_evpn_es_evi es_evi;
190
191 es_evi.es = es;
192
193 return RB_FIND(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree, &es_evi);
194 }
195
196 /* Tell BGP about an ES-EVI deletion and then delete it */
197 static void zebra_evpn_local_es_evi_do_del(struct zebra_evpn_es_evi *es_evi)
198 {
199 if (!(es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL))
200 return;
201
202 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
203 zlog_debug("local es %s evi %d del",
204 es_evi->es->esi_str, es_evi->zevpn->vni);
205
206 if (es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP) {
207 /* send a del only if add was sent for it earlier */
208 zebra_evpn_es_evi_send_to_client(es_evi->es,
209 es_evi->zevpn, false /* add */);
210 }
211
212 /* delete it from the EVPN's local list */
213 list_delete_node(es_evi->zevpn->local_es_evi_list,
214 &es_evi->l2vni_listnode);
215
216 es_evi->flags &= ~ZEBRA_EVPNES_EVI_LOCAL;
217 zebra_evpn_es_evi_free(es_evi);
218 }
219 static void zebra_evpn_local_es_evi_del(struct zebra_evpn_es *es,
220 struct zebra_evpn *zevpn)
221 {
222 struct zebra_evpn_es_evi *es_evi;
223
224 es_evi = zebra_evpn_es_evi_find(es, zevpn);
225 if (es_evi)
226 zebra_evpn_local_es_evi_do_del(es_evi);
227 }
228
229 /* If there are any existing MAC entries for this es/zevpn we need
230 * to install it in the dataplane.
231 *
232 * Note: primary purpose of this is to handle es del/re-add windows where
233 * sync MAC entries may be added by bgpd before the es-evi membership is
234 * created in the dataplane and in zebra
235 */
236 static void zebra_evpn_es_evi_mac_install(struct zebra_evpn_es_evi *es_evi)
237 {
238 struct zebra_mac *mac;
239 struct listnode *node;
240 struct zebra_evpn_es *es = es_evi->es;
241
242 if (listcount(es->mac_list) && IS_ZEBRA_DEBUG_EVPN_MH_ES)
243 zlog_debug("dp-mac install on es %s evi %d add", es->esi_str,
244 es_evi->zevpn->vni);
245
246 for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
247 if (mac->zevpn != es_evi->zevpn)
248 continue;
249
250 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
251 continue;
252
253 zebra_evpn_sync_mac_dp_install(mac, false, false, __func__);
254 }
255 }
256
257 /* Create an ES-EVI if it doesn't already exist and tell BGP */
258 static void zebra_evpn_local_es_evi_add(struct zebra_evpn_es *es,
259 struct zebra_evpn *zevpn)
260 {
261 struct zebra_evpn_es_evi *es_evi;
262
263 es_evi = zebra_evpn_es_evi_find(es, zevpn);
264 if (!es_evi) {
265 es_evi = zebra_evpn_es_evi_new(es, zevpn);
266 if (!es_evi)
267 return;
268
269 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
270 zlog_debug("local es %s evi %d add",
271 es_evi->es->esi_str, es_evi->zevpn->vni);
272 es_evi->flags |= ZEBRA_EVPNES_EVI_LOCAL;
273 /* add to the EVPN's local list */
274 listnode_init(&es_evi->l2vni_listnode, es_evi);
275 listnode_add(zevpn->local_es_evi_list, &es_evi->l2vni_listnode);
276
277 zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
278
279 zebra_evpn_es_evi_mac_install(es_evi);
280 }
281 }
282
283 static void zebra_evpn_es_evi_show_entry(struct vty *vty,
284 struct zebra_evpn_es_evi *es_evi,
285 json_object *json_array)
286 {
287 char type_str[4];
288
289 if (json_array) {
290 json_object *json;
291 json_object *json_types;
292
293 /* Separate JSON object for each es-evi entry */
294 json = json_object_new_object();
295
296 json_object_string_add(json, "esi", es_evi->es->esi_str);
297 json_object_int_add(json, "vni", es_evi->zevpn->vni);
298 if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL) {
299 json_types = json_object_new_array();
300 if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL)
301 json_array_string_add(json_types, "local");
302 json_object_object_add(json, "type", json_types);
303 }
304
305 /* Add es-evi entry to json array */
306 json_object_array_add(json_array, json);
307 } else {
308 type_str[0] = '\0';
309 if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL)
310 strlcat(type_str, "L", sizeof(type_str));
311
312 vty_out(vty, "%-8d %-30s %-4s\n",
313 es_evi->zevpn->vni, es_evi->es->esi_str,
314 type_str);
315 }
316 }
317
318 static void
319 zebra_evpn_es_evi_show_entry_detail(struct vty *vty,
320 struct zebra_evpn_es_evi *es_evi,
321 json_object *json_array)
322 {
323 char type_str[4];
324
325 if (json_array) {
326 json_object *json;
327 json_object *json_flags;
328
329 /* Separate JSON object for each es-evi entry */
330 json = json_object_new_object();
331
332 json_object_string_add(json, "esi", es_evi->es->esi_str);
333 json_object_int_add(json, "vni", es_evi->zevpn->vni);
334 if (es_evi->flags
335 & (ZEBRA_EVPNES_EVI_LOCAL
336 | ZEBRA_EVPNES_EVI_READY_FOR_BGP)) {
337 json_flags = json_object_new_array();
338 if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL)
339 json_array_string_add(json_flags, "local");
340 if (es_evi->flags & ZEBRA_EVPNES_EVI_READY_FOR_BGP)
341 json_array_string_add(json_flags,
342 "readyForBgp");
343 json_object_object_add(json, "flags", json_flags);
344 }
345
346 /* Add es-evi entry to json array */
347 json_object_array_add(json_array, json);
348 } else {
349 type_str[0] = '\0';
350 if (es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL)
351 strlcat(type_str, "L", sizeof(type_str));
352
353 vty_out(vty, "VNI %d ESI: %s\n",
354 es_evi->zevpn->vni, es_evi->es->esi_str);
355 vty_out(vty, " Type: %s\n", type_str);
356 vty_out(vty, " Ready for BGP: %s\n",
357 (es_evi->flags &
358 ZEBRA_EVPNES_EVI_READY_FOR_BGP) ?
359 "yes" : "no");
360 vty_out(vty, "\n");
361 }
362 }
363
364 static void zebra_evpn_es_evi_show_one_evpn(struct zebra_evpn *zevpn,
365 struct vty *vty,
366 json_object *json_array, int detail)
367 {
368 struct zebra_evpn_es_evi *es_evi;
369
370 RB_FOREACH(es_evi, zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree) {
371 if (detail)
372 zebra_evpn_es_evi_show_entry_detail(vty, es_evi,
373 json_array);
374 else
375 zebra_evpn_es_evi_show_entry(vty, es_evi, json_array);
376 }
377 }
378
379 struct evpn_mh_show_ctx {
380 struct vty *vty;
381 json_object *json;
382 int detail;
383 };
384
385 static void zebra_evpn_es_evi_show_one_evpn_hash_cb(struct hash_bucket *bucket,
386 void *ctxt)
387 {
388 struct zebra_evpn *zevpn = (struct zebra_evpn *)bucket->data;
389 struct evpn_mh_show_ctx *wctx = (struct evpn_mh_show_ctx *)ctxt;
390
391 zebra_evpn_es_evi_show_one_evpn(zevpn, wctx->vty,
392 wctx->json, wctx->detail);
393 }
394
395 void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail)
396 {
397 json_object *json_array = NULL;
398 struct zebra_vrf *zvrf;
399 struct evpn_mh_show_ctx wctx;
400
401 zvrf = zebra_vrf_get_evpn();
402 if (uj)
403 json_array = json_object_new_array();
404
405 memset(&wctx, 0, sizeof(wctx));
406 wctx.vty = vty;
407 wctx.json = json_array;
408 wctx.detail = detail;
409
410 if (!detail && !json_array) {
411 vty_out(vty, "Type: L local, R remote\n");
412 vty_out(vty, "%-8s %-30s %-4s\n", "VNI", "ESI", "Type");
413 }
414 /* Display all L2-VNIs */
415 hash_iterate(zvrf->evpn_table, zebra_evpn_es_evi_show_one_evpn_hash_cb,
416 &wctx);
417
418 if (uj)
419 vty_json(vty, json_array);
420 }
421
422 void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj, vni_t vni, int detail)
423 {
424 json_object *json_array = NULL;
425 struct zebra_evpn *zevpn;
426
427 zevpn = zebra_evpn_lookup(vni);
428 if (uj)
429 json_array = json_object_new_array();
430
431 if (zevpn) {
432 if (!detail && !json_array) {
433 vty_out(vty, "Type: L local, R remote\n");
434 vty_out(vty, "%-8s %-30s %-4s\n", "VNI", "ESI", "Type");
435 }
436 zebra_evpn_es_evi_show_one_evpn(zevpn, vty, json_array, detail);
437 } else {
438 if (!uj)
439 vty_out(vty, "VNI %d doesn't exist\n", vni);
440 }
441
442 if (uj)
443 vty_json(vty, json_array);
444 }
445
446 /* Initialize the ES tables maintained per-L2_VNI */
447 void zebra_evpn_es_evi_init(struct zebra_evpn *zevpn)
448 {
449 /* Initialize the ES-EVI RB tree */
450 RB_INIT(zebra_es_evi_rb_head, &zevpn->es_evi_rb_tree);
451
452 /* Initialize the local and remote ES lists maintained for quick
453 * walks by type
454 */
455 zevpn->local_es_evi_list = list_new();
456 listset_app_node_mem(zevpn->local_es_evi_list);
457 }
458
459 /* Cleanup the ES info maintained per- EVPN */
460 void zebra_evpn_es_evi_cleanup(struct zebra_evpn *zevpn)
461 {
462 struct zebra_evpn_es_evi *es_evi;
463 struct zebra_evpn_es_evi *es_evi_next;
464
465 RB_FOREACH_SAFE(es_evi, zebra_es_evi_rb_head,
466 &zevpn->es_evi_rb_tree, es_evi_next) {
467 zebra_evpn_local_es_evi_do_del(es_evi);
468 }
469
470 list_delete(&zevpn->local_es_evi_list);
471 zebra_evpn_es_clear_base_evpn(zevpn);
472 }
473
474 /* called when the oper state or bridge membership changes for the
475 * vxlan device
476 */
477 void zebra_evpn_update_all_es(struct zebra_evpn *zevpn)
478 {
479 struct zebra_evpn_es_evi *es_evi;
480 struct listnode *node;
481 struct interface *vlan_if;
482 struct interface *vxlan_if;
483 struct zebra_if *vxlan_zif;
484 struct zebra_vxlan_vni *vni;
485
486 /* the EVPN is now elgible as a base for EVPN-MH */
487 if (zebra_evpn_send_to_client_ok(zevpn))
488 zebra_evpn_es_set_base_evpn(zevpn);
489 else
490 zebra_evpn_es_clear_base_evpn(zevpn);
491
492 for (ALL_LIST_ELEMENTS_RO(zevpn->local_es_evi_list, node, es_evi))
493 zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
494
495 /* reinstall SVI MAC */
496 vxlan_if = zevpn->vxlan_if;
497 if (vxlan_if) {
498 vxlan_zif = vxlan_if->info;
499 if (if_is_operative(vxlan_if)
500 && vxlan_zif->brslave_info.br_if) {
501 vni = zebra_vxlan_if_vni_find(vxlan_zif, zevpn->vni);
502 vlan_if =
503 zvni_map_to_svi(vni->access_vlan,
504 vxlan_zif->brslave_info.br_if);
505 if (vlan_if)
506 zebra_evpn_acc_bd_svi_mac_add(vlan_if);
507 }
508 }
509 }
510
511 /*****************************************************************************/
512 /* Access broadcast domains (BD)
513 * 1. These broadcast domains can be VLAN aware (in which case
514 * the key is VID) or VLAN unaware (in which case the key is
515 * 2. A VID-BD is created when a VLAN is associated with an access port or
516 * when the VLAN is associated with VXLAN_IF
517 * 3. A BD is translated into ES-EVI entries when a VNI is associated
518 * with the broadcast domain
519 */
520 /* Hash key for VLAN based broadcast domains */
521 static unsigned int zebra_evpn_acc_vl_hash_keymake(const void *p)
522 {
523 const struct zebra_evpn_access_bd *acc_bd = p;
524
525 return jhash_1word(acc_bd->vid, 0);
526 }
527
528 /* Compare two VLAN based broadcast domains */
529 static bool zebra_evpn_acc_vl_cmp(const void *p1, const void *p2)
530 {
531 const struct zebra_evpn_access_bd *acc_bd1 = p1;
532 const struct zebra_evpn_access_bd *acc_bd2 = p2;
533
534 if (acc_bd1 == NULL && acc_bd2 == NULL)
535 return true;
536
537 if (acc_bd1 == NULL || acc_bd2 == NULL)
538 return false;
539
540 return (acc_bd1->vid == acc_bd2->vid);
541 }
542
543 /* Lookup VLAN based broadcast domain */
544 static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid)
545 {
546 struct zebra_evpn_access_bd *acc_bd;
547 struct zebra_evpn_access_bd tmp;
548
549 tmp.vid = vid;
550 acc_bd = hash_lookup(zmh_info->evpn_vlan_table, &tmp);
551
552 return acc_bd;
553 }
554
555 /* A new broadcast domain can be created when a VLAN member or VLAN<=>VxLAN_IF
556 * mapping is added.
557 */
558 static struct zebra_evpn_access_bd *
559 zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if)
560 {
561 struct zebra_evpn_access_bd *acc_bd;
562 struct interface *vlan_if;
563
564 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
565 zlog_debug("access vlan %d add", vid);
566
567 acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd));
568
569 acc_bd->vid = vid;
570
571 /* Initialize the mbr list */
572 acc_bd->mbr_zifs = list_new();
573
574 /* Add to hash */
575 (void)hash_get(zmh_info->evpn_vlan_table, acc_bd, hash_alloc_intern);
576
577 /* check if an svi exists for the vlan */
578 if (br_if) {
579 vlan_if = zvni_map_to_svi(vid, br_if);
580 if (vlan_if) {
581 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
582 zlog_debug("vlan %d SVI %s set", vid,
583 vlan_if->name);
584 acc_bd->vlan_zif = vlan_if->info;
585 }
586 }
587 return acc_bd;
588 }
589
590 /* Free VLAN based broadcast domain -
591 * This just frees appropriate memory, caller should have taken other
592 * needed actions.
593 */
594 static void zebra_evpn_acc_vl_free(struct zebra_evpn_access_bd *acc_bd)
595 {
596 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
597 zlog_debug("access vlan %d del", acc_bd->vid);
598
599 if (acc_bd->vlan_zif && acc_bd->zevpn && acc_bd->zevpn->mac_table)
600 zebra_evpn_mac_svi_del(acc_bd->vlan_zif->ifp, acc_bd->zevpn);
601
602 /* cleanup resources maintained against the ES */
603 list_delete(&acc_bd->mbr_zifs);
604
605 /* remove EVI from various tables */
606 hash_release(zmh_info->evpn_vlan_table, acc_bd);
607
608 XFREE(MTYPE_ZACC_BD, acc_bd);
609 }
610
611 static void zebra_evpn_acc_vl_cleanup_all(struct hash_bucket *bucket, void *arg)
612 {
613 struct zebra_evpn_access_bd *acc_bd = bucket->data;
614
615 zebra_evpn_acc_vl_free(acc_bd);
616 }
617
618 /* called when a bd mbr is removed or VxLAN_IF is diassociated from the access
619 * VLAN
620 */
621 static void zebra_evpn_acc_bd_free_on_deref(struct zebra_evpn_access_bd *acc_bd)
622 {
623 if (!list_isempty(acc_bd->mbr_zifs) || acc_bd->vxlan_zif)
624 return;
625
626 /* if there are no references free the EVI */
627 zebra_evpn_acc_vl_free(acc_bd);
628 }
629
630 /* called when a SVI is goes up/down */
631 void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
632 struct zebra_if *br_zif, bool is_up)
633 {
634 struct zebra_evpn_access_bd *acc_bd;
635 struct zebra_l2info_bridge *br;
636 uint16_t vid;
637 struct zebra_if *tmp_br_zif = br_zif;
638
639 if (!tmp_br_zif) {
640 if (!vlan_zif->link || !vlan_zif->link->info)
641 return;
642
643 tmp_br_zif = vlan_zif->link->info;
644 }
645
646 br = &tmp_br_zif->l2info.br;
647 /* ignore vlan unaware bridges */
648 if (!br->vlan_aware)
649 return;
650
651 vid = vlan_zif->l2info.vl.vid;
652 acc_bd = zebra_evpn_acc_vl_find(vid);
653 if (!acc_bd)
654 return;
655
656 if (is_up) {
657 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
658 zlog_debug("vlan %d SVI %s set", vid,
659 vlan_zif->ifp->name);
660
661 acc_bd->vlan_zif = vlan_zif;
662 if (acc_bd->zevpn)
663 zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp,
664 acc_bd->zevpn);
665 } else if (acc_bd->vlan_zif) {
666 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
667 zlog_debug("vlan %d SVI clear", vid);
668 acc_bd->vlan_zif = NULL;
669 if (acc_bd->zevpn && acc_bd->zevpn->mac_table)
670 zebra_evpn_mac_svi_del(vlan_zif->ifp, acc_bd->zevpn);
671 }
672 }
673
674 /* On some events macs are force-flushed. This api can be used to reinstate
675 * the svi-mac after such cleanup-events.
676 */
677 void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if)
678 {
679 zebra_evpn_acc_bd_svi_set(vlan_if->info, NULL,
680 if_is_operative(vlan_if));
681 }
682
683 /* called when a EVPN-L2VNI is set or cleared against a BD */
684 static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
685 struct zebra_evpn *zevpn,
686 struct zebra_evpn *old_zevpn)
687 {
688 struct zebra_if *zif;
689 struct listnode *node;
690
691 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
692 zlog_debug("access vlan %d l2-vni %u set",
693 acc_bd->vid, zevpn ? zevpn->vni : 0);
694
695 for (ALL_LIST_ELEMENTS_RO(acc_bd->mbr_zifs, node, zif)) {
696 if (!zif->es_info.es)
697 continue;
698
699 if (zevpn)
700 zebra_evpn_local_es_evi_add(zif->es_info.es, zevpn);
701 else if (old_zevpn)
702 zebra_evpn_local_es_evi_del(zif->es_info.es, old_zevpn);
703 }
704
705 if (acc_bd->vlan_zif) {
706 if (zevpn)
707 zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp,
708 acc_bd->zevpn);
709 else if (old_zevpn && old_zevpn->mac_table)
710 zebra_evpn_mac_svi_del(acc_bd->vlan_zif->ifp,
711 old_zevpn);
712 }
713 }
714
715 /* handle VLAN->VxLAN_IF association */
716 void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id,
717 struct zebra_if *vxlan_zif)
718 {
719 vni_t old_vni;
720 struct zebra_evpn_access_bd *acc_bd;
721 struct zebra_evpn *old_zevpn;
722
723 if (!vid)
724 return;
725
726 if (!vni_id)
727 return;
728
729 acc_bd = zebra_evpn_acc_vl_find(vid);
730 if (!acc_bd)
731 acc_bd = zebra_evpn_acc_vl_new(vid,
732 vxlan_zif->brslave_info.br_if);
733
734 old_vni = acc_bd->vni;
735
736 if (vni_id == old_vni)
737 return;
738
739 acc_bd->vni = vni_id;
740 acc_bd->vxlan_zif = vxlan_zif;
741
742 old_zevpn = acc_bd->zevpn;
743 acc_bd->zevpn = zebra_evpn_lookup(vni_id);
744 if (acc_bd->zevpn == old_zevpn)
745 return;
746
747 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
748 zlog_debug("access vlan %d vni %u ref", acc_bd->vid, vni_id);
749
750 zlog_err("access vlan %d vni %u ref", acc_bd->vid, vni_id);
751
752 if (old_zevpn)
753 zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
754
755 if (acc_bd->zevpn)
756 zebra_evpn_acc_bd_evpn_set(acc_bd, acc_bd->zevpn, NULL);
757 }
758
759 /* handle VLAN->VxLAN_IF deref */
760 void zebra_evpn_vl_vxl_deref(uint16_t vid, vni_t vni_id,
761 struct zebra_if *vxlan_zif)
762 {
763 struct zebra_evpn_access_bd *acc_bd;
764
765 if (!vid)
766 return;
767
768 if (!vni_id)
769 return;
770
771 acc_bd = zebra_evpn_acc_vl_find(vid);
772 if (!acc_bd)
773 return;
774
775 /* clear vxlan_if only if it matches */
776 if (acc_bd->vni != vni_id)
777 return;
778
779 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
780 zlog_debug("access vlan %d vni %u deref", acc_bd->vid, vni_id);
781
782 if (acc_bd->zevpn)
783 zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, acc_bd->zevpn);
784
785 acc_bd->zevpn = NULL;
786 acc_bd->vxlan_zif = NULL;
787 acc_bd->vni = 0;
788
789 /* if there are no other references the access_bd can be freed */
790 zebra_evpn_acc_bd_free_on_deref(acc_bd);
791 }
792
793 /* handle EVPN add/del */
794 void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, struct zebra_evpn *zevpn,
795 bool set)
796 {
797 struct zebra_vxlan_vni *vni;
798 struct zebra_evpn_access_bd *acc_bd;
799
800 if (!zif)
801 return;
802
803 /* locate access_bd associated with the vxlan device */
804 vni = zebra_vxlan_if_vni_find(zif, zevpn->vni);
805 if (!vni)
806 return;
807
808 acc_bd = zebra_evpn_acc_vl_find(vni->access_vlan);
809 if (!acc_bd)
810 return;
811
812 if (set) {
813 zebra_evpn_es_set_base_evpn(zevpn);
814 if (acc_bd->zevpn != zevpn) {
815 acc_bd->zevpn = zevpn;
816 zebra_evpn_acc_bd_evpn_set(acc_bd, zevpn, NULL);
817 }
818 } else {
819 if (acc_bd->zevpn) {
820 struct zebra_evpn *old_zevpn = acc_bd->zevpn;
821 acc_bd->zevpn = NULL;
822 zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
823 }
824 }
825 }
826
827 /* handle addition of new VLAN members */
828 void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif)
829 {
830 struct zebra_evpn_access_bd *acc_bd;
831
832 if (!vid)
833 return;
834
835 acc_bd = zebra_evpn_acc_vl_find(vid);
836 if (!acc_bd)
837 acc_bd = zebra_evpn_acc_vl_new(vid, zif->brslave_info.br_if);
838
839 if (listnode_lookup(acc_bd->mbr_zifs, zif))
840 return;
841
842 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
843 zlog_debug("access vlan %d mbr %s ref",
844 vid, zif->ifp->name);
845
846 listnode_add(acc_bd->mbr_zifs, zif);
847 if (acc_bd->zevpn && zif->es_info.es)
848 zebra_evpn_local_es_evi_add(zif->es_info.es, acc_bd->zevpn);
849 }
850
851 /* handle deletion of VLAN members */
852 void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif)
853 {
854 struct zebra_evpn_access_bd *acc_bd;
855 struct listnode *node;
856
857 if (!vid)
858 return;
859
860 acc_bd = zebra_evpn_acc_vl_find(vid);
861 if (!acc_bd)
862 return;
863
864 node = listnode_lookup(acc_bd->mbr_zifs, zif);
865 if (!node)
866 return;
867
868 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
869 zlog_debug("access vlan %d mbr %s deref",
870 vid, zif->ifp->name);
871
872 list_delete_node(acc_bd->mbr_zifs, node);
873
874 if (acc_bd->zevpn && zif->es_info.es)
875 zebra_evpn_local_es_evi_del(zif->es_info.es, acc_bd->zevpn);
876
877 /* if there are no other references the access_bd can be freed */
878 zebra_evpn_acc_bd_free_on_deref(acc_bd);
879 }
880
881 static void zebra_evpn_acc_vl_adv_svi_mac_cb(struct hash_bucket *bucket,
882 void *ctxt)
883 {
884 struct zebra_evpn_access_bd *acc_bd = bucket->data;
885
886 if (acc_bd->vlan_zif && acc_bd->zevpn)
887 zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp, acc_bd->zevpn);
888 }
889
890 /* called when advertise SVI MAC is enabled on the switch */
891 static void zebra_evpn_acc_vl_adv_svi_mac_all(void)
892 {
893 hash_iterate(zmh_info->evpn_vlan_table,
894 zebra_evpn_acc_vl_adv_svi_mac_cb, NULL);
895 }
896
897 static void zebra_evpn_acc_vl_json_fill(struct zebra_evpn_access_bd *acc_bd,
898 json_object *json, bool detail)
899 {
900 json_object_int_add(json, "vlan", acc_bd->vid);
901 if (acc_bd->vxlan_zif)
902 json_object_string_add(json, "vxlanIf",
903 acc_bd->vxlan_zif->ifp->name);
904 if (acc_bd->zevpn)
905 json_object_int_add(json, "vni", acc_bd->zevpn->vni);
906 if (acc_bd->mbr_zifs)
907 json_object_int_add(json, "memberIfCount",
908 listcount(acc_bd->mbr_zifs));
909
910 if (detail) {
911 json_object *json_mbrs;
912 json_object *json_mbr;
913 struct zebra_if *zif;
914 struct listnode *node;
915
916
917 json_mbrs = json_object_new_array();
918 for (ALL_LIST_ELEMENTS_RO(acc_bd->mbr_zifs, node, zif)) {
919 json_mbr = json_object_new_object();
920 json_object_string_add(json_mbr, "ifName",
921 zif->ifp->name);
922 json_object_array_add(json_mbrs, json_mbr);
923 }
924 json_object_object_add(json, "members", json_mbrs);
925 }
926 }
927
928 static void zebra_evpn_acc_vl_show_entry_detail(struct vty *vty,
929 struct zebra_evpn_access_bd *acc_bd, json_object *json)
930 {
931 struct zebra_if *zif;
932 struct listnode *node;
933
934 if (json) {
935 zebra_evpn_acc_vl_json_fill(acc_bd, json, true);
936 } else {
937 vty_out(vty, "VLAN: %u\n", acc_bd->vid);
938 vty_out(vty, " VxLAN Interface: %s\n",
939 acc_bd->vxlan_zif ?
940 acc_bd->vxlan_zif->ifp->name : "-");
941 vty_out(vty, " SVI: %s\n",
942 acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-");
943 vty_out(vty, " L2-VNI: %d\n",
944 acc_bd->zevpn ? acc_bd->zevpn->vni : 0);
945 vty_out(vty, " Member Count: %d\n",
946 listcount(acc_bd->mbr_zifs));
947 vty_out(vty, " Members: \n");
948 for (ALL_LIST_ELEMENTS_RO(acc_bd->mbr_zifs, node, zif))
949 vty_out(vty, " %s\n", zif->ifp->name);
950 vty_out(vty, "\n");
951 }
952 }
953
954 static void zebra_evpn_acc_vl_show_entry(struct vty *vty,
955 struct zebra_evpn_access_bd *acc_bd, json_object *json)
956 {
957 if (json) {
958 zebra_evpn_acc_vl_json_fill(acc_bd, json, false);
959 } else {
960 vty_out(vty, "%-5u %-15s %-8d %-15s %u\n", acc_bd->vid,
961 acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-",
962 acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
963 acc_bd->vxlan_zif ? acc_bd->vxlan_zif->ifp->name : "-",
964 listcount(acc_bd->mbr_zifs));
965 }
966 }
967
968 static void zebra_evpn_acc_vl_show_hash(struct hash_bucket *bucket, void *ctxt)
969 {
970 struct evpn_mh_show_ctx *wctx = ctxt;
971 struct zebra_evpn_access_bd *acc_bd = bucket->data;
972 json_object *json = NULL;
973
974 if (wctx->json)
975 json = json_object_new_object();
976 if (wctx->detail)
977 zebra_evpn_acc_vl_show_entry_detail(wctx->vty, acc_bd, json);
978 else
979 zebra_evpn_acc_vl_show_entry(wctx->vty, acc_bd, json);
980 if (json)
981 json_object_array_add(wctx->json, json);
982 }
983
984 void zebra_evpn_acc_vl_show(struct vty *vty, bool uj)
985 {
986 struct evpn_mh_show_ctx wctx;
987 json_object *json_array = NULL;
988
989 if (uj)
990 json_array = json_object_new_array();
991
992 memset(&wctx, 0, sizeof(wctx));
993 wctx.vty = vty;
994 wctx.json = json_array;
995 wctx.detail = false;
996
997 if (!uj)
998 vty_out(vty, "%-5s %-15s %-8s %-15s %s\n", "VLAN", "SVI",
999 "L2-VNI", "VXLAN-IF", "# Members");
1000
1001 hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
1002 &wctx);
1003
1004 if (uj)
1005 vty_json(vty, json_array);
1006 }
1007
1008 void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj)
1009 {
1010 struct evpn_mh_show_ctx wctx;
1011 json_object *json_array = NULL;
1012
1013 if (uj)
1014 json_array = json_object_new_array();
1015 memset(&wctx, 0, sizeof(wctx));
1016 wctx.vty = vty;
1017 wctx.json = json_array;
1018 wctx.detail = true;
1019
1020 hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
1021 &wctx);
1022
1023 if (uj)
1024 vty_json(vty, json_array);
1025 }
1026
1027 void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid)
1028 {
1029 json_object *json = NULL;
1030 struct zebra_evpn_access_bd *acc_bd;
1031
1032 if (uj)
1033 json = json_object_new_object();
1034
1035 acc_bd = zebra_evpn_acc_vl_find(vid);
1036 if (acc_bd) {
1037 zebra_evpn_acc_vl_show_entry_detail(vty, acc_bd, json);
1038 } else {
1039 if (!json)
1040 vty_out(vty, "VLAN %u not present\n", vid);
1041 }
1042
1043 if (uj)
1044 vty_json(vty, json);
1045 }
1046
1047 /* Initialize VLAN member bitmap on an interface. Although VLAN membership
1048 * is independent of EVPN we only process it if its of interest to EVPN-MH
1049 * i.e. on access ports that can be setup as Ethernet Segments. And that is
1050 * intended as an optimization.
1051 */
1052 void zebra_evpn_if_init(struct zebra_if *zif)
1053 {
1054 if (!zebra_evpn_is_if_es_capable(zif))
1055 return;
1056
1057 if (!bf_is_inited(zif->vlan_bitmap))
1058 bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX);
1059
1060 /* if an es_id and sysmac are already present against the interface
1061 * activate it
1062 */
1063 zebra_evpn_local_es_update(zif, &zif->es_info.esi);
1064 }
1065
1066 /* handle deletion of an access port by removing it from all associated
1067 * broadcast domains.
1068 */
1069 void zebra_evpn_if_cleanup(struct zebra_if *zif)
1070 {
1071 vlanid_t vid;
1072 struct zebra_evpn_es *es;
1073
1074 if (bf_is_inited(zif->vlan_bitmap)) {
1075 bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX)
1076 {
1077 zebra_evpn_vl_mbr_deref(vid, zif);
1078 }
1079
1080 bf_free(zif->vlan_bitmap);
1081 }
1082
1083 /* Delete associated Ethernet Segment */
1084 es = zif->es_info.es;
1085 if (es)
1086 zebra_evpn_local_es_del(&es);
1087 }
1088
1089 /*****************************************************************************
1090 * L2 NH/NHG Management
1091 * A L2 NH entry is programmed in the kernel for every ES-VTEP entry. This
1092 * NH is then added to the L2-ECMP-NHG associated with the ES.
1093 */
1094 static uint32_t zebra_evpn_nhid_alloc(struct zebra_evpn_es *es)
1095 {
1096 uint32_t id;
1097 uint32_t nh_id;
1098
1099 bf_assign_index(zmh_info->nh_id_bitmap, id);
1100
1101 if (!id)
1102 return 0;
1103
1104 if (es) {
1105 nh_id = id | EVPN_NHG_ID_TYPE_BIT;
1106 /* Add to NHG hash */
1107 es->nhg_id = nh_id;
1108 (void)hash_get(zmh_info->nhg_table, es, hash_alloc_intern);
1109 } else {
1110 nh_id = id | EVPN_NH_ID_TYPE_BIT;
1111 }
1112
1113 return nh_id;
1114 }
1115
1116 static void zebra_evpn_nhid_free(uint32_t nh_id, struct zebra_evpn_es *es)
1117 {
1118 uint32_t id = (nh_id & EVPN_NH_ID_VAL_MASK);
1119
1120 if (!id)
1121 return;
1122
1123 if (es) {
1124 hash_release(zmh_info->nhg_table, es);
1125 es->nhg_id = 0;
1126 }
1127
1128 bf_release_index(zmh_info->nh_id_bitmap, id);
1129 }
1130
1131 static unsigned int zebra_evpn_nh_ip_hash_keymake(const void *p)
1132 {
1133 const struct zebra_evpn_l2_nh *nh = p;
1134
1135 return jhash_1word(nh->vtep_ip.s_addr, 0);
1136 }
1137
1138 static bool zebra_evpn_nh_ip_cmp(const void *p1, const void *p2)
1139 {
1140 const struct zebra_evpn_l2_nh *nh1 = p1;
1141 const struct zebra_evpn_l2_nh *nh2 = p2;
1142
1143 if (nh1 == NULL && nh2 == NULL)
1144 return true;
1145
1146 if (nh1 == NULL || nh2 == NULL)
1147 return false;
1148
1149 return (nh1->vtep_ip.s_addr == nh2->vtep_ip.s_addr);
1150 }
1151
1152 static unsigned int zebra_evpn_nhg_hash_keymake(const void *p)
1153 {
1154 const struct zebra_evpn_es *es = p;
1155
1156 return jhash_1word(es->nhg_id, 0);
1157 }
1158
1159 static bool zebra_evpn_nhg_cmp(const void *p1, const void *p2)
1160 {
1161 const struct zebra_evpn_es *es1 = p1;
1162 const struct zebra_evpn_es *es2 = p2;
1163
1164 if (es1 == NULL && es2 == NULL)
1165 return true;
1166
1167 if (es1 == NULL || es2 == NULL)
1168 return false;
1169
1170 return (es1->nhg_id == es2->nhg_id);
1171 }
1172
1173 /* Lookup ES using the NHG id associated with it */
1174 static struct zebra_evpn_es *zebra_evpn_nhg_find(uint32_t nhg_id)
1175 {
1176 struct zebra_evpn_es *es;
1177 struct zebra_evpn_es tmp;
1178
1179 tmp.nhg_id = nhg_id;
1180 es = hash_lookup(zmh_info->nhg_table, &tmp);
1181
1182 return es;
1183 }
1184
1185 /* Returns TRUE if the NHG is associated with a local ES */
1186 bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
1187 struct zebra_evpn_es **local_es)
1188 {
1189 struct zebra_evpn_es *es;
1190
1191 es = zebra_evpn_nhg_find(nhg_id);
1192 if (es && (es->flags & ZEBRA_EVPNES_LOCAL)) {
1193 *local_es = es;
1194 return true;
1195 }
1196
1197 *local_es = NULL;
1198 return false;
1199 }
1200
1201 /* update remote macs associated with the ES */
1202 static void zebra_evpn_nhg_mac_update(struct zebra_evpn_es *es)
1203 {
1204 struct zebra_mac *mac;
1205 struct listnode *node;
1206 bool local_via_nw;
1207
1208 local_via_nw = zebra_evpn_es_local_mac_via_network_port(es);
1209 if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
1210 zlog_debug("mac update on es %s nhg %s", es->esi_str,
1211 (es->flags & ZEBRA_EVPNES_NHG_ACTIVE)
1212 ? "activate"
1213 : "de-activate");
1214
1215 for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
1216 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
1217 || (local_via_nw && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
1218 && zebra_evpn_mac_is_static(mac))) {
1219 if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) {
1220 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
1221 zlog_debug(
1222 "%smac %pEA install via es %s nhg 0x%x",
1223 (mac->flags & ZEBRA_MAC_REMOTE)
1224 ? "rem"
1225 : "local-nw",
1226 &mac->macaddr, es->esi_str,
1227 es->nhg_id);
1228 zebra_evpn_rem_mac_install(
1229 mac->zevpn, mac, false /*was_static*/);
1230 } else {
1231 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
1232 zlog_debug(
1233 "%smac %pEA un-install es %s",
1234 (mac->flags & ZEBRA_MAC_REMOTE)
1235 ? "rem"
1236 : "local-nw",
1237 &mac->macaddr, es->esi_str);
1238 zebra_evpn_rem_mac_uninstall(mac->zevpn, mac,
1239 true /*force*/);
1240 }
1241 }
1242 }
1243 }
1244
1245 /* The MAC ECMP group is activated on the first VTEP */
1246 static void zebra_evpn_nhg_update(struct zebra_evpn_es *es)
1247 {
1248 uint32_t nh_cnt = 0;
1249 struct nh_grp nh_ids[ES_VTEP_MAX_CNT];
1250 struct zebra_evpn_es_vtep *es_vtep;
1251 struct listnode *node;
1252
1253 if (!es->nhg_id)
1254 return;
1255
1256 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1257 if (!es_vtep->nh)
1258 continue;
1259
1260 if (nh_cnt >= ES_VTEP_MAX_CNT)
1261 break;
1262
1263 memset(&nh_ids[nh_cnt], 0, sizeof(struct nh_grp));
1264 nh_ids[nh_cnt].id = es_vtep->nh->nh_id;
1265 ++nh_cnt;
1266 }
1267
1268 if (nh_cnt) {
1269 if (IS_ZEBRA_DEBUG_EVPN_MH_NH) {
1270 char nh_str[ES_VTEP_LIST_STR_SZ];
1271 uint32_t i;
1272 char nh_buf[16];
1273
1274 nh_str[0] = '\0';
1275 for (i = 0; i < nh_cnt; ++i) {
1276 snprintf(nh_buf, sizeof(nh_buf), "%u ",
1277 nh_ids[i].id);
1278 strlcat(nh_str, nh_buf, sizeof(nh_str));
1279 }
1280 zlog_debug("es %s nhg %u add %s", es->esi_str,
1281 es->nhg_id, nh_str);
1282 }
1283
1284 kernel_upd_mac_nhg(es->nhg_id, nh_cnt, nh_ids);
1285 if (!(es->flags & ZEBRA_EVPNES_NHG_ACTIVE)) {
1286 es->flags |= ZEBRA_EVPNES_NHG_ACTIVE;
1287 /* add backup NHG to the br-port */
1288 if ((es->flags & ZEBRA_EVPNES_LOCAL))
1289 zebra_evpn_es_br_port_dplane_update(es,
1290 __func__);
1291 zebra_evpn_nhg_mac_update(es);
1292 }
1293 } else {
1294 if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) {
1295 if (IS_ZEBRA_DEBUG_EVPN_MH_NH)
1296 zlog_debug("es %s nhg %u del", es->esi_str,
1297 es->nhg_id);
1298 es->flags &= ~ZEBRA_EVPNES_NHG_ACTIVE;
1299 /* remove backup NHG from the br-port */
1300 if ((es->flags & ZEBRA_EVPNES_LOCAL))
1301 zebra_evpn_es_br_port_dplane_update(es,
1302 __func__);
1303 zebra_evpn_nhg_mac_update(es);
1304 kernel_del_mac_nhg(es->nhg_id);
1305 }
1306 }
1307
1308 }
1309
1310 static void zebra_evpn_es_l2_nh_show_entry(struct zebra_evpn_l2_nh *nh,
1311 struct vty *vty,
1312 json_object *json_array)
1313 {
1314 if (json_array) {
1315 json_object *json = NULL;
1316
1317 json = json_object_new_object();
1318 json_object_string_addf(json, "vtep", "%pI4", &nh->vtep_ip);
1319 json_object_int_add(json, "nhId", nh->nh_id);
1320 json_object_int_add(json, "refCnt", nh->ref_cnt);
1321
1322 json_object_array_add(json_array, json);
1323 } else {
1324 vty_out(vty, "%-16pI4 %-10u %u\n", &nh->vtep_ip, nh->nh_id,
1325 nh->ref_cnt);
1326 }
1327 }
1328
1329 static void zebra_evpn_l2_nh_show_cb(struct hash_bucket *bucket, void *ctxt)
1330 {
1331 struct zebra_evpn_l2_nh *nh = (struct zebra_evpn_l2_nh *)bucket->data;
1332 struct evpn_mh_show_ctx *wctx = (struct evpn_mh_show_ctx *)ctxt;
1333
1334 zebra_evpn_es_l2_nh_show_entry(nh, wctx->vty, wctx->json);
1335 }
1336
1337 void zebra_evpn_l2_nh_show(struct vty *vty, bool uj)
1338 {
1339 struct evpn_mh_show_ctx wctx;
1340 json_object *json_array = NULL;
1341
1342 if (uj) {
1343 json_array = json_object_new_array();
1344 } else {
1345 vty_out(vty, "%-16s %-10s %s\n", "VTEP", "NH id", "#ES");
1346 }
1347
1348 memset(&wctx, 0, sizeof(wctx));
1349 wctx.vty = vty;
1350 wctx.json = json_array;
1351
1352 hash_iterate(zmh_info->nh_ip_table, zebra_evpn_l2_nh_show_cb, &wctx);
1353
1354 if (uj)
1355 vty_json(vty, json_array);
1356 }
1357
1358 static struct zebra_evpn_l2_nh *zebra_evpn_l2_nh_find(struct in_addr vtep_ip)
1359 {
1360 struct zebra_evpn_l2_nh *nh;
1361 struct zebra_evpn_l2_nh tmp;
1362
1363 tmp.vtep_ip.s_addr = vtep_ip.s_addr;
1364 nh = hash_lookup(zmh_info->nh_ip_table, &tmp);
1365
1366 return nh;
1367 }
1368
1369 static struct zebra_evpn_l2_nh *zebra_evpn_l2_nh_alloc(struct in_addr vtep_ip)
1370 {
1371 struct zebra_evpn_l2_nh *nh;
1372
1373 nh = XCALLOC(MTYPE_L2_NH, sizeof(*nh));
1374 nh->vtep_ip = vtep_ip;
1375 (void)hash_get(zmh_info->nh_ip_table, nh, hash_alloc_intern);
1376
1377 nh->nh_id = zebra_evpn_nhid_alloc(NULL);
1378 if (!nh->nh_id) {
1379 hash_release(zmh_info->nh_ip_table, nh);
1380 XFREE(MTYPE_L2_NH, nh);
1381 return NULL;
1382 }
1383
1384 /* install the NH in the dataplane */
1385 kernel_upd_mac_nh(nh->nh_id, nh->vtep_ip);
1386
1387 return nh;
1388 }
1389
1390 static void zebra_evpn_l2_nh_free(struct zebra_evpn_l2_nh *nh)
1391 {
1392 /* delete the NH from the dataplane */
1393 kernel_del_mac_nh(nh->nh_id);
1394
1395 zebra_evpn_nhid_free(nh->nh_id, NULL);
1396 hash_release(zmh_info->nh_ip_table, nh);
1397 XFREE(MTYPE_L2_NH, nh);
1398 }
1399
1400 static void zebra_evpn_l2_nh_es_vtep_ref(struct zebra_evpn_es_vtep *es_vtep)
1401 {
1402 if (es_vtep->nh)
1403 return;
1404
1405 es_vtep->nh = zebra_evpn_l2_nh_find(es_vtep->vtep_ip);
1406 if (!es_vtep->nh)
1407 es_vtep->nh = zebra_evpn_l2_nh_alloc(es_vtep->vtep_ip);
1408
1409 if (!es_vtep->nh) {
1410 zlog_warn("es %s vtep %pI4 nh ref failed", es_vtep->es->esi_str,
1411 &es_vtep->vtep_ip);
1412 return;
1413 }
1414
1415 ++es_vtep->nh->ref_cnt;
1416
1417 if (IS_ZEBRA_DEBUG_EVPN_MH_NH)
1418 zlog_debug("es %s vtep %pI4 nh %u ref %u", es_vtep->es->esi_str,
1419 &es_vtep->vtep_ip, es_vtep->nh->nh_id,
1420 es_vtep->nh->ref_cnt);
1421
1422 /* add the NH to the parent NHG */
1423 zebra_evpn_nhg_update(es_vtep->es);
1424 }
1425
1426 static void zebra_evpn_l2_nh_es_vtep_deref(struct zebra_evpn_es_vtep *es_vtep)
1427 {
1428 struct zebra_evpn_l2_nh *nh = es_vtep->nh;
1429
1430 if (!nh)
1431 return;
1432
1433 es_vtep->nh = NULL;
1434 if (nh->ref_cnt)
1435 --nh->ref_cnt;
1436
1437 if (IS_ZEBRA_DEBUG_EVPN_MH_NH)
1438 zlog_debug("es %s vtep %pI4 nh %u deref %u",
1439 es_vtep->es->esi_str, &es_vtep->vtep_ip, nh->nh_id,
1440 nh->ref_cnt);
1441
1442 /* remove the NH from the parent NHG */
1443 zebra_evpn_nhg_update(es_vtep->es);
1444
1445 /* uninstall the NH */
1446 if (!nh->ref_cnt)
1447 zebra_evpn_l2_nh_free(nh);
1448 }
1449
1450 /*****************************************************************************/
1451 /* Ethernet Segment Management
1452 * 1. Ethernet Segment is a collection of links attached to the same
1453 * server (MHD) or switch (MHN)
1454 * 2. An Ethernet Segment can span multiple PEs and is identified by the
1455 * 10-byte ES-ID.
1456 * 3. Zebra manages the local ESI configuration.
1457 * 4. It also maintains the aliasing that maps an ESI (local or remote)
1458 * to one or more PEs/VTEPs.
1459 * 5. remote ESs are added by BGP (on rxing EAD Type-1 routes)
1460 */
1461 /* A list of remote VTEPs is maintained for each ES. This list includes -
1462 * 1. VTEPs for which we have imported the ESR i.e. ES-peers
1463 * 2. VTEPs that have an "active" ES-EVI VTEP i.e. EAD-per-ES and EAD-per-EVI
1464 * have been imported into one or more EVPNs
1465 */
1466 static int zebra_evpn_es_vtep_cmp(void *p1, void *p2)
1467 {
1468 const struct zebra_evpn_es_vtep *es_vtep1 = p1;
1469 const struct zebra_evpn_es_vtep *es_vtep2 = p2;
1470
1471 return es_vtep1->vtep_ip.s_addr - es_vtep2->vtep_ip.s_addr;
1472 }
1473
1474 static struct zebra_evpn_es_vtep *zebra_evpn_es_vtep_new(
1475 struct zebra_evpn_es *es, struct in_addr vtep_ip)
1476 {
1477 struct zebra_evpn_es_vtep *es_vtep;
1478
1479 es_vtep = XCALLOC(MTYPE_ZES_VTEP, sizeof(*es_vtep));
1480
1481 es_vtep->es = es;
1482 es_vtep->vtep_ip.s_addr = vtep_ip.s_addr;
1483 listnode_init(&es_vtep->es_listnode, es_vtep);
1484 listnode_add_sort(es->es_vtep_list, &es_vtep->es_listnode);
1485
1486 return es_vtep;
1487 }
1488
1489 static void zebra_evpn_es_vtep_free(struct zebra_evpn_es_vtep *es_vtep)
1490 {
1491 struct zebra_evpn_es *es = es_vtep->es;
1492
1493 list_delete_node(es->es_vtep_list, &es_vtep->es_listnode);
1494 /* update the L2-NHG associated with the ES */
1495 zebra_evpn_l2_nh_es_vtep_deref(es_vtep);
1496 XFREE(MTYPE_ZES_VTEP, es_vtep);
1497 }
1498
1499
1500 /* check if VTEP is already part of the list */
1501 static struct zebra_evpn_es_vtep *zebra_evpn_es_vtep_find(
1502 struct zebra_evpn_es *es, struct in_addr vtep_ip)
1503 {
1504 struct listnode *node = NULL;
1505 struct zebra_evpn_es_vtep *es_vtep;
1506
1507 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1508 if (es_vtep->vtep_ip.s_addr == vtep_ip.s_addr)
1509 return es_vtep;
1510 }
1511 return NULL;
1512 }
1513
1514 /* flush all the dataplane br-port info associated with the ES */
1515 static bool zebra_evpn_es_br_port_dplane_clear(struct zebra_evpn_es *es)
1516 {
1517 struct in_addr sph_filters[ES_VTEP_MAX_CNT];
1518
1519 if (!(es->flags & ZEBRA_EVPNES_BR_PORT))
1520 return false;
1521
1522 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1523 zlog_debug("es %s br-port dplane clear", es->esi_str);
1524
1525 memset(&sph_filters, 0, sizeof(sph_filters));
1526 dplane_br_port_update(es->zif->ifp, false /* non_df */, 0, sph_filters,
1527 0 /* backup_nhg_id */);
1528 return true;
1529 }
1530
1531 static inline bool
1532 zebra_evpn_es_br_port_dplane_update_needed(struct zebra_evpn_es *es)
1533 {
1534 return (es->flags & ZEBRA_EVPNES_NON_DF)
1535 || (es->flags & ZEBRA_EVPNES_NHG_ACTIVE)
1536 || listcount(es->es_vtep_list);
1537 }
1538
1539 /* returns TRUE if dplane entry was updated */
1540 static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
1541 const char *caller)
1542 {
1543 uint32_t backup_nhg_id;
1544 struct in_addr sph_filters[ES_VTEP_MAX_CNT];
1545 struct listnode *node = NULL;
1546 struct zebra_evpn_es_vtep *es_vtep;
1547 uint32_t sph_filter_cnt = 0;
1548
1549 if (!(es->flags & ZEBRA_EVPNES_LOCAL))
1550 return zebra_evpn_es_br_port_dplane_clear(es);
1551
1552 /* If the ES is not a bridge port there is nothing
1553 * in the dataplane
1554 */
1555 if (!(es->flags & ZEBRA_EVPNES_BR_PORT))
1556 return false;
1557
1558 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1559 zlog_debug("es %s br-port dplane update by %s", es->esi_str,
1560 caller);
1561 backup_nhg_id = (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) ? es->nhg_id : 0;
1562
1563 memset(&sph_filters, 0, sizeof(sph_filters));
1564 if (es->flags & ZEBRA_EVPNES_BYPASS) {
1565 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1566 zlog_debug(
1567 "es %s SPH filter disabled as it is in bypass",
1568 es->esi_str);
1569 } else {
1570 if (listcount(es->es_vtep_list) > ES_VTEP_MAX_CNT) {
1571 zlog_warn("es %s vtep count %d exceeds filter cnt %d",
1572 es->esi_str, listcount(es->es_vtep_list),
1573 ES_VTEP_MAX_CNT);
1574 } else {
1575 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node,
1576 es_vtep)) {
1577 if (es_vtep->flags
1578 & ZEBRA_EVPNES_VTEP_DEL_IN_PROG)
1579 continue;
1580 sph_filters[sph_filter_cnt] = es_vtep->vtep_ip;
1581 ++sph_filter_cnt;
1582 }
1583 }
1584 }
1585
1586 dplane_br_port_update(es->zif->ifp, !!(es->flags & ZEBRA_EVPNES_NON_DF),
1587 sph_filter_cnt, sph_filters, backup_nhg_id);
1588
1589 return true;
1590 }
1591
1592 /* returns TRUE if dplane entry was updated */
1593 static bool zebra_evpn_es_df_change(struct zebra_evpn_es *es, bool new_non_df,
1594 const char *caller, const char *reason)
1595 {
1596 bool old_non_df;
1597
1598 old_non_df = !!(es->flags & ZEBRA_EVPNES_NON_DF);
1599
1600 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1601 zlog_debug("df-change es %s %s to %s; %s: %s", es->esi_str,
1602 old_non_df ? "non-df" : "df",
1603 new_non_df ? "non-df" : "df", caller, reason);
1604
1605 if (old_non_df == new_non_df)
1606 return false;
1607
1608 if (new_non_df)
1609 es->flags |= ZEBRA_EVPNES_NON_DF;
1610 else
1611 es->flags &= ~ZEBRA_EVPNES_NON_DF;
1612
1613 /* update non-DF block filter in the dataplane */
1614 return zebra_evpn_es_br_port_dplane_update(es, __func__);
1615 }
1616
1617
1618 /* returns TRUE if dplane entry was updated */
1619 static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es,
1620 const char *caller)
1621 {
1622 struct listnode *node = NULL;
1623 struct zebra_evpn_es_vtep *es_vtep;
1624 bool new_non_df = false;
1625
1626 /* If the ES is not ready (i.e. not completely configured) there
1627 * is no need to setup the BUM block filter
1628 */
1629 if (!(es->flags & ZEBRA_EVPNES_LOCAL)
1630 || (es->flags & ZEBRA_EVPNES_BYPASS)
1631 || !zmh_info->es_originator_ip.s_addr)
1632 return zebra_evpn_es_df_change(es, new_non_df, caller,
1633 "not-ready");
1634
1635 /* if oper-state is down DF filtering must be on. when the link comes
1636 * up again dataplane should block BUM till FRR has had the chance
1637 * to run DF election again
1638 */
1639 if (!(es->flags & ZEBRA_EVPNES_OPER_UP)) {
1640 new_non_df = true;
1641 return zebra_evpn_es_df_change(es, new_non_df, caller,
1642 "oper-down");
1643 }
1644
1645 /* ES was just created; we need to wait for the peers to rx the
1646 * our Type-4 routes and for the switch to import the peers' Type-4
1647 * routes
1648 */
1649 if (es->df_delay_timer) {
1650 new_non_df = true;
1651 return zebra_evpn_es_df_change(es, new_non_df, caller,
1652 "df-delay");
1653 }
1654
1655 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
1656 /* Only VTEPs that have advertised the ESR can participate
1657 * in DF election
1658 */
1659 if (!(es_vtep->flags & ZEBRA_EVPNES_VTEP_RXED_ESR))
1660 continue;
1661
1662 /* If the DF alg is not the same we should fall back to
1663 * service-carving. But as service-carving is not supported
1664 * we will stop forwarding BUM
1665 */
1666 if (es_vtep->df_alg != EVPN_MH_DF_ALG_PREF) {
1667 new_non_df = true;
1668 break;
1669 }
1670
1671 /* Peer VTEP wins DF election if -
1672 * the peer-VTEP has higher preference (or)
1673 * the pref is the same but peer's IP address is lower
1674 */
1675 if ((es_vtep->df_pref > es->df_pref)
1676 || ((es_vtep->df_pref == es->df_pref)
1677 && (es_vtep->vtep_ip.s_addr
1678 < zmh_info->es_originator_ip.s_addr))) {
1679 new_non_df = true;
1680 break;
1681 }
1682 }
1683
1684 return zebra_evpn_es_df_change(es, new_non_df, caller, "elected");
1685 }
1686
1687 static void zebra_evpn_es_vtep_add(struct zebra_evpn_es *es,
1688 struct in_addr vtep_ip, bool esr_rxed,
1689 uint8_t df_alg, uint16_t df_pref)
1690 {
1691 struct zebra_evpn_es_vtep *es_vtep;
1692 bool old_esr_rxed;
1693 bool dplane_updated = false;
1694
1695 es_vtep = zebra_evpn_es_vtep_find(es, vtep_ip);
1696
1697 if (!es_vtep) {
1698 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1699 zlog_debug("es %s vtep %pI4 add",
1700 es->esi_str, &vtep_ip);
1701 es_vtep = zebra_evpn_es_vtep_new(es, vtep_ip);
1702 /* update the L2-NHG associated with the ES */
1703 zebra_evpn_l2_nh_es_vtep_ref(es_vtep);
1704 }
1705
1706 old_esr_rxed = !!(es_vtep->flags & ZEBRA_EVPNES_VTEP_RXED_ESR);
1707 if ((old_esr_rxed != esr_rxed) || (es_vtep->df_alg != df_alg)
1708 || (es_vtep->df_pref != df_pref)) {
1709 /* If any of the DF election params changed we need to re-run
1710 * DF election
1711 */
1712 if (esr_rxed)
1713 es_vtep->flags |= ZEBRA_EVPNES_VTEP_RXED_ESR;
1714 else
1715 es_vtep->flags &= ~ZEBRA_EVPNES_VTEP_RXED_ESR;
1716 es_vtep->df_alg = df_alg;
1717 es_vtep->df_pref = df_pref;
1718 dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
1719 }
1720 /* add the vtep to the SPH list */
1721 if (!dplane_updated && (es->flags & ZEBRA_EVPNES_LOCAL))
1722 zebra_evpn_es_br_port_dplane_update(es, __func__);
1723 }
1724
1725 static void zebra_evpn_es_vtep_del(struct zebra_evpn_es *es,
1726 struct in_addr vtep_ip)
1727 {
1728 struct zebra_evpn_es_vtep *es_vtep;
1729 bool dplane_updated = false;
1730
1731 es_vtep = zebra_evpn_es_vtep_find(es, vtep_ip);
1732
1733 if (es_vtep) {
1734 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1735 zlog_debug("es %s vtep %pI4 del",
1736 es->esi_str, &vtep_ip);
1737 es_vtep->flags |= ZEBRA_EVPNES_VTEP_DEL_IN_PROG;
1738 if (es_vtep->flags & ZEBRA_EVPNES_VTEP_RXED_ESR) {
1739 es_vtep->flags &= ~ZEBRA_EVPNES_VTEP_RXED_ESR;
1740 dplane_updated =
1741 zebra_evpn_es_run_df_election(es, __func__);
1742 }
1743 /* remove the vtep from the SPH list */
1744 if (!dplane_updated && (es->flags & ZEBRA_EVPNES_LOCAL))
1745 zebra_evpn_es_br_port_dplane_update(es, __func__);
1746 zebra_evpn_es_vtep_free(es_vtep);
1747 }
1748 }
1749
1750 /* compare ES-IDs for the global ES RB tree */
1751 static int zebra_es_rb_cmp(const struct zebra_evpn_es *es1,
1752 const struct zebra_evpn_es *es2)
1753 {
1754 return memcmp(&es1->esi, &es2->esi, ESI_BYTES);
1755 }
1756 RB_GENERATE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
1757
1758 /* Lookup ES */
1759 struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi)
1760 {
1761 struct zebra_evpn_es tmp;
1762
1763 memcpy(&tmp.esi, esi, sizeof(esi_t));
1764 return RB_FIND(zebra_es_rb_head, &zmh_info->es_rb_tree, &tmp);
1765 }
1766
1767 /* A new local es is created when a local-es-id and sysmac is configured
1768 * against an interface.
1769 */
1770 static struct zebra_evpn_es *zebra_evpn_es_new(const esi_t *esi)
1771 {
1772 struct zebra_evpn_es *es;
1773
1774 if (!memcmp(esi, zero_esi, sizeof(esi_t)))
1775 return NULL;
1776
1777 es = XCALLOC(MTYPE_ZES, sizeof(struct zebra_evpn_es));
1778
1779 /* fill in ESI */
1780 memcpy(&es->esi, esi, sizeof(esi_t));
1781 esi_to_str(&es->esi, es->esi_str, sizeof(es->esi_str));
1782
1783 /* Add to rb_tree */
1784 RB_INSERT(zebra_es_rb_head, &zmh_info->es_rb_tree, es);
1785
1786 /* Initialise the ES-EVI list */
1787 es->es_evi_list = list_new();
1788 listset_app_node_mem(es->es_evi_list);
1789
1790 /* Initialise the VTEP list */
1791 es->es_vtep_list = list_new();
1792 listset_app_node_mem(es->es_vtep_list);
1793 es->es_vtep_list->cmp = zebra_evpn_es_vtep_cmp;
1794
1795 /* mac entries associated with the ES */
1796 es->mac_list = list_new();
1797 listset_app_node_mem(es->mac_list);
1798
1799 /* reserve a NHG */
1800 es->nhg_id = zebra_evpn_nhid_alloc(es);
1801
1802 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1803 zlog_debug("es %s nhg %u new", es->esi_str, es->nhg_id);
1804
1805 return es;
1806 }
1807
1808 /* Free a given ES -
1809 * This just frees appropriate memory, caller should have taken other
1810 * needed actions.
1811 */
1812 static void zebra_evpn_es_free(struct zebra_evpn_es **esp)
1813 {
1814 struct zebra_evpn_es *es = *esp;
1815
1816 /* If the ES has a local or remote reference it cannot be freed.
1817 * Free is also prevented if there are MAC entries referencing
1818 * it.
1819 */
1820 if ((es->flags & (ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_REMOTE)) ||
1821 listcount(es->mac_list))
1822 return;
1823
1824 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1825 zlog_debug("es %s free", es->esi_str);
1826
1827 /* If the NHG is still installed uninstall it and free the id */
1828 if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) {
1829 es->flags &= ~ZEBRA_EVPNES_NHG_ACTIVE;
1830 kernel_del_mac_nhg(es->nhg_id);
1831 }
1832 zebra_evpn_nhid_free(es->nhg_id, es);
1833
1834 /* cleanup resources maintained against the ES */
1835 list_delete(&es->es_evi_list);
1836 list_delete(&es->es_vtep_list);
1837 list_delete(&es->mac_list);
1838
1839 /* remove from the VNI-ESI rb tree */
1840 RB_REMOVE(zebra_es_rb_head, &zmh_info->es_rb_tree, es);
1841
1842 XFREE(MTYPE_ZES, es);
1843
1844 *esp = NULL;
1845 }
1846
1847 /* Inform BGP about local ES addition */
1848 static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
1849 {
1850 struct zserv *client;
1851 struct stream *s;
1852 uint8_t oper_up;
1853 bool bypass;
1854
1855 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1856 /* BGP may not be running. */
1857 if (!client)
1858 return 0;
1859
1860 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1861
1862 zclient_create_header(s, ZEBRA_LOCAL_ES_ADD, zebra_vrf_get_evpn_id());
1863 stream_put(s, &es->esi, sizeof(esi_t));
1864 stream_put_ipv4(s, zmh_info->es_originator_ip.s_addr);
1865 oper_up = !!(es->flags & ZEBRA_EVPNES_OPER_UP);
1866 stream_putc(s, oper_up);
1867 stream_putw(s, es->df_pref);
1868 bypass = !!(es->flags & ZEBRA_EVPNES_BYPASS);
1869 stream_putc(s, bypass);
1870
1871 /* Write packet size. */
1872 stream_putw_at(s, 0, stream_get_endp(s));
1873
1874 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1875 zlog_debug(
1876 "send add local es %s %pI4 active %u df_pref %u%s to %s",
1877 es->esi_str, &zmh_info->es_originator_ip, oper_up,
1878 es->df_pref, bypass ? " bypass" : "",
1879 zebra_route_string(client->proto));
1880
1881 client->local_es_add_cnt++;
1882 return zserv_send_message(client, s);
1883 }
1884
1885 /* Inform BGP about local ES deletion */
1886 static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es)
1887 {
1888 struct zserv *client;
1889 struct stream *s;
1890
1891 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1892 /* BGP may not be running. */
1893 if (!client)
1894 return 0;
1895
1896 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1897 stream_reset(s);
1898
1899 zclient_create_header(s, ZEBRA_LOCAL_ES_DEL, zebra_vrf_get_evpn_id());
1900 stream_put(s, &es->esi, sizeof(esi_t));
1901
1902 /* Write packet size. */
1903 stream_putw_at(s, 0, stream_get_endp(s));
1904
1905 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
1906 zlog_debug("send del local es %s to %s", es->esi_str,
1907 zebra_route_string(client->proto));
1908
1909 client->local_es_del_cnt++;
1910 return zserv_send_message(client, s);
1911 }
1912
1913 static void zebra_evpn_es_re_eval_send_to_client(struct zebra_evpn_es *es,
1914 bool es_evi_re_reval)
1915 {
1916 bool old_ready;
1917 bool new_ready;
1918 struct listnode *node;
1919 struct zebra_evpn_es_evi *es_evi;
1920
1921 old_ready = !!(es->flags & ZEBRA_EVPNES_READY_FOR_BGP);
1922
1923 if ((es->flags & ZEBRA_EVPNES_LOCAL) &&
1924 zmh_info->es_originator_ip.s_addr)
1925 es->flags |= ZEBRA_EVPNES_READY_FOR_BGP;
1926 else
1927 es->flags &= ~ZEBRA_EVPNES_READY_FOR_BGP;
1928
1929 new_ready = !!(es->flags & ZEBRA_EVPNES_READY_FOR_BGP);
1930 if (old_ready == new_ready)
1931 return;
1932
1933 if (new_ready)
1934 zebra_evpn_es_send_add_to_client(es);
1935 else
1936 zebra_evpn_es_send_del_to_client(es);
1937
1938 /* re-eval associated EVIs */
1939 if (es_evi_re_reval) {
1940 for (ALL_LIST_ELEMENTS_RO(es->es_evi_list, node, es_evi)) {
1941 if (!(es_evi->flags & ZEBRA_EVPNES_EVI_LOCAL))
1942 continue;
1943 zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
1944 }
1945 }
1946 }
1947
1948 void zebra_evpn_es_send_all_to_client(bool add)
1949 {
1950 struct listnode *es_node;
1951 struct listnode *evi_node;
1952 struct zebra_evpn_es *es;
1953 struct zebra_evpn_es_evi *es_evi;
1954
1955 if (!zmh_info)
1956 return;
1957
1958 for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, es_node, es)) {
1959 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP) {
1960 if (add)
1961 zebra_evpn_es_send_add_to_client(es);
1962 for (ALL_LIST_ELEMENTS_RO(es->es_evi_list,
1963 evi_node, es_evi)) {
1964 if (!(es_evi->flags &
1965 ZEBRA_EVPNES_EVI_READY_FOR_BGP))
1966 continue;
1967
1968 if (add)
1969 zebra_evpn_es_evi_send_to_client(
1970 es, es_evi->zevpn,
1971 true /* add */);
1972 else
1973 zebra_evpn_es_evi_send_to_client(
1974 es, es_evi->zevpn,
1975 false /* add */);
1976 }
1977 if (!add)
1978 zebra_evpn_es_send_del_to_client(es);
1979 }
1980 }
1981 }
1982
1983 /* walk the vlan bitmap associated with the zif and create or delete
1984 * es_evis for all vlans associated with a VNI.
1985 * XXX: This API is really expensive. optimize later if possible.
1986 */
1987 static void zebra_evpn_es_setup_evis(struct zebra_evpn_es *es)
1988 {
1989 struct zebra_if *zif = es->zif;
1990 uint16_t vid;
1991 struct zebra_evpn_access_bd *acc_bd;
1992
1993 if (!bf_is_inited(zif->vlan_bitmap))
1994 return;
1995
1996 bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) {
1997 acc_bd = zebra_evpn_acc_vl_find(vid);
1998 if (acc_bd->zevpn)
1999 zebra_evpn_local_es_evi_add(es, acc_bd->zevpn);
2000 }
2001 }
2002
2003 static void zebra_evpn_flush_local_mac(struct zebra_mac *mac,
2004 struct interface *ifp)
2005 {
2006 vlanid_t vid;
2007 struct zebra_if *zif;
2008 struct interface *br_ifp;
2009 struct zebra_vxlan_vni *vni;
2010
2011 zif = ifp->info;
2012 br_ifp = zif->brslave_info.br_if;
2013 if (!br_ifp)
2014 return;
2015
2016 if (mac->zevpn->vxlan_if) {
2017 zif = mac->zevpn->vxlan_if->info;
2018 vni = zebra_vxlan_if_vni_find(zif, mac->zevpn->vni);
2019 vid = vni->access_vlan;
2020 } else {
2021 vid = 0;
2022 }
2023
2024 /* delete the local mac from the dataplane */
2025 dplane_local_mac_del(ifp, br_ifp, vid, &mac->macaddr);
2026 /* delete the local mac in zebra */
2027 zebra_evpn_del_local_mac(mac->zevpn, mac, true);
2028 }
2029
2030 static void zebra_evpn_es_flush_local_macs(struct zebra_evpn_es *es,
2031 struct interface *ifp, bool add)
2032 {
2033 struct zebra_mac *mac;
2034 struct listnode *node;
2035 struct listnode *nnode;
2036
2037 for (ALL_LIST_ELEMENTS(es->mac_list, node, nnode, mac)) {
2038 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
2039 continue;
2040
2041 /* If ES is being attached/detached from the access port we
2042 * need to clear local activity and peer activity and start
2043 * over */
2044 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2045 zlog_debug("VNI %u mac %pEA update; local ES %s %s",
2046 mac->zevpn->vni,
2047 &mac->macaddr,
2048 es->esi_str, add ? "add" : "del");
2049 zebra_evpn_flush_local_mac(mac, ifp);
2050 }
2051 }
2052
2053 void zebra_evpn_es_local_br_port_update(struct zebra_if *zif)
2054 {
2055 struct zebra_evpn_es *es = zif->es_info.es;
2056 bool old_br_port = !!(es->flags & ZEBRA_EVPNES_BR_PORT);
2057 bool new_br_port;
2058
2059 if (zif->brslave_info.bridge_ifindex != IFINDEX_INTERNAL)
2060 es->flags |= ZEBRA_EVPNES_BR_PORT;
2061 else
2062 es->flags &= ~ZEBRA_EVPNES_BR_PORT;
2063
2064 new_br_port = !!(es->flags & ZEBRA_EVPNES_BR_PORT);
2065 if (old_br_port == new_br_port)
2066 return;
2067
2068 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2069 zlog_debug("es %s br_port change old %u new %u", es->esi_str,
2070 old_br_port, new_br_port);
2071
2072 /* update the dataplane br_port attrs */
2073 if (new_br_port && zebra_evpn_es_br_port_dplane_update_needed(es))
2074 zebra_evpn_es_br_port_dplane_update(es, __func__);
2075 }
2076
2077 /* On config of first local-ES turn off DAD */
2078 static void zebra_evpn_mh_dup_addr_detect_off(void)
2079 {
2080 struct zebra_vrf *zvrf;
2081 bool old_detect;
2082 bool new_detect;
2083
2084 if (zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF)
2085 return;
2086
2087 zvrf = zebra_vrf_get_evpn();
2088 old_detect = zebra_evpn_do_dup_addr_detect(zvrf);
2089 zmh_info->flags |= ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF;
2090 new_detect = zebra_evpn_do_dup_addr_detect(zvrf);
2091
2092 if (old_detect && !new_detect) {
2093 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2094 zlog_debug(
2095 "evpn-mh config caused DAD addr detect chg from %s to %s",
2096 old_detect ? "on" : "off",
2097 new_detect ? "on" : "off");
2098 zebra_vxlan_clear_dup_detect_vni_all(zvrf);
2099 }
2100 }
2101
2102 /* On config of first local-ES turn off advertisement of STALE/DELAY/PROBE
2103 * neighbors
2104 */
2105 static void zebra_evpn_mh_advertise_reach_neigh_only(void)
2106 {
2107 if (zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY)
2108 return;
2109
2110 zmh_info->flags |= ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY;
2111 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2112 zlog_debug("evpn-mh: only REACHABLE neigh advertised");
2113
2114 /* XXX - if STALE/DELAY/PROBE neighs were previously advertised we
2115 * need to withdraw them
2116 */
2117 }
2118
2119 /* On config of first local-ES turn on advertisement of local SVI-MAC */
2120 static void zebra_evpn_mh_advertise_svi_mac(void)
2121 {
2122 if (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC)
2123 return;
2124
2125 zmh_info->flags |= ZEBRA_EVPN_MH_ADV_SVI_MAC;
2126 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2127 zlog_debug("evpn-mh: advertise SVI MAC");
2128
2129 /* walk through all SVIs and see if we need to advertise the MAC */
2130 zebra_evpn_acc_vl_adv_svi_mac_all();
2131 }
2132
2133 static void zebra_evpn_es_df_delay_exp_cb(struct thread *t)
2134 {
2135 struct zebra_evpn_es *es;
2136
2137 es = THREAD_ARG(t);
2138
2139 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2140 zlog_debug("es %s df-delay expired", es->esi_str);
2141
2142 zebra_evpn_es_run_df_election(es, __func__);
2143 }
2144
2145 /* currently there is no global config to turn on MH instead we use
2146 * the addition of the first local Ethernet Segment as the trigger to
2147 * init MH specific processing
2148 */
2149 static void zebra_evpn_mh_on_first_local_es(void)
2150 {
2151 zebra_evpn_mh_dup_addr_detect_off();
2152 zebra_evpn_mh_advertise_reach_neigh_only();
2153 zebra_evpn_mh_advertise_svi_mac();
2154 }
2155
2156 static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
2157 struct zebra_if *zif)
2158 {
2159 if (es->flags & ZEBRA_EVPNES_LOCAL)
2160 return;
2161
2162 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2163 zlog_debug("local es %s add; nhg %u if %s", es->esi_str,
2164 es->nhg_id, zif->ifp->name);
2165
2166 zebra_evpn_mh_on_first_local_es();
2167
2168 es->flags |= ZEBRA_EVPNES_LOCAL;
2169 listnode_init(&es->local_es_listnode, es);
2170 listnode_add(zmh_info->local_es_list, &es->local_es_listnode);
2171
2172 /* attach es to interface */
2173 zif->es_info.es = es;
2174 es->df_pref = zif->es_info.df_pref ? zif->es_info.df_pref
2175 : EVPN_MH_DF_PREF_DEFAULT;
2176
2177 /* attach interface to es */
2178 es->zif = zif;
2179 if (if_is_operative(zif->ifp))
2180 es->flags |= ZEBRA_EVPNES_OPER_UP;
2181
2182 if (zif->brslave_info.bridge_ifindex != IFINDEX_INTERNAL)
2183 es->flags |= ZEBRA_EVPNES_BR_PORT;
2184
2185 /* inherit the bypass flag from the interface */
2186 if (zif->flags & ZIF_FLAG_LACP_BYPASS)
2187 es->flags |= ZEBRA_EVPNES_BYPASS;
2188
2189 /* setup base-vni if one doesn't already exist; the ES will get sent
2190 * to BGP as a part of that process
2191 */
2192 if (!zmh_info->es_base_evpn)
2193 zebra_evpn_es_get_one_base_evpn();
2194 else
2195 /* send notification to bgp */
2196 zebra_evpn_es_re_eval_send_to_client(es,
2197 false /* es_evi_re_reval */);
2198
2199 /* Start the DF delay timer on the local ES */
2200 if (!es->df_delay_timer)
2201 thread_add_timer(zrouter.master, zebra_evpn_es_df_delay_exp_cb,
2202 es, ZEBRA_EVPN_MH_DF_DELAY_TIME,
2203 &es->df_delay_timer);
2204
2205 /* See if the local VTEP can function as DF on the ES */
2206 if (!zebra_evpn_es_run_df_election(es, __func__)) {
2207 /* check if the dplane entry needs to be re-programmed as a
2208 * result of some thing other than DF status change
2209 */
2210 if (zebra_evpn_es_br_port_dplane_update_needed(es))
2211 zebra_evpn_es_br_port_dplane_update(es, __func__);
2212 }
2213
2214
2215 /* Setup ES-EVIs for all VxLAN stretched VLANs associated with
2216 * the zif
2217 */
2218 zebra_evpn_es_setup_evis(es);
2219 /* if there any local macs referring to the ES as dest we
2220 * need to clear the contents and start over
2221 */
2222 zebra_evpn_es_flush_local_macs(es, zif->ifp, true);
2223
2224 /* inherit EVPN protodown flags on the access port */
2225 zebra_evpn_mh_update_protodown_es(es, true /*resync_dplane*/);
2226 }
2227
2228 static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp)
2229 {
2230 struct zebra_if *zif;
2231 struct zebra_evpn_es *es = *esp;
2232 bool dplane_updated = false;
2233
2234 if (!(es->flags & ZEBRA_EVPNES_LOCAL))
2235 return;
2236
2237 zif = es->zif;
2238
2239 /* if there any local macs referring to the ES as dest we
2240 * need to clear the contents and start over
2241 */
2242 zebra_evpn_es_flush_local_macs(es, zif->ifp, false);
2243
2244 es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP);
2245
2246 THREAD_OFF(es->df_delay_timer);
2247
2248 /* clear EVPN protodown flags on the access port */
2249 zebra_evpn_mh_clear_protodown_es(es);
2250
2251 /* remove the DF filter */
2252 dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
2253
2254 /* flush the BUM filters and backup NHG */
2255 if (!dplane_updated)
2256 zebra_evpn_es_br_port_dplane_clear(es);
2257
2258 /* clear the es from the parent interface */
2259 zif->es_info.es = NULL;
2260 es->zif = NULL;
2261
2262 /* clear all local flags associated with the ES */
2263 es->flags &= ~(ZEBRA_EVPNES_OPER_UP | ZEBRA_EVPNES_BR_PORT
2264 | ZEBRA_EVPNES_BYPASS);
2265
2266 /* remove from the ES list */
2267 list_delete_node(zmh_info->local_es_list, &es->local_es_listnode);
2268
2269 /* free up the ES if there is no remote reference */
2270 zebra_evpn_es_free(esp);
2271 }
2272
2273 /* Delete an ethernet segment and inform BGP */
2274 static void zebra_evpn_local_es_del(struct zebra_evpn_es **esp)
2275 {
2276 struct zebra_evpn_es_evi *es_evi;
2277 struct listnode *node = NULL;
2278 struct listnode *nnode = NULL;
2279 struct zebra_if *zif;
2280 struct zebra_evpn_es *es = *esp;
2281
2282 if (!CHECK_FLAG(es->flags, ZEBRA_EVPNES_LOCAL))
2283 return;
2284
2285 if (IS_ZEBRA_DEBUG_EVPN_MH_ES) {
2286 zif = es->zif;
2287 zlog_debug("local es %s del; nhg %u if %s", es->esi_str,
2288 es->nhg_id, zif ? zif->ifp->name : "-");
2289 }
2290
2291 /* remove all ES-EVIs associated with the ES */
2292 for (ALL_LIST_ELEMENTS(es->es_evi_list, node, nnode, es_evi))
2293 zebra_evpn_local_es_evi_do_del(es_evi);
2294
2295 /* send a del if the ES had been sent to BGP earlier */
2296 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
2297 zebra_evpn_es_send_del_to_client(es);
2298
2299 zebra_evpn_es_local_info_clear(esp);
2300 }
2301
2302 /* eval remote info associated with the ES */
2303 static void zebra_evpn_es_remote_info_re_eval(struct zebra_evpn_es **esp)
2304 {
2305 struct zebra_evpn_es *es = *esp;
2306
2307 /* if there are remote VTEPs the ES-EVI is classified as "remote" */
2308 if (listcount(es->es_vtep_list)) {
2309 if (!(es->flags & ZEBRA_EVPNES_REMOTE)) {
2310 es->flags |= ZEBRA_EVPNES_REMOTE;
2311 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2312 zlog_debug("remote es %s add; nhg %u",
2313 es->esi_str, es->nhg_id);
2314 }
2315 } else {
2316 if (es->flags & ZEBRA_EVPNES_REMOTE) {
2317 es->flags &= ~ZEBRA_EVPNES_REMOTE;
2318 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2319 zlog_debug("remote es %s del; nhg %u",
2320 es->esi_str, es->nhg_id);
2321 zebra_evpn_es_free(esp);
2322 }
2323 }
2324 }
2325
2326 /* A new local es is created when a local-es-id and sysmac is configured
2327 * against an interface.
2328 */
2329 static int zebra_evpn_local_es_update(struct zebra_if *zif, esi_t *esi)
2330 {
2331 struct zebra_evpn_es *old_es = zif->es_info.es;
2332 struct zebra_evpn_es *es;
2333
2334 if (old_es && !memcmp(&old_es->esi, esi, sizeof(*esi)))
2335 /* dup - nothing to be done */
2336 return 0;
2337
2338 /* release the old_es against the zif */
2339 if (old_es)
2340 zebra_evpn_local_es_del(&old_es);
2341
2342 es = zebra_evpn_es_find(esi);
2343 if (es) {
2344 /* if it exists against another interface flag an error */
2345 if (es->zif && es->zif != zif)
2346 return -1;
2347 } else {
2348 /* create new es */
2349 es = zebra_evpn_es_new(esi);
2350 }
2351
2352 memcpy(&zif->es_info.esi, esi, sizeof(*esi));
2353 if (es)
2354 zebra_evpn_es_local_info_set(es, zif);
2355
2356 return 0;
2357 }
2358
2359 static int zebra_evpn_type3_esi_update(struct zebra_if *zif, uint32_t lid,
2360 struct ethaddr *sysmac)
2361 {
2362 struct zebra_evpn_es *old_es = zif->es_info.es;
2363 esi_t esi;
2364 int offset = 0;
2365 int field_bytes = 0;
2366
2367 /* Complete config of the ES-ID bootstraps the ES */
2368 if (!lid || is_zero_mac(sysmac)) {
2369 /* clear old esi */
2370 memset(&zif->es_info.esi, 0, sizeof(zif->es_info.esi));
2371 /* if in ES is attached to zif delete it */
2372 if (old_es)
2373 zebra_evpn_local_es_del(&old_es);
2374 return 0;
2375 }
2376
2377 /* build 10-byte type-3-ESI -
2378 * Type(1-byte), MAC(6-bytes), ES-LID (3-bytes)
2379 */
2380 field_bytes = 1;
2381 esi.val[offset] = ESI_TYPE_MAC;
2382 offset += field_bytes;
2383
2384 field_bytes = ETH_ALEN;
2385 memcpy(&esi.val[offset], (uint8_t *)sysmac, field_bytes);
2386 offset += field_bytes;
2387
2388 esi.val[offset++] = (uint8_t)(lid >> 16);
2389 esi.val[offset++] = (uint8_t)(lid >> 8);
2390 esi.val[offset++] = (uint8_t)lid;
2391
2392 return zebra_evpn_local_es_update(zif, &esi);
2393 }
2394
2395 int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip)
2396 {
2397 char buf[ESI_STR_LEN];
2398 struct zebra_evpn_es *es;
2399
2400 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2401 zlog_debug("remote es %s vtep %pI4 del",
2402 esi_to_str(esi, buf, sizeof(buf)), &vtep_ip);
2403
2404 es = zebra_evpn_es_find(esi);
2405 if (!es) {
2406 zlog_warn("remote es %s vtep %pI4 del failed, es missing",
2407 esi_to_str(esi, buf, sizeof(buf)), &vtep_ip);
2408 return -1;
2409 }
2410
2411 zebra_evpn_es_vtep_del(es, vtep_ip);
2412 zebra_evpn_es_remote_info_re_eval(&es);
2413
2414 return 0;
2415 }
2416
2417 /* force delete a remote ES on the way down */
2418 static void zebra_evpn_remote_es_flush(struct zebra_evpn_es **esp)
2419 {
2420 struct zebra_evpn_es_vtep *es_vtep;
2421 struct listnode *node;
2422 struct listnode *nnode;
2423 struct zebra_evpn_es *es = *esp;
2424
2425 for (ALL_LIST_ELEMENTS(es->es_vtep_list, node, nnode, es_vtep)) {
2426 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2427 zlog_debug("es %s vtep %pI4 flush",
2428 es->esi_str,
2429 &es_vtep->vtep_ip);
2430 zebra_evpn_es_vtep_free(es_vtep);
2431 }
2432 zebra_evpn_es_remote_info_re_eval(esp);
2433 }
2434
2435 int zebra_evpn_remote_es_add(const esi_t *esi, struct in_addr vtep_ip,
2436 bool esr_rxed, uint8_t df_alg, uint16_t df_pref)
2437 {
2438 char buf[ESI_STR_LEN];
2439 struct zebra_evpn_es *es;
2440
2441 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2442 zlog_debug("remote es %s vtep %pI4 add %s df_alg %d df_pref %d",
2443 esi_to_str(esi, buf, sizeof(buf)),
2444 &vtep_ip, esr_rxed ? "esr" : "", df_alg,
2445 df_pref);
2446
2447 es = zebra_evpn_es_find(esi);
2448 if (!es) {
2449 es = zebra_evpn_es_new(esi);
2450 if (!es) {
2451 zlog_warn(
2452 "remote es %s vtep %pI4 add failed, es missing",
2453 esi_to_str(esi, buf, sizeof(buf)), &vtep_ip);
2454 return -1;
2455 }
2456 }
2457
2458 if (df_alg != EVPN_MH_DF_ALG_PREF)
2459 zlog_warn(
2460 "remote es %s vtep %pI4 add %s with unsupported df_alg %d",
2461 esi_to_str(esi, buf, sizeof(buf)), &vtep_ip,
2462 esr_rxed ? "esr" : "", df_alg);
2463
2464 zebra_evpn_es_vtep_add(es, vtep_ip, esr_rxed, df_alg, df_pref);
2465 zebra_evpn_es_remote_info_re_eval(&es);
2466
2467 return 0;
2468 }
2469
2470 void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS)
2471 {
2472 struct stream *s;
2473 struct in_addr vtep_ip;
2474 esi_t esi;
2475
2476 if (!is_evpn_enabled()) {
2477 zlog_debug(
2478 "%s: EVPN not enabled yet we received a es_add zapi call",
2479 __func__);
2480 return;
2481 }
2482
2483 memset(&esi, 0, sizeof(esi_t));
2484 s = msg;
2485
2486 STREAM_GET(&esi, s, sizeof(esi_t));
2487 STREAM_GET(&vtep_ip.s_addr, s, sizeof(vtep_ip.s_addr));
2488
2489 if (hdr->command == ZEBRA_REMOTE_ES_VTEP_ADD) {
2490 uint32_t zapi_flags;
2491 uint8_t df_alg;
2492 uint16_t df_pref;
2493 bool esr_rxed;
2494
2495 STREAM_GETL(s, zapi_flags);
2496 esr_rxed = (zapi_flags & ZAPI_ES_VTEP_FLAG_ESR_RXED) ? true
2497 : false;
2498 STREAM_GETC(s, df_alg);
2499 STREAM_GETW(s, df_pref);
2500 zebra_rib_queue_evpn_rem_es_add(&esi, &vtep_ip, esr_rxed,
2501 df_alg, df_pref);
2502 } else {
2503 zebra_rib_queue_evpn_rem_es_del(&esi, &vtep_ip);
2504 }
2505
2506 stream_failure:
2507 return;
2508 }
2509
2510 void zebra_evpn_es_mac_deref_entry(struct zebra_mac *mac)
2511 {
2512 struct zebra_evpn_es *es = mac->es;
2513
2514 mac->es = NULL;
2515 if (!es)
2516 return;
2517
2518 list_delete_node(es->mac_list, &mac->es_listnode);
2519 if (!listcount(es->mac_list))
2520 zebra_evpn_es_free(&es);
2521 }
2522
2523 /* Associate a MAC entry with a local or remote ES. Returns false if there
2524 * was no ES change.
2525 */
2526 bool zebra_evpn_es_mac_ref_entry(struct zebra_mac *mac,
2527 struct zebra_evpn_es *es)
2528 {
2529 if (mac->es == es)
2530 return false;
2531
2532 if (mac->es)
2533 zebra_evpn_es_mac_deref_entry(mac);
2534
2535 if (!es)
2536 return true;
2537
2538 mac->es = es;
2539 listnode_init(&mac->es_listnode, mac);
2540 listnode_add(es->mac_list, &mac->es_listnode);
2541
2542 return true;
2543 }
2544
2545 bool zebra_evpn_es_mac_ref(struct zebra_mac *mac, const esi_t *esi)
2546 {
2547 struct zebra_evpn_es *es;
2548
2549 es = zebra_evpn_es_find(esi);
2550 if (!es) {
2551 /* If non-zero esi implicitly create a new ES */
2552 if (memcmp(esi, zero_esi, sizeof(esi_t))) {
2553 es = zebra_evpn_es_new(esi);
2554 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2555 zlog_debug("auto es %s add on mac ref",
2556 es->esi_str);
2557 }
2558 }
2559
2560 return zebra_evpn_es_mac_ref_entry(mac, es);
2561 }
2562
2563 /* Inform BGP about local ES-EVI add or del */
2564 static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
2565 struct zebra_evpn *zevpn, bool add)
2566 {
2567 struct zserv *client;
2568 struct stream *s;
2569
2570 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
2571 /* BGP may not be running. */
2572 if (!client)
2573 return 0;
2574
2575 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2576
2577 zclient_create_header(s,
2578 add ? ZEBRA_LOCAL_ES_EVI_ADD : ZEBRA_LOCAL_ES_EVI_DEL,
2579 zebra_vrf_get_evpn_id());
2580 stream_put(s, &es->esi, sizeof(esi_t));
2581 stream_putl(s, zevpn->vni);
2582
2583 /* Write packet size. */
2584 stream_putw_at(s, 0, stream_get_endp(s));
2585
2586 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2587 zlog_debug("send %s local es %s evi %u to %s",
2588 add ? "add" : "del",
2589 es->esi_str, zevpn->vni,
2590 zebra_route_string(client->proto));
2591
2592 client->local_es_add_cnt++;
2593 return zserv_send_message(client, s);
2594 }
2595
2596 /* sysmac part of a local ESI has changed */
2597 static int zebra_evpn_es_sys_mac_update(struct zebra_if *zif,
2598 struct ethaddr *sysmac)
2599 {
2600 int rv;
2601
2602 rv = zebra_evpn_type3_esi_update(zif, zif->es_info.lid, sysmac);
2603 if (!rv)
2604 memcpy(&zif->es_info.sysmac, sysmac, sizeof(struct ethaddr));
2605
2606 return rv;
2607 }
2608
2609 /* local-ID part of ESI has changed */
2610 static int zebra_evpn_es_lid_update(struct zebra_if *zif, uint32_t lid)
2611 {
2612 int rv;
2613
2614 rv = zebra_evpn_type3_esi_update(zif, lid, &zif->es_info.sysmac);
2615 if (!rv)
2616 zif->es_info.lid = lid;
2617
2618 return rv;
2619 }
2620
2621 /* type-0 esi has changed */
2622 static int zebra_evpn_es_type0_esi_update(struct zebra_if *zif, esi_t *esi)
2623 {
2624 int rv;
2625
2626 rv = zebra_evpn_local_es_update(zif, esi);
2627
2628 /* clear the old es_lid, es_sysmac - type-0 is being set so old
2629 * type-3 params need to be flushed
2630 */
2631 memset(&zif->es_info.sysmac, 0, sizeof(struct ethaddr));
2632 zif->es_info.lid = 0;
2633
2634 return rv;
2635 }
2636
2637 void zebra_evpn_es_cleanup(void)
2638 {
2639 struct zebra_evpn_es *es;
2640 struct zebra_evpn_es *es_next;
2641
2642 RB_FOREACH_SAFE(es, zebra_es_rb_head,
2643 &zmh_info->es_rb_tree, es_next) {
2644 zebra_evpn_local_es_del(&es);
2645 if (es)
2646 zebra_evpn_remote_es_flush(&es);
2647 }
2648 }
2649
2650 static void zebra_evpn_es_df_pref_update(struct zebra_if *zif, uint16_t df_pref)
2651 {
2652 struct zebra_evpn_es *es;
2653 uint16_t tmp_pref;
2654
2655 if (zif->es_info.df_pref == df_pref)
2656 return;
2657
2658 zif->es_info.df_pref = df_pref;
2659 es = zif->es_info.es;
2660
2661 if (!es)
2662 return;
2663
2664 tmp_pref = zif->es_info.df_pref ? zif->es_info.df_pref
2665 : EVPN_MH_DF_PREF_DEFAULT;
2666
2667 if (es->df_pref == tmp_pref)
2668 return;
2669
2670 es->df_pref = tmp_pref;
2671 /* run df election */
2672 zebra_evpn_es_run_df_election(es, __func__);
2673 /* notify bgp */
2674 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
2675 zebra_evpn_es_send_add_to_client(es);
2676 }
2677
2678 /* If bypass mode on an es changed we set all local macs to
2679 * inactive and drop the sync info
2680 */
2681 static void zebra_evpn_es_bypass_update_macs(struct zebra_evpn_es *es,
2682 struct interface *ifp, bool bypass)
2683 {
2684 struct zebra_mac *mac;
2685 struct listnode *node;
2686 struct listnode *nnode;
2687 struct zebra_if *zif;
2688
2689 /* Flush all MACs linked to the ES */
2690 for (ALL_LIST_ELEMENTS(es->mac_list, node, nnode, mac)) {
2691 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
2692 continue;
2693
2694 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2695 zlog_debug("VNI %u mac %pEA %s update es %s",
2696 mac->zevpn->vni,
2697 &mac->macaddr,
2698 bypass ? "bypass" : "non-bypass",
2699 es->esi_str);
2700 zebra_evpn_flush_local_mac(mac, ifp);
2701 }
2702
2703 /* While in bypass-mode locally learnt MACs are linked
2704 * to the access port instead of the ES
2705 */
2706 zif = ifp->info;
2707 if (!zif->mac_list)
2708 return;
2709
2710 for (ALL_LIST_ELEMENTS(zif->mac_list, node, nnode, mac)) {
2711 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
2712 continue;
2713
2714 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2715 zlog_debug("VNI %u mac %pEA %s update ifp %s",
2716 mac->zevpn->vni,
2717 &mac->macaddr,
2718 bypass ? "bypass" : "non-bypass", ifp->name);
2719 zebra_evpn_flush_local_mac(mac, ifp);
2720 }
2721 }
2722
2723 void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
2724 struct interface *ifp, bool bypass)
2725 {
2726 bool old_bypass;
2727 bool dplane_updated;
2728
2729 old_bypass = !!(es->flags & ZEBRA_EVPNES_BYPASS);
2730 if (old_bypass == bypass)
2731 return;
2732
2733 if (bypass)
2734 es->flags |= ZEBRA_EVPNES_BYPASS;
2735 else
2736 es->flags &= ~ZEBRA_EVPNES_BYPASS;
2737
2738 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2739 zlog_debug("bond %s es %s lacp bypass changed to %s", ifp->name,
2740 es->esi_str, bypass ? "on" : "off");
2741
2742 /* send bypass update to BGP */
2743 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
2744 zebra_evpn_es_send_add_to_client(es);
2745
2746 zebra_evpn_es_bypass_update_macs(es, ifp, bypass);
2747
2748 /* re-run DF election */
2749 dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
2750
2751 /* disable SPH filter */
2752 if (!dplane_updated && (es->flags & ZEBRA_EVPNES_LOCAL)
2753 && (listcount(es->es_vtep_list) > ES_VTEP_MAX_CNT))
2754 zebra_evpn_es_br_port_dplane_update(es, __func__);
2755 }
2756
2757 static void zebra_evpn_es_bypass_cfg_update(struct zebra_if *zif, bool bypass)
2758 {
2759 bool old_bypass = !!(zif->es_info.flags & ZIF_CFG_ES_FLAG_BYPASS);
2760
2761 if (old_bypass == bypass)
2762 return;
2763
2764 if (bypass)
2765 zif->es_info.flags |= ZIF_CFG_ES_FLAG_BYPASS;
2766 else
2767 zif->es_info.flags &= ~ZIF_CFG_ES_FLAG_BYPASS;
2768
2769
2770 if (zif->es_info.es)
2771 zebra_evpn_es_bypass_update(zif->es_info.es, zif->ifp, bypass);
2772 }
2773
2774
2775 /* Only certain types of access ports can be setup as an Ethernet Segment */
2776 bool zebra_evpn_is_if_es_capable(struct zebra_if *zif)
2777 {
2778 if (zif->zif_type == ZEBRA_IF_BOND)
2779 return true;
2780
2781 /* relax the checks to allow config to be applied in zebra
2782 * before interface is rxed from the kernel
2783 */
2784 if (zif->ifp->ifindex == IFINDEX_INTERNAL)
2785 return true;
2786
2787 /* XXX: allow swpX i.e. a regular ethernet port to be an ES link too */
2788 return false;
2789 }
2790
2791 void zebra_evpn_if_es_print(struct vty *vty, json_object *json,
2792 struct zebra_if *zif)
2793 {
2794 char buf[ETHER_ADDR_STRLEN];
2795 char esi_buf[ESI_STR_LEN];
2796
2797 if (json) {
2798 json_object *json_evpn;
2799
2800 json_evpn = json_object_new_object();
2801 json_object_object_add(json, "evpnMh", json_evpn);
2802
2803 if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac)) {
2804 json_object_int_add(json_evpn, "esId",
2805 zif->es_info.lid);
2806 json_object_string_add(
2807 json_evpn, "esSysmac",
2808 prefix_mac2str(&zif->es_info.sysmac, buf,
2809 sizeof(buf)));
2810 } else if (memcmp(&zif->es_info.esi, zero_esi,
2811 sizeof(*zero_esi))) {
2812 json_object_string_add(json_evpn, "esId",
2813 esi_to_str(&zif->es_info.esi,
2814 esi_buf,
2815 sizeof(esi_buf)));
2816 }
2817
2818 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
2819 json_object_string_add(
2820 json_evpn, "uplink",
2821 CHECK_FLAG(zif->flags,
2822 ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP)
2823 ? "up"
2824 : "down");
2825 } else {
2826 char mh_buf[80];
2827 bool vty_print = false;
2828
2829 mh_buf[0] = '\0';
2830 strlcat(mh_buf, " EVPN-MH:", sizeof(mh_buf));
2831 if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac)) {
2832 vty_print = true;
2833 snprintf(mh_buf + strlen(mh_buf),
2834 sizeof(mh_buf) - strlen(mh_buf),
2835 " ES id %u ES sysmac %s", zif->es_info.lid,
2836 prefix_mac2str(&zif->es_info.sysmac, buf,
2837 sizeof(buf)));
2838 } else if (memcmp(&zif->es_info.esi, zero_esi,
2839 sizeof(*zero_esi))) {
2840 vty_print = true;
2841 snprintf(mh_buf + strnlen(mh_buf, sizeof(mh_buf)),
2842 sizeof(mh_buf)
2843 - strnlen(mh_buf, sizeof(mh_buf)),
2844 " ES id %s",
2845 esi_to_str(&zif->es_info.esi, esi_buf,
2846 sizeof(esi_buf)));
2847 }
2848
2849 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) {
2850 vty_print = true;
2851 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP)
2852 strlcat(mh_buf, " uplink (up)", sizeof(mh_buf));
2853 else
2854 strlcat(mh_buf, " uplink (down)",
2855 sizeof(mh_buf));
2856 }
2857
2858 if (vty_print)
2859 vty_out(vty, "%s\n", mh_buf);
2860 }
2861 }
2862
2863 static void zebra_evpn_local_mac_oper_state_change(struct zebra_evpn_es *es)
2864 {
2865 struct zebra_mac *mac;
2866 struct listnode *node;
2867
2868 /* If fast-failover is supported by the dataplane via the use
2869 * of an ES backup NHG there is nothing to be done in the
2870 * control plane
2871 */
2872 if (!(zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF))
2873 return;
2874
2875 if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2876 zlog_debug("mac slow-fail on es %s %s ", es->esi_str,
2877 (es->flags & ZEBRA_EVPNES_OPER_UP) ? "up" : "down");
2878
2879 for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
2880 if (!(mac->flags & ZEBRA_MAC_LOCAL)
2881 || !zebra_evpn_mac_is_static(mac))
2882 continue;
2883
2884 if (es->flags & ZEBRA_EVPNES_OPER_UP) {
2885 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2886 zlog_debug(
2887 "VNI %u mac %pEA move to acc %s es %s %s ",
2888 mac->zevpn->vni,
2889 &mac->macaddr,
2890 es->zif->ifp->name, es->esi_str,
2891 (es->flags & ZEBRA_EVPNES_OPER_UP)
2892 ? "up"
2893 : "down");
2894 /* switch the local macs to access port */
2895 if (zebra_evpn_sync_mac_dp_install(
2896 mac, false /*set_inactive*/,
2897 false /*force_clear_static*/, __func__)
2898 < 0)
2899 /* if the local mac install fails get rid of the
2900 * old rem entry
2901 */
2902 zebra_evpn_rem_mac_uninstall(mac->zevpn, mac,
2903 true /*force*/);
2904 } else {
2905 /* switch the local macs to network port. if there
2906 * is no active NHG we don't bother deleting the MAC;
2907 * that is left up to the dataplane to handle.
2908 */
2909 if (!(es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
2910 continue;
2911 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2912 zlog_debug(
2913 "VNI %u mac %pEA move to nhg %u es %s %s ",
2914 mac->zevpn->vni,
2915 &mac->macaddr,
2916 es->nhg_id, es->esi_str,
2917 (es->flags & ZEBRA_EVPNES_OPER_UP)
2918 ? "up"
2919 : "down");
2920 zebra_evpn_rem_mac_install(mac->zevpn, mac,
2921 true /*was_static*/);
2922 }
2923 }
2924 }
2925
2926 void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up)
2927 {
2928 struct zebra_evpn_es *es = zif->es_info.es;
2929 bool old_up = !!(es->flags & ZEBRA_EVPNES_OPER_UP);
2930
2931 if (old_up == up)
2932 return;
2933
2934 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2935 zlog_debug("es %s state changed to %s ",
2936 es->esi_str,
2937 up ? "up" : "down");
2938 if (up)
2939 es->flags |= ZEBRA_EVPNES_OPER_UP;
2940 else
2941 es->flags &= ~ZEBRA_EVPNES_OPER_UP;
2942
2943 zebra_evpn_es_run_df_election(es, __func__);
2944 zebra_evpn_local_mac_oper_state_change(es);
2945
2946 /* inform BGP of the ES oper state change */
2947 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
2948 zebra_evpn_es_send_add_to_client(es);
2949 }
2950
2951 static char *zebra_evpn_es_vtep_str(char *vtep_str, struct zebra_evpn_es *es,
2952 uint8_t vtep_str_size)
2953 {
2954 struct zebra_evpn_es_vtep *zvtep;
2955 struct listnode *node;
2956 bool first = true;
2957 char ip_buf[INET6_ADDRSTRLEN];
2958
2959 vtep_str[0] = '\0';
2960 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, zvtep)) {
2961 if (first) {
2962 first = false;
2963 strlcat(vtep_str,
2964 inet_ntop(AF_INET, &zvtep->vtep_ip, ip_buf,
2965 sizeof(ip_buf)),
2966 vtep_str_size);
2967 } else {
2968 strlcat(vtep_str, ",", vtep_str_size);
2969 strlcat(vtep_str,
2970 inet_ntop(AF_INET, &zvtep->vtep_ip, ip_buf,
2971 sizeof(ip_buf)),
2972 vtep_str_size);
2973 }
2974 }
2975 return vtep_str;
2976 }
2977
2978 static void zebra_evpn_es_json_vtep_fill(struct zebra_evpn_es *es,
2979 json_object *json_vteps)
2980 {
2981 struct zebra_evpn_es_vtep *es_vtep;
2982 struct listnode *node;
2983 json_object *json_vtep_entry;
2984 char alg_buf[EVPN_DF_ALG_STR_LEN];
2985
2986 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
2987 json_vtep_entry = json_object_new_object();
2988 json_object_string_addf(json_vtep_entry, "vtep", "%pI4",
2989 &es_vtep->vtep_ip);
2990 if (es_vtep->flags & ZEBRA_EVPNES_VTEP_RXED_ESR) {
2991 json_object_string_add(
2992 json_vtep_entry, "dfAlgorithm",
2993 evpn_es_df_alg2str(es_vtep->df_alg, alg_buf,
2994 sizeof(alg_buf)));
2995 json_object_int_add(json_vtep_entry, "dfPreference",
2996 es_vtep->df_pref);
2997 }
2998 if (es_vtep->nh)
2999 json_object_int_add(json_vtep_entry, "nexthopId",
3000 es_vtep->nh->nh_id);
3001 json_object_array_add(json_vteps, json_vtep_entry);
3002 }
3003 }
3004
3005 static void zebra_evpn_es_show_entry(struct vty *vty, struct zebra_evpn_es *es,
3006 json_object *json_array)
3007 {
3008 char type_str[5];
3009 char vtep_str[ES_VTEP_LIST_STR_SZ];
3010
3011 if (json_array) {
3012 json_object *json = NULL;
3013 json_object *json_vteps;
3014 json_object *json_flags;
3015
3016 json = json_object_new_object();
3017 json_object_string_add(json, "esi", es->esi_str);
3018
3019 if (es->flags
3020 & (ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_REMOTE
3021 | ZEBRA_EVPNES_NON_DF)) {
3022 json_flags = json_object_new_array();
3023 if (es->flags & ZEBRA_EVPNES_LOCAL)
3024 json_array_string_add(json_flags, "local");
3025 if (es->flags & ZEBRA_EVPNES_REMOTE)
3026 json_array_string_add(json_flags, "remote");
3027 if (es->flags & ZEBRA_EVPNES_NON_DF)
3028 json_array_string_add(json_flags, "nonDF");
3029 if (es->flags & ZEBRA_EVPNES_BYPASS)
3030 json_array_string_add(json_flags, "bypass");
3031 json_object_object_add(json, "flags", json_flags);
3032 }
3033
3034 if (es->zif)
3035 json_object_string_add(json, "accessPort",
3036 es->zif->ifp->name);
3037
3038 if (listcount(es->es_vtep_list)) {
3039 json_vteps = json_object_new_array();
3040 zebra_evpn_es_json_vtep_fill(es, json_vteps);
3041 json_object_object_add(json, "vteps", json_vteps);
3042 }
3043 json_object_array_add(json_array, json);
3044 } else {
3045 type_str[0] = '\0';
3046 if (es->flags & ZEBRA_EVPNES_LOCAL)
3047 strlcat(type_str, "L", sizeof(type_str));
3048 if (es->flags & ZEBRA_EVPNES_REMOTE)
3049 strlcat(type_str, "R", sizeof(type_str));
3050 if (es->flags & ZEBRA_EVPNES_NON_DF)
3051 strlcat(type_str, "N", sizeof(type_str));
3052 if (es->flags & ZEBRA_EVPNES_BYPASS)
3053 strlcat(type_str, "B", sizeof(type_str));
3054
3055 zebra_evpn_es_vtep_str(vtep_str, es, sizeof(vtep_str));
3056
3057 vty_out(vty, "%-30s %-4s %-21s %s\n",
3058 es->esi_str, type_str,
3059 es->zif ? es->zif->ifp->name : "-",
3060 vtep_str);
3061 }
3062 }
3063
3064 static void zebra_evpn_es_show_entry_detail(struct vty *vty,
3065 struct zebra_evpn_es *es, json_object *json)
3066 {
3067 char type_str[80];
3068 char alg_buf[EVPN_DF_ALG_STR_LEN];
3069 struct zebra_evpn_es_vtep *es_vtep;
3070 struct listnode *node;
3071 char thread_buf[THREAD_TIMER_STRLEN];
3072
3073 if (json) {
3074 json_object *json_vteps;
3075 json_object *json_flags;
3076
3077 json_object_string_add(json, "esi", es->esi_str);
3078 if (es->zif)
3079 json_object_string_add(json, "accessPort",
3080 es->zif->ifp->name);
3081
3082
3083 if (es->flags) {
3084 json_flags = json_object_new_array();
3085 if (es->flags & ZEBRA_EVPNES_LOCAL)
3086 json_array_string_add(json_flags, "local");
3087 if (es->flags & ZEBRA_EVPNES_REMOTE)
3088 json_array_string_add(json_flags, "remote");
3089 if (es->flags & ZEBRA_EVPNES_NON_DF)
3090 json_array_string_add(json_flags, "nonDF");
3091 if (es->flags & ZEBRA_EVPNES_BYPASS)
3092 json_array_string_add(json_flags, "bypass");
3093 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
3094 json_array_string_add(json_flags,
3095 "readyForBgp");
3096 if (es->flags & ZEBRA_EVPNES_BR_PORT)
3097 json_array_string_add(json_flags, "bridgePort");
3098 if (es->flags & ZEBRA_EVPNES_OPER_UP)
3099 json_array_string_add(json_flags, "operUp");
3100 if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE)
3101 json_array_string_add(json_flags,
3102 "nexthopGroupActive");
3103 json_object_object_add(json, "flags", json_flags);
3104 }
3105
3106 json_object_int_add(json, "vniCount",
3107 listcount(es->es_evi_list));
3108 json_object_int_add(json, "macCount", listcount(es->mac_list));
3109 json_object_int_add(json, "dfPreference", es->df_pref);
3110 if (es->df_delay_timer)
3111 json_object_string_add(
3112 json, "dfDelayTimer",
3113 thread_timer_to_hhmmss(thread_buf,
3114 sizeof(thread_buf),
3115 es->df_delay_timer));
3116 json_object_int_add(json, "nexthopGroup", es->nhg_id);
3117 if (listcount(es->es_vtep_list)) {
3118 json_vteps = json_object_new_array();
3119 zebra_evpn_es_json_vtep_fill(es, json_vteps);
3120 json_object_object_add(json, "vteps", json_vteps);
3121 }
3122 } else {
3123 type_str[0] = '\0';
3124 if (es->flags & ZEBRA_EVPNES_LOCAL)
3125 strlcat(type_str, "Local", sizeof(type_str));
3126 if (es->flags & ZEBRA_EVPNES_REMOTE) {
3127 if (strnlen(type_str, sizeof(type_str)))
3128 strlcat(type_str, ",", sizeof(type_str));
3129 strlcat(type_str, "Remote", sizeof(type_str));
3130 }
3131
3132 vty_out(vty, "ESI: %s\n", es->esi_str);
3133 vty_out(vty, " Type: %s\n", type_str);
3134 vty_out(vty, " Interface: %s\n",
3135 (es->zif) ?
3136 es->zif->ifp->name : "-");
3137 if (es->flags & ZEBRA_EVPNES_LOCAL) {
3138 vty_out(vty, " State: %s\n",
3139 (es->flags & ZEBRA_EVPNES_OPER_UP) ? "up"
3140 : "down");
3141 vty_out(vty, " Bridge port: %s\n",
3142 (es->flags & ZEBRA_EVPNES_BR_PORT) ? "yes"
3143 : "no");
3144 }
3145 vty_out(vty, " Ready for BGP: %s\n",
3146 (es->flags & ZEBRA_EVPNES_READY_FOR_BGP) ?
3147 "yes" : "no");
3148 if (es->flags & ZEBRA_EVPNES_BYPASS)
3149 vty_out(vty, " LACP bypass: on\n");
3150 vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
3151 vty_out(vty, " MAC Count: %d\n", listcount(es->mac_list));
3152 if (es->flags & ZEBRA_EVPNES_LOCAL)
3153 vty_out(vty, " DF status: %s \n",
3154 (es->flags & ZEBRA_EVPNES_NON_DF) ? "non-df"
3155 : "df");
3156 if (es->df_delay_timer)
3157 vty_out(vty, " DF delay: %s\n",
3158 thread_timer_to_hhmmss(thread_buf,
3159 sizeof(thread_buf),
3160 es->df_delay_timer));
3161 vty_out(vty, " DF preference: %u\n", es->df_pref);
3162 vty_out(vty, " Nexthop group: %u\n", es->nhg_id);
3163 vty_out(vty, " VTEPs:\n");
3164 for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
3165 vty_out(vty, " %pI4",
3166 &es_vtep->vtep_ip);
3167 if (es_vtep->flags & ZEBRA_EVPNES_VTEP_RXED_ESR)
3168 vty_out(vty, " df_alg: %s df_pref: %d",
3169 evpn_es_df_alg2str(es_vtep->df_alg,
3170 alg_buf,
3171 sizeof(alg_buf)),
3172 es_vtep->df_pref);
3173 vty_out(vty, " nh: %u\n",
3174 es_vtep->nh ? es_vtep->nh->nh_id : 0);
3175 }
3176
3177 vty_out(vty, "\n");
3178 }
3179 }
3180
3181 void zebra_evpn_es_show(struct vty *vty, bool uj)
3182 {
3183 struct zebra_evpn_es *es;
3184 json_object *json_array = NULL;
3185
3186 if (uj) {
3187 json_array = json_object_new_array();
3188 } else {
3189 vty_out(vty, "Type: B bypass, L local, R remote, N non-DF\n");
3190 vty_out(vty, "%-30s %-4s %-21s %s\n",
3191 "ESI", "Type", "ES-IF", "VTEPs");
3192 }
3193
3194 RB_FOREACH(es, zebra_es_rb_head, &zmh_info->es_rb_tree)
3195 zebra_evpn_es_show_entry(vty, es, json_array);
3196
3197 if (uj)
3198 vty_json(vty, json_array);
3199 }
3200
3201 void zebra_evpn_es_show_detail(struct vty *vty, bool uj)
3202 {
3203 struct zebra_evpn_es *es;
3204 json_object *json_array = NULL;
3205
3206 if (uj)
3207 json_array = json_object_new_array();
3208
3209 RB_FOREACH (es, zebra_es_rb_head, &zmh_info->es_rb_tree) {
3210 json_object *json = NULL;
3211
3212 if (uj)
3213 json = json_object_new_object();
3214 zebra_evpn_es_show_entry_detail(vty, es, json);
3215 if (uj)
3216 json_object_array_add(json_array, json);
3217 }
3218
3219 if (uj)
3220 vty_json(vty, json_array);
3221 }
3222
3223 void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi)
3224 {
3225 struct zebra_evpn_es *es;
3226 char esi_str[ESI_STR_LEN];
3227 json_object *json = NULL;
3228
3229 if (uj)
3230 json = json_object_new_object();
3231
3232 es = zebra_evpn_es_find(esi);
3233
3234 if (es) {
3235 zebra_evpn_es_show_entry_detail(vty, es, json);
3236 } else {
3237 if (!uj) {
3238 esi_to_str(esi, esi_str, sizeof(esi_str));
3239 vty_out(vty, "ESI %s does not exist\n", esi_str);
3240 }
3241 }
3242
3243 if (uj)
3244 vty_json(vty, json);
3245 }
3246
3247 int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp)
3248 {
3249 struct zebra_if *zif = ifp->info;
3250 char buf[ETHER_ADDR_STRLEN];
3251 bool type_3_esi = false;
3252 char esi_buf[ESI_STR_LEN];
3253
3254 if (zif->es_info.lid) {
3255 vty_out(vty, " evpn mh es-id %u\n", zif->es_info.lid);
3256 type_3_esi = true;
3257 }
3258
3259 if (!is_zero_mac(&zif->es_info.sysmac)) {
3260 vty_out(vty, " evpn mh es-sys-mac %s\n",
3261 prefix_mac2str(&zif->es_info.sysmac,
3262 buf, sizeof(buf)));
3263 type_3_esi = true;
3264 }
3265
3266 if (!type_3_esi
3267 && memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
3268 vty_out(vty, " evpn mh es-id %s\n",
3269 esi_to_str(&zif->es_info.esi, esi_buf, sizeof(esi_buf)));
3270
3271 if (zif->es_info.df_pref)
3272 vty_out(vty, " evpn mh es-df-pref %u\n", zif->es_info.df_pref);
3273
3274 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
3275 vty_out(vty, " evpn mh uplink\n");
3276
3277 return 0;
3278 }
3279
3280 #include "zebra/zebra_evpn_mh_clippy.c"
3281 /* CLI for setting an ES in bypass mode */
3282 DEFPY_HIDDEN(zebra_evpn_es_bypass, zebra_evpn_es_bypass_cmd,
3283 "[no] evpn mh bypass",
3284 NO_STR "EVPN\n" EVPN_MH_VTY_STR "set bypass mode\n")
3285 {
3286 VTY_DECLVAR_CONTEXT(interface, ifp);
3287 struct zebra_if *zif;
3288
3289 zif = ifp->info;
3290
3291 if (no) {
3292 zebra_evpn_es_bypass_cfg_update(zif, false);
3293 } else {
3294 if (!zebra_evpn_is_if_es_capable(zif)) {
3295 vty_out(vty,
3296 "%% DF bypass cannot be associated with this interface type\n");
3297 return CMD_WARNING;
3298 }
3299 zebra_evpn_es_bypass_cfg_update(zif, true);
3300 }
3301 return CMD_SUCCESS;
3302 }
3303
3304 /* CLI for configuring DF preference part for an ES */
3305 DEFPY(zebra_evpn_es_pref, zebra_evpn_es_pref_cmd,
3306 "[no$no] evpn mh es-df-pref [(1-65535)$df_pref]",
3307 NO_STR "EVPN\n" EVPN_MH_VTY_STR
3308 "preference value used for DF election\n"
3309 "pref\n")
3310 {
3311 VTY_DECLVAR_CONTEXT(interface, ifp);
3312 struct zebra_if *zif;
3313
3314 zif = ifp->info;
3315
3316 if (no) {
3317 zebra_evpn_es_df_pref_update(zif, 0);
3318 } else {
3319 if (!zebra_evpn_is_if_es_capable(zif)) {
3320 vty_out(vty,
3321 "%% DF preference cannot be associated with this interface type\n");
3322 return CMD_WARNING;
3323 }
3324 zebra_evpn_es_df_pref_update(zif, df_pref);
3325 }
3326 return CMD_SUCCESS;
3327 }
3328
3329 /* CLI for setting up sysmac part of ESI on an access port */
3330 DEFPY(zebra_evpn_es_sys_mac,
3331 zebra_evpn_es_sys_mac_cmd,
3332 "[no$no] evpn mh es-sys-mac [X:X:X:X:X:X$mac]",
3333 NO_STR
3334 "EVPN\n"
3335 EVPN_MH_VTY_STR
3336 "Ethernet segment system MAC\n"
3337 MAC_STR
3338 )
3339 {
3340 VTY_DECLVAR_CONTEXT(interface, ifp);
3341 struct zebra_if *zif;
3342 int ret = 0;
3343
3344 zif = ifp->info;
3345
3346 if (no) {
3347 static struct ethaddr zero_mac;
3348
3349 ret = zebra_evpn_es_sys_mac_update(zif, &zero_mac);
3350 if (ret == -1) {
3351 vty_out(vty, "%% Failed to clear ES sysmac\n");
3352 return CMD_WARNING;
3353 }
3354 } else {
3355
3356 if (!zebra_evpn_is_if_es_capable(zif)) {
3357 vty_out(vty,
3358 "%% ESI cannot be associated with this interface type\n");
3359 return CMD_WARNING;
3360 }
3361
3362 if (!mac || is_zero_mac(&mac->eth_addr)) {
3363 vty_out(vty, "%% ES sysmac value is invalid\n");
3364 return CMD_WARNING;
3365 }
3366
3367 ret = zebra_evpn_es_sys_mac_update(zif, &mac->eth_addr);
3368 if (ret == -1) {
3369 vty_out(vty,
3370 "%% ESI already exists on a different interface\n");
3371 return CMD_WARNING;
3372 }
3373 }
3374 return CMD_SUCCESS;
3375 }
3376
3377 /* CLI for setting up local-ID part of ESI on an access port */
3378 DEFPY(zebra_evpn_es_id,
3379 zebra_evpn_es_id_cmd,
3380 "[no$no] evpn mh es-id [(1-16777215)$es_lid | NAME$esi_str]",
3381 NO_STR
3382 "EVPN\n"
3383 EVPN_MH_VTY_STR
3384 "Ethernet segment identifier\n"
3385 "local discriminator\n"
3386 "10-byte ID - 00:AA:BB:CC:DD:EE:FF:GG:HH:II\n"
3387 )
3388 {
3389 VTY_DECLVAR_CONTEXT(interface, ifp);
3390 struct zebra_if *zif;
3391 int ret = 0;
3392 esi_t esi;
3393
3394 zif = ifp->info;
3395
3396 if (no) {
3397 if (zif->es_info.lid)
3398 ret = zebra_evpn_es_lid_update(zif, 0);
3399 else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi)))
3400 ret = zebra_evpn_es_type0_esi_update(zif, zero_esi);
3401
3402 if (ret == -1) {
3403 vty_out(vty,
3404 "%% Failed to clear ES local id or ESI name\n");
3405 return CMD_WARNING;
3406 }
3407 } else {
3408 if (!zebra_evpn_is_if_es_capable(zif)) {
3409 vty_out(vty,
3410 "%% ESI cannot be associated with this interface type\n");
3411 return CMD_WARNING;
3412 }
3413
3414 if (esi_str) {
3415 if (!str_to_esi(esi_str, &esi)) {
3416 vty_out(vty, "%% Malformed ESI name\n");
3417 return CMD_WARNING;
3418 }
3419 ret = zebra_evpn_es_type0_esi_update(zif, &esi);
3420 } else {
3421 if (!es_lid) {
3422 vty_out(vty,
3423 "%% Specify ES local id or ESI name\n");
3424 return CMD_WARNING;
3425 }
3426 ret = zebra_evpn_es_lid_update(zif, es_lid);
3427 }
3428
3429 if (ret == -1) {
3430 vty_out(vty,
3431 "%% ESI already exists on a different interface\n");
3432 return CMD_WARNING;
3433 }
3434 }
3435 return CMD_SUCCESS;
3436 }
3437
3438 /* CLI for tagging an interface as an uplink */
3439 DEFPY(zebra_evpn_mh_uplink, zebra_evpn_mh_uplink_cmd, "[no] evpn mh uplink",
3440 NO_STR "EVPN\n" EVPN_MH_VTY_STR "uplink to the VxLAN core\n")
3441 {
3442 VTY_DECLVAR_CONTEXT(interface, ifp);
3443 struct zebra_if *zif;
3444
3445 zif = ifp->info;
3446 zebra_evpn_mh_uplink_cfg_update(zif, no ? false : true);
3447
3448 return CMD_SUCCESS;
3449 }
3450
3451 void zebra_evpn_mh_json(json_object *json)
3452 {
3453 json_object *json_array;
3454 char thread_buf[THREAD_TIMER_STRLEN];
3455
3456 json_object_int_add(json, "macHoldtime", zmh_info->mac_hold_time);
3457 json_object_int_add(json, "neighHoldtime", zmh_info->neigh_hold_time);
3458 json_object_int_add(json, "startupDelay", zmh_info->startup_delay_time);
3459 json_object_string_add(
3460 json, "startupDelayTimer",
3461 thread_timer_to_hhmmss(thread_buf, sizeof(thread_buf),
3462 zmh_info->startup_delay_timer));
3463 json_object_int_add(json, "uplinkConfigCount",
3464 zmh_info->uplink_cfg_cnt);
3465 json_object_int_add(json, "uplinkActiveCount",
3466 zmh_info->uplink_oper_up_cnt);
3467
3468 if (zmh_info->protodown_rc) {
3469 json_array = json_object_new_array();
3470 if (CHECK_FLAG(zmh_info->protodown_rc,
3471 ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY))
3472 json_object_array_add(
3473 json_array,
3474 json_object_new_string("startupDelay"));
3475 if (CHECK_FLAG(zmh_info->protodown_rc,
3476 ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN))
3477 json_object_array_add(
3478 json_array,
3479 json_object_new_string("uplinkDown"));
3480 json_object_object_add(json, "protodownReasons", json_array);
3481 }
3482 }
3483
3484 void zebra_evpn_mh_print(struct vty *vty)
3485 {
3486 char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
3487 char thread_buf[THREAD_TIMER_STRLEN];
3488
3489 vty_out(vty, "EVPN MH:\n");
3490 vty_out(vty, " mac-holdtime: %ds, neigh-holdtime: %ds\n",
3491 zmh_info->mac_hold_time, zmh_info->neigh_hold_time);
3492 vty_out(vty, " startup-delay: %ds, start-delay-timer: %s\n",
3493 zmh_info->startup_delay_time,
3494 thread_timer_to_hhmmss(thread_buf, sizeof(thread_buf),
3495 zmh_info->startup_delay_timer));
3496 vty_out(vty, " uplink-cfg-cnt: %u, uplink-active-cnt: %u\n",
3497 zmh_info->uplink_cfg_cnt, zmh_info->uplink_oper_up_cnt);
3498 if (zmh_info->protodown_rc)
3499 vty_out(vty, " protodown reasons: %s\n",
3500 zebra_protodown_rc_str(zmh_info->protodown_rc, pd_buf,
3501 sizeof(pd_buf)));
3502 }
3503
3504 /*****************************************************************************/
3505 /* A base L2-VNI is maintained to derive parameters such as ES originator-IP.
3506 * XXX: once single vxlan device model becomes available this will not be
3507 * necessary
3508 */
3509 /* called when a new vni is added or becomes oper up or becomes a bridge port */
3510 void zebra_evpn_es_set_base_evpn(struct zebra_evpn *zevpn)
3511 {
3512 struct listnode *node;
3513 struct zebra_evpn_es *es;
3514
3515 if (zmh_info->es_base_evpn) {
3516 if (zmh_info->es_base_evpn != zevpn) {
3517 /* unrelated EVPN; ignore it */
3518 return;
3519 }
3520 /* check if the local vtep-ip has changed */
3521 } else {
3522 /* check if the EVPN can be used as base EVPN */
3523 if (!zebra_evpn_send_to_client_ok(zevpn))
3524 return;
3525
3526 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3527 zlog_debug("es base vni set to %d",
3528 zevpn->vni);
3529 zmh_info->es_base_evpn = zevpn;
3530 }
3531
3532 /* update local VTEP-IP */
3533 if (zmh_info->es_originator_ip.s_addr ==
3534 zmh_info->es_base_evpn->local_vtep_ip.s_addr)
3535 return;
3536
3537 zmh_info->es_originator_ip.s_addr =
3538 zmh_info->es_base_evpn->local_vtep_ip.s_addr;
3539
3540 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3541 zlog_debug("es originator ip set to %pI4",
3542 &zmh_info->es_base_evpn->local_vtep_ip);
3543
3544 /* if originator ip changes we need to update bgp */
3545 for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, node, es)) {
3546 zebra_evpn_es_run_df_election(es, __func__);
3547
3548 if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
3549 zebra_evpn_es_send_add_to_client(es);
3550 else
3551 zebra_evpn_es_re_eval_send_to_client(es,
3552 true /* es_evi_re_reval */);
3553 }
3554 }
3555
3556 /* called when a vni is removed or becomes oper down or is removed from a
3557 * bridge
3558 */
3559 void zebra_evpn_es_clear_base_evpn(struct zebra_evpn *zevpn)
3560 {
3561 struct listnode *node;
3562 struct zebra_evpn_es *es;
3563
3564 if (zmh_info->es_base_evpn != zevpn)
3565 return;
3566
3567 zmh_info->es_base_evpn = NULL;
3568 /* lost current base EVPN; try to find a new one */
3569 zebra_evpn_es_get_one_base_evpn();
3570
3571 /* couldn't locate an eligible base evpn */
3572 if (!zmh_info->es_base_evpn && zmh_info->es_originator_ip.s_addr) {
3573 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3574 zlog_debug("es originator ip cleared");
3575
3576 zmh_info->es_originator_ip.s_addr = 0;
3577 /* lost originator ip */
3578 for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, node, es)) {
3579 zebra_evpn_es_re_eval_send_to_client(es,
3580 true /* es_evi_re_reval */);
3581 }
3582 }
3583 }
3584
3585 /* Locate an "eligible" L2-VNI to follow */
3586 static int zebra_evpn_es_get_one_base_evpn_cb(struct hash_bucket *b, void *data)
3587 {
3588 struct zebra_evpn *zevpn = b->data;
3589
3590 zebra_evpn_es_set_base_evpn(zevpn);
3591
3592 if (zmh_info->es_base_evpn)
3593 return HASHWALK_ABORT;
3594
3595 return HASHWALK_CONTINUE;
3596 }
3597
3598 /* locate a base_evpn to follow for the purposes of common params like
3599 * originator IP
3600 */
3601 static void zebra_evpn_es_get_one_base_evpn(void)
3602 {
3603 struct zebra_vrf *zvrf;
3604
3605 zvrf = zebra_vrf_get_evpn();
3606 hash_walk(zvrf->evpn_table, zebra_evpn_es_get_one_base_evpn_cb, NULL);
3607 }
3608
3609 /*****************************************************************************
3610 * local ethernet segments can be error-disabled if the switch is not
3611 * ready to start transmitting traffic via the VxLAN overlay
3612 */
3613 bool zebra_evpn_is_es_bond(struct interface *ifp)
3614 {
3615 struct zebra_if *zif = ifp->info;
3616
3617 return !!(struct zebra_if *)zif->es_info.es;
3618 }
3619
3620 bool zebra_evpn_is_es_bond_member(struct interface *ifp)
3621 {
3622 struct zebra_if *zif = ifp->info;
3623
3624 return IS_ZEBRA_IF_BOND_SLAVE(zif->ifp) && zif->bondslave_info.bond_if
3625 && ((struct zebra_if *)zif->bondslave_info.bond_if->info)
3626 ->es_info.es;
3627 }
3628
3629 void zebra_evpn_mh_update_protodown_bond_mbr(struct zebra_if *zif, bool clear,
3630 const char *caller)
3631 {
3632 bool new_protodown;
3633 uint32_t old_protodown_rc = 0;
3634 uint32_t new_protodown_rc = 0;
3635 uint32_t protodown_rc = 0;
3636
3637 if (!clear) {
3638 struct zebra_if *bond_zif;
3639
3640 bond_zif = zif->bondslave_info.bond_if->info;
3641 protodown_rc = bond_zif->protodown_rc;
3642 }
3643
3644 old_protodown_rc = zif->protodown_rc;
3645 new_protodown_rc = (old_protodown_rc & ~ZEBRA_PROTODOWN_EVPN_ALL);
3646 new_protodown_rc |= (protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL);
3647 new_protodown = !!new_protodown_rc;
3648
3649 if (IS_ZEBRA_DEBUG_EVPN_MH_ES && (new_protodown_rc != old_protodown_rc))
3650 zlog_debug(
3651 "%s bond mbr %s protodown_rc changed; old 0x%x new 0x%x",
3652 caller, zif->ifp->name, old_protodown_rc,
3653 new_protodown_rc);
3654
3655 if (zebra_if_update_protodown_rc(zif->ifp, new_protodown,
3656 new_protodown_rc) == 0) {
3657 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3658 zlog_debug("%s protodown %s", zif->ifp->name,
3659 new_protodown ? "on" : "off");
3660 }
3661 }
3662
3663 /* The bond members inherit the protodown reason code from the bond */
3664 static void zebra_evpn_mh_update_protodown_bond(struct zebra_if *bond_zif)
3665 {
3666 struct zebra_if *zif;
3667 struct listnode *node;
3668
3669 if (!bond_zif->bond_info.mbr_zifs)
3670 return;
3671
3672 for (ALL_LIST_ELEMENTS_RO(bond_zif->bond_info.mbr_zifs, node, zif)) {
3673 zebra_evpn_mh_update_protodown_bond_mbr(zif, false /*clear*/,
3674 __func__);
3675 }
3676 }
3677
3678 /* The global EVPN MH protodown rc is applied to all local ESs */
3679 static void zebra_evpn_mh_update_protodown_es(struct zebra_evpn_es *es,
3680 bool resync_dplane)
3681 {
3682 struct zebra_if *zif;
3683 uint32_t old_protodown_rc;
3684
3685 zif = es->zif;
3686 /* if the reason code is the same bail unless it is a new
3687 * ES bond in that case we would need to ensure that the
3688 * dplane is really in sync with zebra
3689 */
3690 if (!resync_dplane
3691 && (zif->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL)
3692 == (zmh_info->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL))
3693 return;
3694
3695 old_protodown_rc = zif->protodown_rc;
3696 zif->protodown_rc &= ~ZEBRA_PROTODOWN_EVPN_ALL;
3697 zif->protodown_rc |=
3698 (zmh_info->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL);
3699
3700 if (IS_ZEBRA_DEBUG_EVPN_MH_ES
3701 && (old_protodown_rc != zif->protodown_rc))
3702 zlog_debug(
3703 "es %s ifp %s protodown_rc changed; old 0x%x new 0x%x",
3704 es->esi_str, zif->ifp->name, old_protodown_rc,
3705 zif->protodown_rc);
3706
3707 /* update dataplane with the new protodown setting */
3708 zebra_evpn_mh_update_protodown_bond(zif);
3709 }
3710
3711 static void zebra_evpn_mh_clear_protodown_es(struct zebra_evpn_es *es)
3712 {
3713 struct zebra_if *zif;
3714 uint32_t old_protodown_rc;
3715
3716 zif = es->zif;
3717 if (!(zif->protodown_rc & ZEBRA_PROTODOWN_EVPN_ALL))
3718 return;
3719
3720 old_protodown_rc = zif->protodown_rc;
3721 zif->protodown_rc &= ~ZEBRA_PROTODOWN_EVPN_ALL;
3722
3723 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3724 zlog_debug(
3725 "clear: es %s ifp %s protodown_rc cleared; old 0x%x new 0x%x",
3726 es->esi_str, zif->ifp->name, old_protodown_rc,
3727 zif->protodown_rc);
3728
3729 /* update dataplane with the new protodown setting */
3730 zebra_evpn_mh_update_protodown_bond(zif);
3731 }
3732
3733 static void zebra_evpn_mh_update_protodown_es_all(void)
3734 {
3735 struct listnode *node;
3736 struct zebra_evpn_es *es;
3737
3738 for (ALL_LIST_ELEMENTS_RO(zmh_info->local_es_list, node, es))
3739 zebra_evpn_mh_update_protodown_es(es, false /*resync_dplane*/);
3740 }
3741
3742 static void zebra_evpn_mh_update_protodown(uint32_t protodown_rc, bool set)
3743 {
3744 uint32_t old_protodown_rc = zmh_info->protodown_rc;
3745
3746 if (set) {
3747 if ((protodown_rc & zmh_info->protodown_rc) == protodown_rc)
3748 return;
3749
3750 zmh_info->protodown_rc |= protodown_rc;
3751 } else {
3752 if (!(protodown_rc & zmh_info->protodown_rc))
3753 return;
3754 zmh_info->protodown_rc &= ~protodown_rc;
3755 }
3756
3757 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3758 zlog_debug("mh protodown_rc changed; old 0x%x new 0x%x",
3759 old_protodown_rc, zmh_info->protodown_rc);
3760 zebra_evpn_mh_update_protodown_es_all();
3761 }
3762
3763 static inline bool zebra_evpn_mh_is_all_uplinks_down(void)
3764 {
3765 return zmh_info->uplink_cfg_cnt && !zmh_info->uplink_oper_up_cnt;
3766 }
3767
3768 static void zebra_evpn_mh_uplink_oper_flags_update(struct zebra_if *zif,
3769 bool set)
3770 {
3771 if (set && if_is_operative(zif->ifp)) {
3772 if (!(zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP)) {
3773 zif->flags |= ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP;
3774 ++zmh_info->uplink_oper_up_cnt;
3775 }
3776 } else {
3777 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) {
3778 zif->flags &= ~ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP;
3779 if (zmh_info->uplink_oper_up_cnt)
3780 --zmh_info->uplink_oper_up_cnt;
3781 }
3782 }
3783 }
3784
3785 static void zebra_evpn_mh_uplink_cfg_update(struct zebra_if *zif, bool set)
3786 {
3787 bool old_protodown = zebra_evpn_mh_is_all_uplinks_down();
3788 bool new_protodown;
3789
3790 if (set) {
3791 if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
3792 return;
3793
3794 zif->flags |= ZIF_FLAG_EVPN_MH_UPLINK;
3795 ++zmh_info->uplink_cfg_cnt;
3796 } else {
3797 if (!(zif->flags & ZIF_FLAG_EVPN_MH_UPLINK))
3798 return;
3799
3800 zif->flags &= ~ZIF_FLAG_EVPN_MH_UPLINK;
3801 if (zmh_info->uplink_cfg_cnt)
3802 --zmh_info->uplink_cfg_cnt;
3803 }
3804
3805 zebra_evpn_mh_uplink_oper_flags_update(zif, set);
3806 new_protodown = zebra_evpn_mh_is_all_uplinks_down();
3807 if (old_protodown == new_protodown)
3808 return;
3809
3810 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3811 zlog_debug(
3812 "mh-uplink-cfg-chg on if %s/%d %s uplinks cfg %u up %u",
3813 zif->ifp->name, zif->ifp->ifindex, set ? "set" : "down",
3814 zmh_info->uplink_cfg_cnt, zmh_info->uplink_oper_up_cnt);
3815
3816 zebra_evpn_mh_update_protodown(ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN,
3817 new_protodown);
3818 }
3819
3820 void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif)
3821 {
3822 bool old_protodown = zebra_evpn_mh_is_all_uplinks_down();
3823 bool new_protodown;
3824
3825 zebra_evpn_mh_uplink_oper_flags_update(zif, true /*set*/);
3826
3827 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3828 zlog_debug(
3829 "mh-uplink-oper-chg on if %s/%d %s; uplinks cfg %u up %u",
3830 zif->ifp->name, zif->ifp->ifindex,
3831 if_is_operative(zif->ifp) ? "up" : "down",
3832 zmh_info->uplink_cfg_cnt, zmh_info->uplink_oper_up_cnt);
3833
3834 new_protodown = zebra_evpn_mh_is_all_uplinks_down();
3835 if (old_protodown == new_protodown)
3836 return;
3837
3838 /* if protodown_rc XXX_UPLINK_DOWN is about to be cleared
3839 * fire up the start-up delay timer to allow the EVPN network
3840 * to converge (Type-2 routes need to be advertised and processed)
3841 */
3842 if (!new_protodown && (zmh_info->uplink_oper_up_cnt == 1))
3843 zebra_evpn_mh_startup_delay_timer_start("uplink-up");
3844
3845 zebra_evpn_mh_update_protodown(ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN,
3846 new_protodown);
3847 }
3848
3849 static void zebra_evpn_mh_startup_delay_exp_cb(struct thread *t)
3850 {
3851 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3852 zlog_debug("startup-delay expired");
3853
3854 zebra_evpn_mh_update_protodown(ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY,
3855 false /* set */);
3856 }
3857
3858 static void zebra_evpn_mh_startup_delay_timer_start(const char *rc)
3859 {
3860 if (zmh_info->startup_delay_timer) {
3861 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3862 zlog_debug("startup-delay timer cancelled");
3863 THREAD_OFF(zmh_info->startup_delay_timer);
3864 }
3865
3866 if (zmh_info->startup_delay_time) {
3867 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3868 zlog_debug(
3869 "startup-delay timer started for %d sec on %s",
3870 zmh_info->startup_delay_time, rc);
3871 thread_add_timer(zrouter.master,
3872 zebra_evpn_mh_startup_delay_exp_cb, NULL,
3873 zmh_info->startup_delay_time,
3874 &zmh_info->startup_delay_timer);
3875 zebra_evpn_mh_update_protodown(
3876 ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY, true /* set */);
3877 } else {
3878 zebra_evpn_mh_update_protodown(
3879 ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY, false /* set */);
3880 }
3881 }
3882
3883 /*****************************************************************************
3884 * Nexthop management: nexthops associated with Type-2 routes that have
3885 * an ES as destination are consolidated by BGP into a per-VRF nh->rmac
3886 * mapping which is the installed as a remote neigh/fdb entry with a
3887 * dummy (type-1) prefix referencing it.
3888 * This handling is needed because Type-2 routes with ES as dest use NHG
3889 * that are setup using EAD routes (i.e. such NHGs do not include the
3890 * RMAC info).
3891 ****************************************************************************/
3892 void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS)
3893 {
3894 struct stream *s;
3895 vrf_id_t vrf_id;
3896 struct ipaddr nh;
3897 struct ethaddr rmac;
3898 struct prefix_evpn dummy_prefix;
3899 size_t min_len = 4 + sizeof(nh);
3900
3901 s = msg;
3902
3903 /*
3904 * Ensure that the stream sent to us is long enough
3905 */
3906 if (hdr->command == ZEBRA_EVPN_REMOTE_NH_ADD)
3907 min_len += sizeof(rmac);
3908 if (hdr->length < min_len)
3909 return;
3910
3911 vrf_id = stream_getl(s);
3912 stream_get(&nh, s, sizeof(nh));
3913
3914 memset(&dummy_prefix, 0, sizeof(dummy_prefix));
3915 dummy_prefix.family = AF_EVPN;
3916 dummy_prefix.prefixlen = (sizeof(struct evpn_addr) * 8);
3917 dummy_prefix.prefix.route_type = 1; /* XXX - fixup to type-1 def */
3918 dummy_prefix.prefix.ead_addr.ip.ipa_type = nh.ipa_type;
3919
3920 if (hdr->command == ZEBRA_EVPN_REMOTE_NH_ADD) {
3921 stream_get(&rmac, s, sizeof(rmac));
3922 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3923 zlog_debug(
3924 "evpn remote nh %d %pIA rmac %pEA add pfx %pFX",
3925 vrf_id, &nh, &rmac, &dummy_prefix);
3926 zebra_rib_queue_evpn_route_add(vrf_id, &rmac, &nh,
3927 (struct prefix *)&dummy_prefix);
3928 } else {
3929 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
3930 zlog_debug("evpn remote nh %d %pIA del pfx %pFX",
3931 vrf_id, &nh, &dummy_prefix);
3932 zebra_rib_queue_evpn_route_del(vrf_id, &nh,
3933 (struct prefix *)&dummy_prefix);
3934 }
3935 }
3936
3937 /*****************************************************************************/
3938 void zebra_evpn_mh_config_write(struct vty *vty)
3939 {
3940 if (zmh_info->mac_hold_time != ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF)
3941 vty_out(vty, "evpn mh mac-holdtime %d\n",
3942 zmh_info->mac_hold_time);
3943
3944 if (zmh_info->neigh_hold_time != ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF)
3945 vty_out(vty, "evpn mh neigh-holdtime %d\n",
3946 zmh_info->neigh_hold_time);
3947
3948 if (zmh_info->startup_delay_time != ZEBRA_EVPN_MH_STARTUP_DELAY_DEF)
3949 vty_out(vty, "evpn mh startup-delay %d\n",
3950 zmh_info->startup_delay_time);
3951
3952 if (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF)
3953 vty_out(vty, "evpn mh redirect-off\n");
3954 }
3955
3956 int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
3957 uint32_t duration, bool set_default)
3958 {
3959 if (set_default)
3960 duration = ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF;
3961
3962 zmh_info->neigh_hold_time = duration;
3963
3964 return 0;
3965 }
3966
3967 int zebra_evpn_mh_mac_holdtime_update(struct vty *vty,
3968 uint32_t duration, bool set_default)
3969 {
3970 if (set_default)
3971 duration = ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF;
3972
3973 zmh_info->mac_hold_time = duration;
3974
3975 return 0;
3976 }
3977
3978 int zebra_evpn_mh_startup_delay_update(struct vty *vty, uint32_t duration,
3979 bool set_default)
3980 {
3981 if (set_default)
3982 duration = ZEBRA_EVPN_MH_STARTUP_DELAY_DEF;
3983
3984 zmh_info->startup_delay_time = duration;
3985
3986 /* if startup_delay_timer is running allow it to be adjusted
3987 * up or down
3988 */
3989 if (zmh_info->startup_delay_timer)
3990 zebra_evpn_mh_startup_delay_timer_start("config");
3991
3992 return 0;
3993 }
3994
3995 int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off)
3996 {
3997 /* This knob needs to be set before ESs are configured
3998 * i.e. cannot be changed on the fly
3999 */
4000 if (redirect_off)
4001 zmh_info->flags |= ZEBRA_EVPN_MH_REDIRECT_OFF;
4002 else
4003 zmh_info->flags &= ~ZEBRA_EVPN_MH_REDIRECT_OFF;
4004
4005 return 0;
4006 }
4007
4008 void zebra_evpn_interface_init(void)
4009 {
4010 install_element(INTERFACE_NODE, &zebra_evpn_es_id_cmd);
4011 install_element(INTERFACE_NODE, &zebra_evpn_es_sys_mac_cmd);
4012 install_element(INTERFACE_NODE, &zebra_evpn_es_pref_cmd);
4013 install_element(INTERFACE_NODE, &zebra_evpn_es_bypass_cmd);
4014 install_element(INTERFACE_NODE, &zebra_evpn_mh_uplink_cmd);
4015 }
4016
4017 void zebra_evpn_mh_init(void)
4018 {
4019 zrouter.mh_info = XCALLOC(MTYPE_ZMH_INFO, sizeof(*zrouter.mh_info));
4020
4021 zmh_info->mac_hold_time = ZEBRA_EVPN_MH_MAC_HOLD_TIME_DEF;
4022 zmh_info->neigh_hold_time = ZEBRA_EVPN_MH_NEIGH_HOLD_TIME_DEF;
4023 /* setup ES tables */
4024 RB_INIT(zebra_es_rb_head, &zmh_info->es_rb_tree);
4025 zmh_info->local_es_list = list_new();
4026 listset_app_node_mem(zmh_info->local_es_list);
4027
4028 bf_init(zmh_info->nh_id_bitmap, EVPN_NH_ID_MAX);
4029 bf_assign_zero_index(zmh_info->nh_id_bitmap);
4030 zmh_info->nhg_table = hash_create(zebra_evpn_nhg_hash_keymake,
4031 zebra_evpn_nhg_cmp, "l2 NHG table");
4032 zmh_info->nh_ip_table =
4033 hash_create(zebra_evpn_nh_ip_hash_keymake, zebra_evpn_nh_ip_cmp,
4034 "l2 NH IP table");
4035
4036 /* setup broadcast domain tables */
4037 zmh_info->evpn_vlan_table = hash_create(zebra_evpn_acc_vl_hash_keymake,
4038 zebra_evpn_acc_vl_cmp, "access VLAN hash table");
4039
4040 zmh_info->startup_delay_time = ZEBRA_EVPN_MH_STARTUP_DELAY_DEF;
4041 zebra_evpn_mh_startup_delay_timer_start("init");
4042 }
4043
4044 void zebra_evpn_mh_terminate(void)
4045 {
4046 list_delete(&zmh_info->local_es_list);
4047
4048 hash_iterate(zmh_info->evpn_vlan_table,
4049 zebra_evpn_acc_vl_cleanup_all, NULL);
4050 hash_free(zmh_info->evpn_vlan_table);
4051 hash_free(zmh_info->nhg_table);
4052 hash_free(zmh_info->nh_ip_table);
4053 bf_free(zmh_info->nh_id_bitmap);
4054
4055 XFREE(MTYPE_ZMH_INFO, zrouter.mh_info);
4056 }