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