]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_evpn_mac.c
*: Change thread->func to return void instead of int
[mirror_frr.git] / zebra / zebra_evpn_mac.c
1 /*
2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23 #include <zebra.h>
24
25 #include "hash.h"
26 #include "interface.h"
27 #include "jhash.h"
28 #include "memory.h"
29 #include "prefix.h"
30 #include "vlan.h"
31 #include "json.h"
32 #include "printfrr.h"
33
34 #include "zebra/zserv.h"
35 #include "zebra/debug.h"
36 #include "zebra/zebra_router.h"
37 #include "zebra/zebra_errors.h"
38 #include "zebra/zebra_vrf.h"
39 #include "zebra/zebra_evpn.h"
40 #include "zebra/zebra_evpn_mh.h"
41 #include "zebra/zebra_evpn_mac.h"
42 #include "zebra/zebra_evpn_neigh.h"
43
44 DEFINE_MTYPE_STATIC(ZEBRA, MAC, "EVPN MAC");
45
46 /*
47 * Return number of valid MACs in an EVPN's MAC hash table - all
48 * remote MACs and non-internal (auto) local MACs count.
49 */
50 uint32_t num_valid_macs(struct zebra_evpn *zevpn)
51 {
52 unsigned int i;
53 uint32_t num_macs = 0;
54 struct hash *hash;
55 struct hash_bucket *hb;
56 struct zebra_mac *mac;
57
58 hash = zevpn->mac_table;
59 if (!hash)
60 return num_macs;
61 for (i = 0; i < hash->size; i++) {
62 for (hb = hash->index[i]; hb; hb = hb->next) {
63 mac = (struct zebra_mac *)hb->data;
64 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
65 || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
66 || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
67 num_macs++;
68 }
69 }
70
71 return num_macs;
72 }
73
74 uint32_t num_dup_detected_macs(struct zebra_evpn *zevpn)
75 {
76 unsigned int i;
77 uint32_t num_macs = 0;
78 struct hash *hash;
79 struct hash_bucket *hb;
80 struct zebra_mac *mac;
81
82 hash = zevpn->mac_table;
83 if (!hash)
84 return num_macs;
85 for (i = 0; i < hash->size; i++) {
86 for (hb = hash->index[i]; hb; hb = hb->next) {
87 mac = (struct zebra_mac *)hb->data;
88 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
89 num_macs++;
90 }
91 }
92
93 return num_macs;
94 }
95
96 /* Setup mac_list against the access port. This is done when a mac uses
97 * the ifp as destination for the first time
98 */
99 static void zebra_evpn_mac_ifp_new(struct zebra_if *zif)
100 {
101 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
102 zlog_debug("MAC list created for ifp %s (%u)", zif->ifp->name,
103 zif->ifp->ifindex);
104
105 zif->mac_list = list_new();
106 listset_app_node_mem(zif->mac_list);
107 }
108
109 /* Unlink local mac from a destination access port */
110 static void zebra_evpn_mac_ifp_unlink(struct zebra_mac *zmac)
111 {
112 struct zebra_if *zif;
113 struct interface *ifp = zmac->ifp;
114
115 if (!ifp)
116 return;
117
118 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
119 zlog_debug("VNI %d MAC %pEA unlinked from ifp %s (%u)",
120 zmac->zevpn->vni,
121 &zmac->macaddr,
122 ifp->name, ifp->ifindex);
123
124 zif = ifp->info;
125 list_delete_node(zif->mac_list, &zmac->ifp_listnode);
126 zmac->ifp = NULL;
127 }
128
129 /* Free up the mac_list if any as a part of the interface del/cleanup */
130 void zebra_evpn_mac_ifp_del(struct interface *ifp)
131 {
132 struct zebra_if *zif = ifp->info;
133 struct listnode *node;
134 struct zebra_mac *zmac;
135
136 if (zif->mac_list) {
137 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
138 zlog_debug("MAC list deleted for ifp %s (%u)",
139 zif->ifp->name, zif->ifp->ifindex);
140
141 for (ALL_LIST_ELEMENTS_RO(zif->mac_list, node, zmac)) {
142 zebra_evpn_mac_ifp_unlink(zmac);
143 }
144 list_delete(&zif->mac_list);
145 }
146 }
147
148 /* Link local mac to destination access port. This is done only if the
149 * local mac is associated with a zero ESI i.e. single attach or lacp-bypass
150 * bridge port member
151 */
152 static void zebra_evpn_mac_ifp_link(struct zebra_mac *zmac,
153 struct interface *ifp)
154 {
155 struct zebra_if *zif;
156
157 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
158 return;
159
160 /* already linked to the destination */
161 if (zmac->ifp == ifp)
162 return;
163
164 /* unlink the mac from any old destination */
165 if (zmac->ifp)
166 zebra_evpn_mac_ifp_unlink(zmac);
167
168 if (!ifp)
169 return;
170
171 zif = ifp->info;
172 /* the interface mac_list is created on first mac link attempt */
173 if (!zif->mac_list)
174 zebra_evpn_mac_ifp_new(zif);
175
176 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
177 zlog_debug("VNI %d MAC %pEA linked to ifp %s (%u)",
178 zmac->zevpn->vni,
179 &zmac->macaddr,
180 ifp->name, ifp->ifindex);
181
182 zmac->ifp = ifp;
183 listnode_init(&zmac->ifp_listnode, zmac);
184 listnode_add(zif->mac_list, &zmac->ifp_listnode);
185 }
186
187 /* If the mac is a local mac clear links to destination access port */
188 void zebra_evpn_mac_clear_fwd_info(struct zebra_mac *zmac)
189 {
190 zebra_evpn_mac_ifp_unlink(zmac);
191 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
192 }
193
194 /*
195 * Install remote MAC into the forwarding plane.
196 */
197 int zebra_evpn_rem_mac_install(struct zebra_evpn *zevpn, struct zebra_mac *mac,
198 bool was_static)
199 {
200 const struct zebra_if *zif, *br_zif;
201 const struct zebra_l2info_vxlan *vxl;
202 bool sticky;
203 enum zebra_dplane_result res;
204 const struct interface *br_ifp;
205 vlanid_t vid;
206 uint32_t nhg_id;
207 struct in_addr vtep_ip;
208
209 zif = zevpn->vxlan_if->info;
210 if (!zif)
211 return -1;
212
213 br_ifp = zif->brslave_info.br_if;
214 if (br_ifp == NULL)
215 return -1;
216
217 vxl = &zif->l2info.vxl;
218
219 sticky = !!CHECK_FLAG(mac->flags,
220 (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
221
222 /* If nexthop group for the FDB entry is inactive (not programmed in
223 * the dataplane) the MAC entry cannot be installed
224 */
225 if (mac->es) {
226 if (!(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
227 return -1;
228 nhg_id = mac->es->nhg_id;
229 vtep_ip.s_addr = 0;
230 } else {
231 nhg_id = 0;
232 vtep_ip = mac->fwd_info.r_vtep_ip;
233 }
234
235 br_zif = (const struct zebra_if *)(br_ifp->info);
236
237 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
238 vid = vxl->access_vlan;
239 else
240 vid = 0;
241
242 res = dplane_rem_mac_add(zevpn->vxlan_if, br_ifp, vid, &mac->macaddr,
243 vtep_ip, sticky, nhg_id, was_static);
244 if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
245 return 0;
246 else
247 return -1;
248 }
249
250 /*
251 * Uninstall remote MAC from the forwarding plane.
252 */
253 int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn,
254 struct zebra_mac *mac, bool force)
255 {
256 const struct zebra_if *zif, *br_zif;
257 const struct zebra_l2info_vxlan *vxl;
258 struct in_addr vtep_ip;
259 const struct interface *ifp, *br_ifp;
260 vlanid_t vid;
261 enum zebra_dplane_result res;
262
263 /* If the MAC was not installed there is no need to uninstall it */
264 if (!force && mac->es && !(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
265 return -1;
266
267 if (!zevpn->vxlan_if) {
268 if (IS_ZEBRA_DEBUG_VXLAN)
269 zlog_debug(
270 "VNI %u hash %p couldn't be uninstalled - no intf",
271 zevpn->vni, zevpn);
272 return -1;
273 }
274
275 zif = zevpn->vxlan_if->info;
276 if (!zif)
277 return -1;
278
279 br_ifp = zif->brslave_info.br_if;
280 if (br_ifp == NULL)
281 return -1;
282
283 vxl = &zif->l2info.vxl;
284
285 br_zif = (const struct zebra_if *)br_ifp->info;
286
287 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
288 vid = vxl->access_vlan;
289 else
290 vid = 0;
291
292 ifp = zevpn->vxlan_if;
293 vtep_ip = mac->fwd_info.r_vtep_ip;
294
295 res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vtep_ip);
296 if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
297 return 0;
298 else
299 return -1;
300 }
301
302 /*
303 * Decrement neighbor refcount of MAC; uninstall and free it if
304 * appropriate.
305 */
306 void zebra_evpn_deref_ip2mac(struct zebra_evpn *zevpn, struct zebra_mac *mac)
307 {
308 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
309 return;
310
311 /* If all remote neighbors referencing a remote MAC go away,
312 * we need to uninstall the MAC.
313 */
314 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
315 && remote_neigh_count(mac) == 0) {
316 zebra_evpn_rem_mac_uninstall(zevpn, mac, false /*force*/);
317 zebra_evpn_es_mac_deref_entry(mac);
318 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
319 }
320
321 /* If no references, delete the MAC. */
322 if (!zebra_evpn_mac_in_use(mac))
323 zebra_evpn_mac_del(zevpn, mac);
324 }
325
326 static void zebra_evpn_mac_get_access_info(struct zebra_mac *mac,
327 struct interface **ifpP,
328 vlanid_t *vid)
329 {
330 /* if the mac is associated with an ES we must get the access
331 * info from the ES
332 */
333 if (mac->es) {
334 struct zebra_if *zif;
335
336 /* get the access port from the es */
337 *ifpP = mac->es->zif ? mac->es->zif->ifp : NULL;
338 /* get the vlan from the EVPN */
339 if (mac->zevpn->vxlan_if) {
340 zif = mac->zevpn->vxlan_if->info;
341 *vid = zif->l2info.vxl.access_vlan;
342 } else {
343 *vid = 0;
344 }
345 } else {
346 struct zebra_ns *zns;
347
348 *vid = mac->fwd_info.local.vid;
349 zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
350 *ifpP = if_lookup_by_index_per_ns(zns,
351 mac->fwd_info.local.ifindex);
352 }
353 }
354
355 #define MAC_BUF_SIZE 256
356 static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac *mac, char *buf,
357 size_t len)
358 {
359 if (mac->flags == 0) {
360 snprintfrr(buf, len, "None ");
361 return buf;
362 }
363
364 snprintfrr(
365 buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
366 CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "",
367 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "",
368 CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "",
369 CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "",
370 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router "
371 : "",
372 CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "",
373 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW "
374 : "",
375 CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "",
376 CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "",
377 CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "LOC Active "
378 : "",
379 CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "",
380 CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)
381 ? "LOC Inactive "
382 : "");
383 return buf;
384 }
385
386 static void zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)
387 {
388 struct zebra_vrf *zvrf = NULL;
389 struct zebra_mac *mac = NULL;
390 struct zebra_evpn *zevpn = NULL;
391 struct listnode *node = NULL;
392 struct zebra_neigh *nbr = NULL;
393
394 mac = THREAD_ARG(t);
395
396 /* since this is asynchronous we need sanity checks*/
397 zvrf = vrf_info_lookup(mac->zevpn->vrf_id);
398 if (!zvrf)
399 return;
400
401 zevpn = zebra_evpn_lookup(mac->zevpn->vni);
402 if (!zevpn)
403 return;
404
405 mac = zebra_evpn_mac_lookup(zevpn, &mac->macaddr);
406 if (!mac)
407 return;
408
409 if (IS_ZEBRA_DEBUG_VXLAN) {
410 char mac_buf[MAC_BUF_SIZE];
411
412 zlog_debug(
413 "%s: duplicate addr mac %pEA flags %slearn count %u host count %u auto recovery expired",
414 __func__, &mac->macaddr,
415 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
416 sizeof(mac_buf)),
417 mac->dad_count, listcount(mac->neigh_list));
418 }
419
420 /* Remove all IPs as duplicate associcated with this MAC */
421 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
422 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
423 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
424 ZEBRA_NEIGH_SET_INACTIVE(nbr);
425 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
426 zebra_evpn_rem_neigh_install(
427 zevpn, nbr, false /*was_static*/);
428 }
429
430 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
431 nbr->dad_count = 0;
432 nbr->detect_start_time.tv_sec = 0;
433 nbr->dad_dup_detect_time = 0;
434 }
435
436 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
437 mac->dad_count = 0;
438 mac->detect_start_time.tv_sec = 0;
439 mac->detect_start_time.tv_usec = 0;
440 mac->dad_dup_detect_time = 0;
441 mac->dad_mac_auto_recovery_timer = NULL;
442
443 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
444 /* Inform to BGP */
445 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
446 mac->flags, mac->loc_seq,
447 mac->es))
448 return;
449
450 /* Process all neighbors associated with this MAC. */
451 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
452 0 /*es_change*/);
453
454 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
455 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
456
457 /* Install the entry. */
458 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
459 }
460 }
461
462 static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
463 struct zebra_mac *mac,
464 struct in_addr vtep_ip,
465 bool do_dad, bool *is_dup_detect,
466 bool is_local)
467 {
468 struct zebra_neigh *nbr;
469 struct listnode *node = NULL;
470 struct timeval elapsed = {0, 0};
471 bool reset_params = false;
472
473 if (!(zebra_evpn_do_dup_addr_detect(zvrf) && do_dad))
474 return;
475
476 /* MAC is detected as duplicate,
477 * Local MAC event -> hold on advertising to BGP.
478 * Remote MAC event -> hold on installing it.
479 */
480 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
481 if (IS_ZEBRA_DEBUG_VXLAN) {
482 char mac_buf[MAC_BUF_SIZE];
483
484 zlog_debug(
485 "%s: duplicate addr MAC %pEA flags %sskip update to client, learn count %u recover time %u",
486 __func__, &mac->macaddr,
487 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
488 sizeof(mac_buf)),
489 mac->dad_count, zvrf->dad_freeze_time);
490 }
491 /* For duplicate MAC do not update
492 * client but update neigh due to
493 * this MAC update.
494 */
495 if (zvrf->dad_freeze)
496 *is_dup_detect = true;
497
498 return;
499 }
500
501 /* Check if detection time (M-secs) expired.
502 * Reset learn count and detection start time.
503 */
504 monotime_since(&mac->detect_start_time, &elapsed);
505 reset_params = (elapsed.tv_sec > zvrf->dad_time);
506 if (is_local && !reset_params) {
507 /* RFC-7432: A PE/VTEP that detects a MAC mobility
508 * event via LOCAL learning starts an M-second timer.
509 *
510 * NOTE: This is the START of the probe with count is
511 * 0 during LOCAL learn event.
512 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
513 */
514 reset_params = !mac->dad_count;
515 }
516
517 if (reset_params) {
518 if (IS_ZEBRA_DEBUG_VXLAN) {
519 char mac_buf[MAC_BUF_SIZE];
520
521 zlog_debug(
522 "%s: duplicate addr MAC %pEA flags %sdetection time passed, reset learn count %u",
523 __func__, &mac->macaddr,
524 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
525 sizeof(mac_buf)),
526 mac->dad_count);
527 }
528
529 mac->dad_count = 0;
530 /* Start dup. addr detection (DAD) start time,
531 * ONLY during LOCAL learn.
532 */
533 if (is_local)
534 monotime(&mac->detect_start_time);
535
536 } else if (!is_local) {
537 /* For REMOTE MAC, increment detection count
538 * ONLY while in probe window, once window passed,
539 * next local learn event should trigger DAD.
540 */
541 mac->dad_count++;
542 }
543
544 /* For LOCAL MAC learn event, once count is reset above via either
545 * initial/start detection time or passed the probe time, the count
546 * needs to be incremented.
547 */
548 if (is_local)
549 mac->dad_count++;
550
551 if (mac->dad_count >= zvrf->dad_max_moves) {
552 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
553 "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4",
554 mac->zevpn->vni, &mac->macaddr,
555 is_local ? "local update, last" :
556 "remote update, from", &vtep_ip);
557
558 SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
559
560 /* Capture Duplicate detection time */
561 mac->dad_dup_detect_time = monotime(NULL);
562
563 /* Mark all IPs/Neighs as duplicate
564 * associcated with this MAC
565 */
566 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
567
568 /* Ony Mark IPs which are Local */
569 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
570 continue;
571
572 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
573
574 nbr->dad_dup_detect_time = monotime(NULL);
575
576 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
577 "VNI %u: MAC %pEA IP %pIA detected as duplicate during %s update, inherit duplicate from MAC",
578 mac->zevpn->vni, &mac->macaddr, &nbr->ip,
579 is_local ? "local" : "remote");
580 }
581
582 /* Start auto recovery timer for this MAC */
583 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
584 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
585 if (IS_ZEBRA_DEBUG_VXLAN) {
586 char mac_buf[MAC_BUF_SIZE];
587
588 zlog_debug(
589 "%s: duplicate addr MAC %pEA flags %sauto recovery time %u start",
590 __func__, &mac->macaddr,
591 zebra_evpn_zebra_mac_flag_dump(
592 mac, mac_buf, sizeof(mac_buf)),
593 zvrf->dad_freeze_time);
594 }
595
596 thread_add_timer(zrouter.master,
597 zebra_evpn_dad_mac_auto_recovery_exp,
598 mac, zvrf->dad_freeze_time,
599 &mac->dad_mac_auto_recovery_timer);
600 }
601
602 /* In case of local update, do not inform to client (BGPd),
603 * upd_neigh for neigh sequence change.
604 */
605 if (zvrf->dad_freeze)
606 *is_dup_detect = true;
607 }
608 }
609
610 /*
611 * Print a specific MAC entry.
612 */
613 void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
614 {
615 struct vty *vty;
616 struct zebra_neigh *n = NULL;
617 struct listnode *node = NULL;
618 char buf1[ETHER_ADDR_STRLEN];
619 char buf2[INET6_ADDRSTRLEN];
620 struct zebra_vrf *zvrf;
621 struct timeval detect_start_time = {0, 0};
622 char timebuf[MONOTIME_STRLEN];
623 char thread_buf[THREAD_TIMER_STRLEN];
624 time_t uptime;
625 char up_str[MONOTIME_STRLEN];
626
627 zvrf = zebra_vrf_get_evpn();
628 if (!zvrf)
629 return;
630
631 vty = (struct vty *)ctxt;
632 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
633
634 uptime = monotime(NULL);
635 uptime -= mac->uptime;
636
637 frrtime_to_interval(uptime, up_str, sizeof(up_str));
638
639 if (json) {
640 json_object *json_mac = json_object_new_object();
641
642 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
643 struct interface *ifp;
644 vlanid_t vid;
645
646 zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
647 json_object_string_add(json_mac, "type", "local");
648 if (ifp) {
649 json_object_string_add(json_mac, "intf",
650 ifp->name);
651 json_object_int_add(json_mac, "ifindex",
652 ifp->ifindex);
653 }
654 if (vid)
655 json_object_int_add(json_mac, "vlan", vid);
656 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
657 json_object_string_add(json_mac, "type", "remote");
658 json_object_string_addf(json_mac, "remoteVtep", "%pI4",
659 &mac->fwd_info.r_vtep_ip);
660 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
661 json_object_string_add(json_mac, "type", "auto");
662
663 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
664 json_object_boolean_true_add(json_mac, "stickyMac");
665
666 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
667 json_object_boolean_true_add(json_mac, "sviMac");
668
669 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
670 json_object_boolean_true_add(json_mac,
671 "defaultGateway");
672
673 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
674 json_object_boolean_true_add(json_mac,
675 "remoteGatewayMac");
676
677 json_object_string_add(json_mac, "uptime", up_str);
678 json_object_int_add(json_mac, "localSequence", mac->loc_seq);
679 json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
680
681 json_object_int_add(json_mac, "detectionCount", mac->dad_count);
682 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
683 json_object_boolean_true_add(json_mac, "isDuplicate");
684 else
685 json_object_boolean_false_add(json_mac, "isDuplicate");
686
687 json_object_int_add(json_mac, "syncNeighCount",
688 mac->sync_neigh_cnt);
689 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE))
690 json_object_boolean_true_add(json_mac, "localInactive");
691 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY))
692 json_object_boolean_true_add(json_mac, "peerProxy");
693 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
694 json_object_boolean_true_add(json_mac, "peerActive");
695 if (mac->hold_timer)
696 json_object_string_add(
697 json_mac, "peerActiveHold",
698 thread_timer_to_hhmmss(thread_buf,
699 sizeof(thread_buf),
700 mac->hold_timer));
701 if (mac->es)
702 json_object_string_add(json_mac, "esi",
703 mac->es->esi_str);
704 /* print all the associated neigh */
705 if (!listcount(mac->neigh_list))
706 json_object_string_add(json_mac, "neighbors", "none");
707 else {
708 json_object *json_active_nbrs = json_object_new_array();
709 json_object *json_inactive_nbrs =
710 json_object_new_array();
711 json_object *json_nbrs = json_object_new_object();
712
713 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
714 if (IS_ZEBRA_NEIGH_ACTIVE(n))
715 json_object_array_add(
716 json_active_nbrs,
717 json_object_new_string(
718 ipaddr2str(
719 &n->ip, buf2,
720 sizeof(buf2))));
721 else
722 json_object_array_add(
723 json_inactive_nbrs,
724 json_object_new_string(
725 ipaddr2str(
726 &n->ip, buf2,
727 sizeof(buf2))));
728 }
729
730 json_object_object_add(json_nbrs, "active",
731 json_active_nbrs);
732 json_object_object_add(json_nbrs, "inactive",
733 json_inactive_nbrs);
734 json_object_object_add(json_mac, "neighbors",
735 json_nbrs);
736 }
737
738 json_object_object_add(json, buf1, json_mac);
739 } else {
740 vty_out(vty, "MAC: %s\n", buf1);
741
742 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
743 struct interface *ifp;
744 vlanid_t vid;
745
746 zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
747
748 if (mac->es)
749 vty_out(vty, " ESI: %s\n", mac->es->esi_str);
750
751 if (ifp)
752 vty_out(vty, " Intf: %s(%u)", ifp->name,
753 ifp->ifindex);
754 else
755 vty_out(vty, " Intf: -");
756 vty_out(vty, " VLAN: %u", vid);
757 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
758 if (mac->es)
759 vty_out(vty, " Remote ES: %s",
760 mac->es->esi_str);
761 else
762 vty_out(vty, " Remote VTEP: %pI4",
763 &mac->fwd_info.r_vtep_ip);
764 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
765 vty_out(vty, " Auto Mac ");
766 }
767
768 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
769 vty_out(vty, " Sticky Mac ");
770
771 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
772 vty_out(vty, " SVI-Mac ");
773
774 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
775 vty_out(vty, " Default-gateway Mac ");
776
777 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
778 vty_out(vty, " Remote-gateway Mac ");
779
780 vty_out(vty, "\n");
781 vty_out(vty, " Sync-info: neigh#: %u", mac->sync_neigh_cnt);
782 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE))
783 vty_out(vty, " local-inactive");
784 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY))
785 vty_out(vty, " peer-proxy");
786 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
787 vty_out(vty, " peer-active");
788 if (mac->hold_timer)
789 vty_out(vty, " (ht: %s)",
790 thread_timer_to_hhmmss(thread_buf,
791 sizeof(thread_buf),
792 mac->hold_timer));
793 vty_out(vty, "\n");
794 vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq,
795 mac->rem_seq);
796 vty_out(vty, " Uptime: %s\n", up_str);
797
798 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
799 vty_out(vty, " Duplicate, detected at %s",
800 time_to_string(mac->dad_dup_detect_time,
801 timebuf));
802 } else if (mac->dad_count) {
803 monotime_since(&mac->detect_start_time,
804 &detect_start_time);
805 if (detect_start_time.tv_sec <= zvrf->dad_time) {
806 time_to_string(mac->detect_start_time.tv_sec,
807 timebuf);
808 vty_out(vty,
809 " Duplicate detection started at %s, detection count %u\n",
810 timebuf, mac->dad_count);
811 }
812 }
813
814 /* print all the associated neigh */
815 vty_out(vty, " Neighbors:\n");
816 if (!listcount(mac->neigh_list))
817 vty_out(vty, " No Neighbors\n");
818 else {
819 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
820 vty_out(vty, " %s %s\n",
821 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
822 (IS_ZEBRA_NEIGH_ACTIVE(n)
823 ? "Active"
824 : "Inactive"));
825 }
826 }
827
828 vty_out(vty, "\n");
829 }
830 }
831
832 static char *zebra_evpn_print_mac_flags(struct zebra_mac *mac, char *flags_buf,
833 size_t flags_buf_sz)
834 {
835 snprintf(flags_buf, flags_buf_sz, "%s%s%s%s",
836 mac->sync_neigh_cnt ? "N" : "",
837 (mac->flags & ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "",
838 (mac->flags & ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "",
839 (mac->flags & ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : "");
840
841 return flags_buf;
842 }
843
844 /*
845 * Print MAC hash entry - called for display of all MACs.
846 */
847 void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
848 {
849 struct vty *vty;
850 json_object *json_mac_hdr = NULL, *json_mac = NULL;
851 struct zebra_mac *mac;
852 char buf1[ETHER_ADDR_STRLEN];
853 char addr_buf[PREFIX_STRLEN];
854 struct mac_walk_ctx *wctx = ctxt;
855 char flags_buf[6];
856
857 vty = wctx->vty;
858 json_mac_hdr = wctx->json;
859 mac = (struct zebra_mac *)bucket->data;
860
861 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
862
863 if (json_mac_hdr)
864 json_mac = json_object_new_object();
865
866 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
867 struct interface *ifp;
868 vlanid_t vid;
869
870 if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
871 return;
872
873 zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
874 if (json_mac_hdr == NULL) {
875 vty_out(vty, "%-17s %-6s %-5s %-30s", buf1, "local",
876 zebra_evpn_print_mac_flags(mac, flags_buf,
877 sizeof(flags_buf)),
878 ifp ? ifp->name : "-");
879 } else {
880 json_object_string_add(json_mac, "type", "local");
881 if (ifp)
882 json_object_string_add(json_mac, "intf",
883 ifp->name);
884 }
885 if (vid) {
886 if (json_mac_hdr == NULL)
887 vty_out(vty, " %-5u", vid);
888 else
889 json_object_int_add(json_mac, "vlan", vid);
890 } else /* No vid? fill out the space */
891 if (json_mac_hdr == NULL)
892 vty_out(vty, " %-5s", "");
893 if (json_mac_hdr == NULL) {
894 vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq);
895 vty_out(vty, "\n");
896 } else {
897 json_object_int_add(json_mac, "localSequence",
898 mac->loc_seq);
899 json_object_int_add(json_mac, "remoteSequence",
900 mac->rem_seq);
901 json_object_int_add(json_mac, "detectionCount",
902 mac->dad_count);
903 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
904 json_object_boolean_true_add(json_mac,
905 "isDuplicate");
906 else
907 json_object_boolean_false_add(json_mac,
908 "isDuplicate");
909 json_object_object_add(json_mac_hdr, buf1, json_mac);
910 }
911
912 wctx->count++;
913
914 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
915
916 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
917 && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
918 &wctx->r_vtep_ip))
919 return;
920
921 if (json_mac_hdr == NULL) {
922 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
923 && (wctx->count == 0)) {
924 vty_out(vty, "\nVNI %u\n\n", wctx->zevpn->vni);
925 vty_out(vty, "%-17s %-6s %-5s%-30s %-5s %s\n",
926 "MAC", "Type", "Flags",
927 "Intf/Remote ES/VTEP", "VLAN",
928 "Seq #'s");
929 }
930 if (mac->es == NULL)
931 inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip,
932 addr_buf, sizeof(addr_buf));
933
934 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %u/%u\n", buf1,
935 "remote",
936 zebra_evpn_print_mac_flags(mac, flags_buf,
937 sizeof(flags_buf)),
938 mac->es ? mac->es->esi_str : addr_buf,
939 "", mac->loc_seq, mac->rem_seq);
940 } else {
941 json_object_string_add(json_mac, "type", "remote");
942 json_object_string_addf(json_mac, "remoteVtep", "%pI4",
943 &mac->fwd_info.r_vtep_ip);
944 json_object_object_add(json_mac_hdr, buf1, json_mac);
945 json_object_int_add(json_mac, "localSequence",
946 mac->loc_seq);
947 json_object_int_add(json_mac, "remoteSequence",
948 mac->rem_seq);
949 json_object_int_add(json_mac, "detectionCount",
950 mac->dad_count);
951 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
952 json_object_boolean_true_add(json_mac,
953 "isDuplicate");
954 else
955 json_object_boolean_false_add(json_mac,
956 "isDuplicate");
957 }
958
959 wctx->count++;
960 }
961 }
962
963 /*
964 * Print MAC hash entry in detail - called for display of all MACs.
965 */
966 void zebra_evpn_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
967 {
968 struct vty *vty;
969 json_object *json_mac_hdr = NULL;
970 struct zebra_mac *mac;
971 struct mac_walk_ctx *wctx = ctxt;
972 char buf1[ETHER_ADDR_STRLEN];
973
974 vty = wctx->vty;
975 json_mac_hdr = wctx->json;
976 mac = (struct zebra_mac *)bucket->data;
977 if (!mac)
978 return;
979
980 wctx->count++;
981 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
982
983 zebra_evpn_print_mac(mac, vty, json_mac_hdr);
984 }
985
986 /*
987 * Inform BGP about local MACIP.
988 */
989 int zebra_evpn_macip_send_msg_to_client(vni_t vni,
990 const struct ethaddr *macaddr,
991 const struct ipaddr *ip, uint8_t flags,
992 uint32_t seq, int state,
993 struct zebra_evpn_es *es, uint16_t cmd)
994 {
995 int ipa_len;
996 struct zserv *client = NULL;
997 struct stream *s = NULL;
998 esi_t *esi = es ? &es->esi : zero_esi;
999
1000 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1001 /* BGP may not be running. */
1002 if (!client)
1003 return 0;
1004
1005 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1006
1007 zclient_create_header(s, cmd, zebra_vrf_get_evpn_id());
1008 stream_putl(s, vni);
1009 stream_put(s, macaddr->octet, ETH_ALEN);
1010 if (ip) {
1011 ipa_len = 0;
1012 if (IS_IPADDR_V4(ip))
1013 ipa_len = IPV4_MAX_BYTELEN;
1014 else if (IS_IPADDR_V6(ip))
1015 ipa_len = IPV6_MAX_BYTELEN;
1016
1017 stream_putl(s, ipa_len); /* IP address length */
1018 if (ipa_len)
1019 stream_put(s, &ip->ip.addr, ipa_len); /* IP address */
1020 } else
1021 stream_putl(s, 0); /* Just MAC. */
1022
1023 if (cmd == ZEBRA_MACIP_ADD) {
1024 stream_putc(s, flags); /* sticky mac/gateway mac */
1025 stream_putl(s, seq); /* sequence number */
1026 stream_put(s, esi, sizeof(esi_t));
1027 } else {
1028 stream_putl(s, state); /* state - active/inactive */
1029 }
1030
1031
1032 /* Write packet size. */
1033 stream_putw_at(s, 0, stream_get_endp(s));
1034
1035 if (IS_ZEBRA_DEBUG_VXLAN) {
1036 char flag_buf[MACIP_BUF_SIZE];
1037
1038 zlog_debug(
1039 "Send MACIP %s f %s MAC %pEA IP %pIA seq %u L2-VNI %u ESI %s to %s",
1040 (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
1041 zclient_evpn_dump_macip_flags(flags, flag_buf,
1042 sizeof(flag_buf)),
1043 macaddr, ip, seq, vni,
1044 es ? es->esi_str : "-",
1045 zebra_route_string(client->proto));
1046 }
1047
1048 if (cmd == ZEBRA_MACIP_ADD)
1049 client->macipadd_cnt++;
1050 else
1051 client->macipdel_cnt++;
1052
1053 return zserv_send_message(client, s);
1054 }
1055
1056 static unsigned int mac_hash_keymake(const void *p)
1057 {
1058 const struct zebra_mac *pmac = p;
1059 const void *pnt = (void *)pmac->macaddr.octet;
1060
1061 return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
1062 }
1063
1064 /*
1065 * Compare two MAC addresses.
1066 */
1067 static bool mac_cmp(const void *p1, const void *p2)
1068 {
1069 const struct zebra_mac *pmac1 = p1;
1070 const struct zebra_mac *pmac2 = p2;
1071
1072 if (pmac1 == NULL && pmac2 == NULL)
1073 return true;
1074
1075 if (pmac1 == NULL || pmac2 == NULL)
1076 return false;
1077
1078 return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
1079 == 0);
1080 }
1081
1082 /*
1083 * Callback to allocate MAC hash entry.
1084 */
1085 static void *zebra_evpn_mac_alloc(void *p)
1086 {
1087 const struct zebra_mac *tmp_mac = p;
1088 struct zebra_mac *mac;
1089
1090 mac = XCALLOC(MTYPE_MAC, sizeof(struct zebra_mac));
1091 *mac = *tmp_mac;
1092
1093 return ((void *)mac);
1094 }
1095
1096 /*
1097 * Add MAC entry.
1098 */
1099 struct zebra_mac *zebra_evpn_mac_add(struct zebra_evpn *zevpn,
1100 const struct ethaddr *macaddr)
1101 {
1102 struct zebra_mac tmp_mac;
1103 struct zebra_mac *mac = NULL;
1104
1105 memset(&tmp_mac, 0, sizeof(struct zebra_mac));
1106 memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
1107 mac = hash_get(zevpn->mac_table, &tmp_mac, zebra_evpn_mac_alloc);
1108 assert(mac);
1109
1110 mac->zevpn = zevpn;
1111 mac->dad_mac_auto_recovery_timer = NULL;
1112
1113 mac->neigh_list = list_new();
1114 mac->neigh_list->cmp = neigh_list_cmp;
1115
1116 mac->uptime = monotime(NULL);
1117 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1118 char mac_buf[MAC_BUF_SIZE];
1119
1120 zlog_debug("%s: MAC %pEA flags %s", __func__,
1121 &mac->macaddr,
1122 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1123 sizeof(mac_buf)));
1124 }
1125 return mac;
1126 }
1127
1128 /*
1129 * Delete MAC entry.
1130 */
1131 int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
1132 {
1133 struct zebra_mac *tmp_mac;
1134
1135 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1136 char mac_buf[MAC_BUF_SIZE];
1137
1138 zlog_debug("%s: MAC %pEA flags %s", __func__,
1139 &mac->macaddr,
1140 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1141 sizeof(mac_buf)));
1142 }
1143
1144 /* If the MAC is freed before the neigh we will end up
1145 * with a stale pointer against the neigh
1146 */
1147 if (!list_isempty(mac->neigh_list))
1148 zlog_warn("%s: MAC %pEA flags 0x%x neigh list not empty %d",
1149 __func__, &mac->macaddr, mac->flags,
1150 listcount(mac->neigh_list));
1151
1152 /* force de-ref any ES entry linked to the MAC */
1153 zebra_evpn_es_mac_deref_entry(mac);
1154
1155 /* remove links to the destination access port */
1156 zebra_evpn_mac_clear_fwd_info(mac);
1157
1158 /* Cancel proxy hold timer */
1159 zebra_evpn_mac_stop_hold_timer(mac);
1160
1161 /* Cancel auto recovery */
1162 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
1163
1164 list_delete(&mac->neigh_list);
1165
1166 /* Free the VNI hash entry and allocated memory. */
1167 tmp_mac = hash_release(zevpn->mac_table, mac);
1168 XFREE(MTYPE_MAC, tmp_mac);
1169
1170 return 0;
1171 }
1172
1173 static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
1174 struct zebra_mac *mac)
1175 {
1176 if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
1177 return true;
1178 else if ((wctx->flags & DEL_REMOTE_MAC)
1179 && (mac->flags & ZEBRA_MAC_REMOTE))
1180 return true;
1181 else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
1182 && (mac->flags & ZEBRA_MAC_REMOTE)
1183 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
1184 return true;
1185 else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO)
1186 && !listcount(mac->neigh_list)) {
1187 if (IS_ZEBRA_DEBUG_VXLAN) {
1188 char mac_buf[MAC_BUF_SIZE];
1189
1190 zlog_debug(
1191 "%s: Del MAC %pEA flags %s", __func__,
1192 &mac->macaddr,
1193 zebra_evpn_zebra_mac_flag_dump(
1194 mac, mac_buf, sizeof(mac_buf)));
1195 }
1196 wctx->uninstall = 0;
1197
1198 return true;
1199 }
1200
1201 return false;
1202 }
1203
1204 /*
1205 * Free MAC hash entry (callback)
1206 */
1207 static void zebra_evpn_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
1208 {
1209 struct mac_walk_ctx *wctx = arg;
1210 struct zebra_mac *mac = bucket->data;
1211
1212 if (zebra_evpn_check_mac_del_from_db(wctx, mac)) {
1213 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
1214 zebra_evpn_mac_send_del_to_client(wctx->zevpn->vni,
1215 &mac->macaddr,
1216 mac->flags, false);
1217 }
1218 if (wctx->uninstall) {
1219 if (zebra_evpn_mac_is_static(mac))
1220 zebra_evpn_sync_mac_dp_install(
1221 mac, false /* set_inactive */,
1222 true /* force_clear_static */,
1223 __func__);
1224
1225 if (mac->flags & ZEBRA_MAC_REMOTE)
1226 zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac,
1227 false /*force*/);
1228 }
1229
1230 zebra_evpn_mac_del(wctx->zevpn, mac);
1231 }
1232
1233 return;
1234 }
1235
1236 /*
1237 * Delete all MAC entries for this EVPN.
1238 */
1239 void zebra_evpn_mac_del_all(struct zebra_evpn *zevpn, int uninstall,
1240 int upd_client, uint32_t flags)
1241 {
1242 struct mac_walk_ctx wctx;
1243
1244 if (!zevpn->mac_table)
1245 return;
1246
1247 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
1248 wctx.zevpn = zevpn;
1249 wctx.uninstall = uninstall;
1250 wctx.upd_client = upd_client;
1251 wctx.flags = flags;
1252
1253 hash_iterate(zevpn->mac_table, zebra_evpn_mac_del_hash_entry, &wctx);
1254 }
1255
1256 /*
1257 * Look up MAC hash entry.
1258 */
1259 struct zebra_mac *zebra_evpn_mac_lookup(struct zebra_evpn *zevpn,
1260 const struct ethaddr *mac)
1261 {
1262 struct zebra_mac tmp;
1263 struct zebra_mac *pmac;
1264
1265 memset(&tmp, 0, sizeof(tmp));
1266 memcpy(&tmp.macaddr, mac, ETH_ALEN);
1267 pmac = hash_lookup(zevpn->mac_table, &tmp);
1268
1269 return pmac;
1270 }
1271
1272 /*
1273 * Inform BGP about local MAC addition.
1274 */
1275 int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
1276 uint32_t mac_flags, uint32_t seq,
1277 struct zebra_evpn_es *es)
1278 {
1279 uint8_t flags = 0;
1280
1281 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
1282 /* host reachability has not been verified locally */
1283
1284 /* if no ES peer is claiming reachability we can't advertise the
1285 * entry
1286 */
1287 if (!CHECK_FLAG(mac_flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1288 return 0;
1289
1290 /* ES peers are claiming reachability; we will
1291 * advertise the entry but with a proxy flag
1292 */
1293 SET_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT);
1294 }
1295
1296 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
1297 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
1298 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
1299 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
1300
1301 return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, flags,
1302 seq, ZEBRA_NEIGH_ACTIVE, es,
1303 ZEBRA_MACIP_ADD);
1304 }
1305
1306 /*
1307 * Inform BGP about local MAC deletion.
1308 */
1309 int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
1310 uint32_t flags, bool force)
1311 {
1312 if (!force) {
1313 if (CHECK_FLAG(flags, ZEBRA_MAC_LOCAL_INACTIVE)
1314 && !CHECK_FLAG(flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1315 /* the host was not advertised - nothing to delete */
1316 return 0;
1317 }
1318
1319 return zebra_evpn_macip_send_msg_to_client(
1320 vni, macaddr, NULL, 0 /* flags */, 0 /* seq */,
1321 ZEBRA_NEIGH_ACTIVE, NULL, ZEBRA_MACIP_DEL);
1322 }
1323
1324 /*
1325 * wrapper to create a MAC hash table
1326 */
1327 struct hash *zebra_mac_db_create(const char *desc)
1328 {
1329 return hash_create_size(8, mac_hash_keymake, mac_cmp, desc);
1330 }
1331
1332 /* program sync mac flags in the dataplane */
1333 int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
1334 bool force_clear_static, const char *caller)
1335 {
1336 struct interface *ifp;
1337 bool sticky;
1338 bool set_static;
1339 struct zebra_evpn *zevpn = mac->zevpn;
1340 vlanid_t vid;
1341 struct zebra_if *zif;
1342 struct interface *br_ifp;
1343
1344 /* If the ES-EVI doesn't exist defer install. When the ES-EVI is
1345 * created we will attempt to install the mac entry again
1346 */
1347 if (mac->es) {
1348 struct zebra_evpn_es_evi *es_evi;
1349
1350 es_evi = zebra_evpn_es_evi_find(mac->es, mac->zevpn);
1351 if (!es_evi) {
1352 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
1353 zlog_debug(
1354 "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no es-evi",
1355 caller, zevpn->vni, &mac->macaddr,
1356 mac->es ? mac->es->esi_str : "-",
1357 mac->flags,
1358 set_inactive ? "inactive " : "");
1359 return -1;
1360 }
1361 }
1362
1363 /* get the access vlan from the vxlan_device */
1364 zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
1365
1366 if (!ifp) {
1367 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1368 char mac_buf[MAC_BUF_SIZE];
1369
1370 zlog_debug(
1371 "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port",
1372 caller, zevpn->vni, &mac->macaddr,
1373 mac->es ? mac->es->esi_str : "-",
1374 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1375 sizeof(mac_buf)),
1376 set_inactive ? "inactive " : "");
1377 }
1378 return -1;
1379 }
1380
1381 zif = ifp->info;
1382 br_ifp = zif->brslave_info.br_if;
1383 if (!br_ifp) {
1384 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1385 char mac_buf[MAC_BUF_SIZE];
1386
1387 zlog_debug(
1388 "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br",
1389 caller, zevpn->vni, &mac->macaddr,
1390 mac->es ? mac->es->esi_str : "-",
1391 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1392 sizeof(mac_buf)),
1393 set_inactive ? "inactive " : "");
1394 }
1395 return -1;
1396 }
1397
1398 sticky = !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY);
1399 if (force_clear_static)
1400 set_static = false;
1401 else
1402 set_static = zebra_evpn_mac_is_static(mac);
1403
1404 /* We can install a local mac that has been synced from the peer
1405 * over the VxLAN-overlay/network-port if fast failover is not
1406 * supported and if the local ES is oper-down.
1407 */
1408 if (mac->es && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
1409 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1410 char mac_buf[MAC_BUF_SIZE];
1411
1412 zlog_debug(
1413 "dp-%s sync-nw-mac vni %u mac %pEA es %s %s%s",
1414 set_static ? "install" : "uninstall",
1415 zevpn->vni, &mac->macaddr,
1416 mac->es ? mac->es->esi_str : "-",
1417 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1418 sizeof(mac_buf)),
1419 set_inactive ? "inactive " : "");
1420 }
1421 if (set_static)
1422 /* XXX - old_static needs to be computed more
1423 * accurately
1424 */
1425 zebra_evpn_rem_mac_install(zevpn, mac,
1426 true /* old_static */);
1427 else
1428 zebra_evpn_rem_mac_uninstall(zevpn, mac,
1429 false /* force */);
1430
1431 return 0;
1432 }
1433
1434 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1435 char mac_buf[MAC_BUF_SIZE];
1436
1437 zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s",
1438 zevpn->vni, &mac->macaddr,
1439 mac->es ? mac->es->esi_str : "-",
1440 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1441 sizeof(mac_buf)),
1442 set_static ? "static " : "",
1443 set_inactive ? "inactive " : "");
1444 }
1445
1446 dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
1447 set_static, set_inactive);
1448 return 0;
1449 }
1450
1451 void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac,
1452 bool old_bgp_ready,
1453 bool new_bgp_ready)
1454 {
1455 if (new_bgp_ready)
1456 zebra_evpn_mac_send_add_to_client(mac->zevpn->vni,
1457 &mac->macaddr, mac->flags,
1458 mac->loc_seq, mac->es);
1459 else if (old_bgp_ready)
1460 zebra_evpn_mac_send_del_to_client(mac->zevpn->vni,
1461 &mac->macaddr, mac->flags,
1462 true /* force */);
1463 }
1464
1465 /* MAC hold timer is used to age out peer-active flag.
1466 *
1467 * During this wait time we expect the dataplane component or an
1468 * external neighmgr daemon to probe existing hosts to independently
1469 * establish their presence on the ES.
1470 */
1471 static void zebra_evpn_mac_hold_exp_cb(struct thread *t)
1472 {
1473 struct zebra_mac *mac;
1474 bool old_bgp_ready;
1475 bool new_bgp_ready;
1476 bool old_static;
1477 bool new_static;
1478
1479 mac = THREAD_ARG(t);
1480 /* the purpose of the hold timer is to age out the peer-active
1481 * flag
1482 */
1483 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1484 return;
1485
1486 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1487 old_static = zebra_evpn_mac_is_static(mac);
1488 UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE);
1489 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1490 new_static = zebra_evpn_mac_is_static(mac);
1491
1492 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1493 char mac_buf[MAC_BUF_SIZE];
1494
1495 zlog_debug(
1496 "sync-mac vni %u mac %pEA es %s %shold expired",
1497 mac->zevpn->vni, &mac->macaddr,
1498 mac->es ? mac->es->esi_str : "-",
1499 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1500 sizeof(mac_buf)));
1501 }
1502
1503 /* re-program the local mac in the dataplane if the mac is no
1504 * longer static
1505 */
1506 if (old_static != new_static)
1507 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
1508 false /* force_clear_static */,
1509 __func__);
1510
1511 /* inform bgp if needed */
1512 if (old_bgp_ready != new_bgp_ready)
1513 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
1514 new_bgp_ready);
1515 }
1516
1517 static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
1518 {
1519 if (mac->hold_timer)
1520 return;
1521
1522 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1523 char mac_buf[MAC_BUF_SIZE];
1524
1525 zlog_debug(
1526 "sync-mac vni %u mac %pEA es %s %shold started",
1527 mac->zevpn->vni, &mac->macaddr,
1528 mac->es ? mac->es->esi_str : "-",
1529 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1530 sizeof(mac_buf)));
1531 }
1532 thread_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac,
1533 zmh_info->mac_hold_time, &mac->hold_timer);
1534 }
1535
1536 void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac)
1537 {
1538 if (!mac->hold_timer)
1539 return;
1540
1541 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1542 char mac_buf[MAC_BUF_SIZE];
1543
1544 zlog_debug(
1545 "sync-mac vni %u mac %pEA es %s %shold stopped",
1546 mac->zevpn->vni, &mac->macaddr,
1547 mac->es ? mac->es->esi_str : "-",
1548 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1549 sizeof(mac_buf)));
1550 }
1551
1552 THREAD_OFF(mac->hold_timer);
1553 }
1554
1555 void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
1556 {
1557 bool old_static;
1558 bool new_static;
1559
1560 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1561 char mac_buf[MAC_BUF_SIZE];
1562
1563 zlog_debug(
1564 "sync-mac del vni %u mac %pEA es %s seq %d f %s",
1565 mac->zevpn->vni, &mac->macaddr,
1566 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
1567 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1568 sizeof(mac_buf)));
1569 }
1570
1571 old_static = zebra_evpn_mac_is_static(mac);
1572 UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
1573 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1574 zebra_evpn_mac_start_hold_timer(mac);
1575 new_static = zebra_evpn_mac_is_static(mac);
1576
1577 if (old_static != new_static)
1578 /* program the local mac in the kernel */
1579 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
1580 false /* force_clear_static */,
1581 __func__);
1582 }
1583
1584 static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
1585 struct zebra_mac *mac,
1586 uint32_t seq, uint16_t ipa_len,
1587 const struct ipaddr *ipaddr,
1588 bool sync)
1589 {
1590 char ipbuf[INET6_ADDRSTRLEN];
1591 uint32_t tmp_seq;
1592 const char *n_type;
1593
1594 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1595 tmp_seq = mac->loc_seq;
1596 n_type = "local";
1597 } else {
1598 tmp_seq = mac->rem_seq;
1599 n_type = "remote";
1600 }
1601
1602 if (seq < tmp_seq) {
1603 /* if the mac was never advertised to bgp we must accept
1604 * whatever sequence number bgp sends
1605 * XXX - check with Vivek
1606 */
1607 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
1608 && !zebra_evpn_mac_is_ready_for_bgp(mac->flags)) {
1609 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
1610 || IS_ZEBRA_DEBUG_VXLAN) {
1611 char mac_buf[MAC_BUF_SIZE];
1612
1613 zlog_debug(
1614 "%s-macip accept vni %u %s-mac %pEA%s%s lower seq %u f %s",
1615 sync ? "sync" : "rem", zevpn->vni,
1616 n_type,
1617 &mac->macaddr,
1618 ipa_len ? " IP " : "",
1619 ipa_len ? ipaddr2str(ipaddr, ipbuf,
1620 sizeof(ipbuf))
1621 : "",
1622 tmp_seq,
1623 zebra_evpn_zebra_mac_flag_dump(
1624 mac, mac_buf, sizeof(mac_buf)));
1625 }
1626
1627 return true;
1628 }
1629
1630 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) {
1631 char mac_buf[MAC_BUF_SIZE];
1632
1633 zlog_debug(
1634 "%s-macip ignore vni %u %s-mac %pEA%s%s as existing has higher seq %u f %s",
1635 sync ? "sync" : "rem", zevpn->vni, n_type,
1636 &mac->macaddr,
1637 ipa_len ? " IP " : "",
1638 ipa_len ? ipaddr2str(ipaddr, ipbuf,
1639 sizeof(ipbuf))
1640 : "",
1641 tmp_seq,
1642 zebra_evpn_zebra_mac_flag_dump(
1643 mac, mac_buf, sizeof(mac_buf)));
1644 }
1645 return false;
1646 }
1647
1648 return true;
1649 }
1650
1651 struct zebra_mac *zebra_evpn_proc_sync_mac_update(
1652 struct zebra_evpn *zevpn, const struct ethaddr *macaddr,
1653 uint16_t ipa_len, const struct ipaddr *ipaddr, uint8_t flags,
1654 uint32_t seq, const esi_t *esi, struct sync_mac_ip_ctx *ctx)
1655 {
1656 struct zebra_mac *mac;
1657 bool inform_bgp = false;
1658 bool inform_dataplane = false;
1659 bool seq_change = false;
1660 bool es_change = false;
1661 uint32_t tmp_seq;
1662 char ipbuf[INET6_ADDRSTRLEN];
1663 bool old_local = false;
1664 bool old_bgp_ready;
1665 bool new_bgp_ready;
1666
1667 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
1668 if (!mac) {
1669 /* if it is a new local path we need to inform both
1670 * the control protocol and the data-plane
1671 */
1672 inform_bgp = true;
1673 inform_dataplane = true;
1674 ctx->mac_created = true;
1675 ctx->mac_inactive = true;
1676
1677 /* create the MAC and associate it with the dest ES */
1678 mac = zebra_evpn_mac_add(zevpn, macaddr);
1679 zebra_evpn_es_mac_ref(mac, esi);
1680
1681 /* local mac activated by an ES peer */
1682 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
1683 /* if mac-only route setup peer flags */
1684 if (!ipa_len) {
1685 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
1686 SET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
1687 else
1688 SET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE);
1689 }
1690 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
1691 old_bgp_ready = false;
1692 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1693 } else {
1694 uint32_t old_flags;
1695 uint32_t new_flags;
1696 bool old_static;
1697 bool new_static;
1698 bool sticky;
1699 bool remote_gw;
1700
1701 mac->uptime = monotime(NULL);
1702
1703 old_flags = mac->flags;
1704 sticky = !!CHECK_FLAG(old_flags, ZEBRA_MAC_STICKY);
1705 remote_gw = !!CHECK_FLAG(old_flags, ZEBRA_MAC_REMOTE_DEF_GW);
1706 if (sticky || remote_gw) {
1707 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
1708 zlog_debug(
1709 "Ignore sync-macip vni %u mac %pEA%s%s%s%s",
1710 zevpn->vni, macaddr,
1711 ipa_len ? " IP " : "",
1712 ipa_len ? ipaddr2str(ipaddr, ipbuf,
1713 sizeof(ipbuf))
1714 : "",
1715 sticky ? " sticky" : "",
1716 remote_gw ? " remote_gw" : "");
1717 ctx->ignore_macip = true;
1718 return NULL;
1719 }
1720 if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, ipa_len,
1721 ipaddr, true)) {
1722 ctx->ignore_macip = true;
1723 return NULL;
1724 }
1725
1726 old_local = !!CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL);
1727 old_static = zebra_evpn_mac_is_static(mac);
1728
1729 /* re-build the mac flags */
1730 new_flags = 0;
1731 SET_FLAG(new_flags, ZEBRA_MAC_LOCAL);
1732 /* retain old local activity flag */
1733 if (old_flags & ZEBRA_MAC_LOCAL) {
1734 new_flags |= (old_flags & ZEBRA_MAC_LOCAL_INACTIVE);
1735 } else {
1736 new_flags |= ZEBRA_MAC_LOCAL_INACTIVE;
1737 ctx->mac_inactive = true;
1738 }
1739 if (ipa_len) {
1740 /* if mac-ip route do NOT update the peer flags
1741 * i.e. retain only flags as is
1742 */
1743 new_flags |= (old_flags & ZEBRA_MAC_ALL_PEER_FLAGS);
1744 } else {
1745 /* if mac-only route update peer flags */
1746 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
1747 SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_PROXY);
1748 /* if the mac was peer-active previously we
1749 * need to keep the flag and start the
1750 * holdtimer on it. the peer-active flag is
1751 * cleared on holdtimer expiry.
1752 */
1753 if (CHECK_FLAG(old_flags,
1754 ZEBRA_MAC_ES_PEER_ACTIVE)) {
1755 SET_FLAG(new_flags,
1756 ZEBRA_MAC_ES_PEER_ACTIVE);
1757 zebra_evpn_mac_start_hold_timer(mac);
1758 }
1759 } else {
1760 SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_ACTIVE);
1761 /* stop hold timer if a peer has verified
1762 * reachability
1763 */
1764 zebra_evpn_mac_stop_hold_timer(mac);
1765 }
1766 }
1767 mac->rem_seq = 0;
1768 zebra_evpn_mac_clear_fwd_info(mac);
1769 mac->flags = new_flags;
1770
1771 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) {
1772 char mac_buf[MAC_BUF_SIZE], omac_buf[MAC_BUF_SIZE];
1773 struct zebra_mac omac;
1774
1775 omac.flags = old_flags;
1776 zlog_debug(
1777 "sync-mac vni %u mac %pEA old_f %snew_f %s",
1778 zevpn->vni, macaddr,
1779 zebra_evpn_zebra_mac_flag_dump(
1780 &omac, omac_buf, sizeof(omac_buf)),
1781 zebra_evpn_zebra_mac_flag_dump(
1782 mac, mac_buf, sizeof(mac_buf)));
1783 }
1784
1785 /* update es */
1786 es_change = zebra_evpn_es_mac_ref(mac, esi);
1787 /* if mac dest change - inform both sides */
1788 if (es_change) {
1789 inform_bgp = true;
1790 inform_dataplane = true;
1791 ctx->mac_inactive = true;
1792 }
1793
1794 /* if peer-flag is being set notify dataplane that the
1795 * entry must not be expired because of local inactivity
1796 */
1797 new_static = zebra_evpn_mac_is_static(mac);
1798 if (old_static != new_static)
1799 inform_dataplane = true;
1800
1801 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(old_flags);
1802 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1803 if (old_bgp_ready != new_bgp_ready)
1804 inform_bgp = true;
1805 }
1806
1807
1808 /* update sequence number; if that results in a new local sequence
1809 * inform bgp
1810 */
1811 tmp_seq = MAX(mac->loc_seq, seq);
1812 if (tmp_seq != mac->loc_seq) {
1813 mac->loc_seq = tmp_seq;
1814 seq_change = true;
1815 inform_bgp = true;
1816 }
1817
1818 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1819 char mac_buf[MAC_BUF_SIZE];
1820
1821 zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s",
1822 ctx->mac_created ? "created" : "updated",
1823 zevpn->vni, macaddr,
1824 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
1825 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1826 sizeof(mac_buf)),
1827 inform_bgp ? "inform_bgp" : "",
1828 inform_dataplane ? " inform_dp" : "");
1829 }
1830
1831 if (inform_bgp)
1832 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
1833 new_bgp_ready);
1834
1835 /* neighs using the mac may need to be re-sent to
1836 * bgp with updated info
1837 */
1838 if (seq_change || es_change || !old_local)
1839 zebra_evpn_process_neigh_on_local_mac_change(
1840 zevpn, mac, seq_change, es_change);
1841
1842 if (inform_dataplane) {
1843 if (ipa_len)
1844 /* if the mac is being created as a part of MAC-IP
1845 * route wait for the neigh to be updated or
1846 * created before programming the mac
1847 */
1848 ctx->mac_dp_update_deferred = true;
1849 else
1850 /* program the local mac in the kernel. when the ES
1851 * change we need to force the dataplane to reset
1852 * the activity as we are yet to establish activity
1853 * locally
1854 */
1855 zebra_evpn_sync_mac_dp_install(
1856 mac, ctx->mac_inactive,
1857 false /* force_clear_static */, __func__);
1858 }
1859
1860 return mac;
1861 }
1862
1863 /* update local fowarding info. return true if a dest-ES change
1864 * is detected
1865 */
1866 static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac,
1867 struct interface *ifp,
1868 vlanid_t vid)
1869 {
1870 struct zebra_if *zif = ifp->info;
1871 bool es_change;
1872 ns_id_t local_ns_id = NS_DEFAULT;
1873 struct zebra_vrf *zvrf;
1874 struct zebra_evpn_es *es;
1875
1876 zvrf = ifp->vrf->info;
1877 if (zvrf && zvrf->zns)
1878 local_ns_id = zvrf->zns->ns_id;
1879
1880 zebra_evpn_mac_clear_fwd_info(mac);
1881
1882 es = zif->es_info.es;
1883 if (es && (es->flags & ZEBRA_EVPNES_BYPASS))
1884 es = NULL;
1885 es_change = zebra_evpn_es_mac_ref_entry(mac, es);
1886
1887 if (!mac->es) {
1888 /* if es is set fwd_info is not-relevant/taped-out */
1889 mac->fwd_info.local.ifindex = ifp->ifindex;
1890 mac->fwd_info.local.ns_id = local_ns_id;
1891 mac->fwd_info.local.vid = vid;
1892 zebra_evpn_mac_ifp_link(mac, ifp);
1893 }
1894
1895 return es_change;
1896 }
1897
1898 /* Notify Local MACs to the clienti, skips GW MAC */
1899 static void zebra_evpn_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
1900 void *arg)
1901 {
1902 struct mac_walk_ctx *wctx = arg;
1903 struct zebra_mac *zmac = bucket->data;
1904
1905 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_DEF_GW))
1906 return;
1907
1908 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
1909 zebra_evpn_mac_send_add_to_client(wctx->zevpn->vni,
1910 &zmac->macaddr, zmac->flags,
1911 zmac->loc_seq, zmac->es);
1912 }
1913
1914 /* Iterator to Notify Local MACs of a EVPN */
1915 void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevpn)
1916 {
1917 struct mac_walk_ctx wctx;
1918
1919 if (!zevpn->mac_table)
1920 return;
1921
1922 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
1923 wctx.zevpn = zevpn;
1924
1925 hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client,
1926 &wctx);
1927 }
1928
1929 void zebra_evpn_rem_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
1930 {
1931 zebra_evpn_process_neigh_on_remote_mac_del(zevpn, mac);
1932 /* the remote sequence number in the auto mac entry
1933 * needs to be reset to 0 as the mac entry may have
1934 * been removed on all VTEPs (including
1935 * the originating one)
1936 */
1937 mac->rem_seq = 0;
1938
1939 /* If all remote neighbors referencing a remote MAC
1940 * go away, we need to uninstall the MAC.
1941 */
1942 if (remote_neigh_count(mac) == 0) {
1943 zebra_evpn_rem_mac_uninstall(zevpn, mac, false /*force*/);
1944 zebra_evpn_es_mac_deref_entry(mac);
1945 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
1946 }
1947
1948 if (list_isempty(mac->neigh_list))
1949 zebra_evpn_mac_del(zevpn, mac);
1950 else
1951 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
1952 }
1953
1954 /* Print Duplicate MAC */
1955 void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
1956 {
1957 struct zebra_mac *mac;
1958
1959 mac = (struct zebra_mac *)bucket->data;
1960 if (!mac)
1961 return;
1962
1963 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1964 zebra_evpn_print_mac_hash(bucket, ctxt);
1965 }
1966
1967 /* Print Duplicate MAC in detail */
1968 void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
1969 void *ctxt)
1970 {
1971 struct zebra_mac *mac;
1972
1973 mac = (struct zebra_mac *)bucket->data;
1974 if (!mac)
1975 return;
1976
1977 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1978 zebra_evpn_print_mac_hash_detail(bucket, ctxt);
1979 }
1980
1981 int zebra_evpn_mac_remote_macip_add(
1982 struct zebra_evpn *zevpn, struct zebra_vrf *zvrf,
1983 const struct ethaddr *macaddr, uint16_t ipa_len,
1984 const struct ipaddr *ipaddr, struct zebra_mac **macp,
1985 struct in_addr vtep_ip, uint8_t flags, uint32_t seq, const esi_t *esi)
1986 {
1987 char buf1[INET6_ADDRSTRLEN];
1988 bool sticky;
1989 bool remote_gw;
1990 int update_mac = 0;
1991 bool do_dad = false;
1992 bool is_dup_detect = false;
1993 esi_t *old_esi;
1994 bool old_static = false;
1995 struct zebra_mac *mac;
1996 bool old_es_present;
1997 bool new_es_present;
1998
1999 sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
2000 remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2001
2002 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
2003
2004 /* Ignore if the mac is already present as a gateway mac */
2005 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)
2006 && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
2007 if (IS_ZEBRA_DEBUG_VXLAN)
2008 zlog_debug(
2009 "Ignore remote MACIP ADD VNI %u MAC %pEA%s%s as MAC is already configured as gateway MAC",
2010 zevpn->vni, macaddr,
2011 ipa_len ? " IP " : "",
2012 ipa_len ? ipaddr2str(ipaddr, buf1, sizeof(buf1))
2013 : "");
2014 return -1;
2015 }
2016
2017 old_esi = (mac && mac->es) ? &mac->es->esi : zero_esi;
2018
2019 /* check if the remote MAC is unknown or has a change.
2020 * If so, that needs to be updated first. Note that client could
2021 * install MAC and MACIP separately or just install the latter.
2022 */
2023 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
2024 || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
2025 || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
2026 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
2027 || memcmp(old_esi, esi, sizeof(esi_t)) || seq != mac->rem_seq)
2028 update_mac = 1;
2029
2030 if (update_mac) {
2031 if (!mac) {
2032 mac = zebra_evpn_mac_add(zevpn, macaddr);
2033 zebra_evpn_es_mac_ref(mac, esi);
2034
2035 /* Is this MAC created for a MACIP? */
2036 if (ipa_len)
2037 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2038 } else {
2039 /* When host moves but changes its (MAC,IP)
2040 * binding, BGP may install a MACIP entry that
2041 * corresponds to "older" location of the host
2042 * in transient situations (because {IP1,M1}
2043 * is a different route from {IP1,M2}). Check
2044 * the sequence number and ignore this update
2045 * if appropriate.
2046 */
2047 if (!zebra_evpn_mac_is_bgp_seq_ok(
2048 zevpn, mac, seq, ipa_len, ipaddr, false))
2049 return -1;
2050
2051 old_es_present = !!mac->es;
2052 zebra_evpn_es_mac_ref(mac, esi);
2053 new_es_present = !!mac->es;
2054 /* XXX - dataplane is curently not able to handle a MAC
2055 * replace if the destination changes from L2-NHG to
2056 * single VTEP and vice-versa. So delete the old entry
2057 * and re-install
2058 */
2059 if (old_es_present != new_es_present)
2060 zebra_evpn_rem_mac_uninstall(zevpn, mac, false);
2061 }
2062
2063 /* Check MAC's curent state is local (this is the case
2064 * where MAC has moved from L->R) and check previous
2065 * detection started via local learning.
2066 * RFC-7432: A PE/VTEP that detects a MAC mobility
2067 * event via local learning starts an M-second timer.
2068 *
2069 * VTEP-IP or seq. change alone is not considered
2070 * for dup. detection.
2071 *
2072 * MAC is already marked duplicate set dad, then
2073 * is_dup_detect will be set to not install the entry.
2074 */
2075 if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
2076 && mac->dad_count)
2077 || CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
2078 do_dad = true;
2079
2080 /* Remove local MAC from BGP. */
2081 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
2082 /* force drop the sync flags */
2083 old_static = zebra_evpn_mac_is_static(mac);
2084 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2085 char mac_buf[MAC_BUF_SIZE];
2086
2087 zlog_debug(
2088 "sync-mac->remote vni %u mac %pEA es %s seq %d f %s",
2089 zevpn->vni, macaddr,
2090 mac->es ? mac->es->esi_str : "-",
2091 mac->loc_seq,
2092 zebra_evpn_zebra_mac_flag_dump(
2093 mac, mac_buf, sizeof(mac_buf)));
2094 }
2095
2096 zebra_evpn_mac_clear_sync_info(mac);
2097 zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr,
2098 mac->flags,
2099 false /* force */);
2100 }
2101
2102 /* Set "auto" and "remote" forwarding info. */
2103 zebra_evpn_mac_clear_fwd_info(mac);
2104 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
2105 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
2106 mac->fwd_info.r_vtep_ip = vtep_ip;
2107
2108 if (sticky)
2109 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2110 else
2111 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2112
2113 if (remote_gw)
2114 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
2115 else
2116 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
2117
2118 zebra_evpn_dup_addr_detect_for_mac(
2119 zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad,
2120 &is_dup_detect, false);
2121
2122 if (!is_dup_detect) {
2123 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
2124 /* Install the entry. */
2125 zebra_evpn_rem_mac_install(zevpn, mac, old_static);
2126 }
2127 }
2128
2129 /* Update seq number. */
2130 mac->rem_seq = seq;
2131
2132 /* If there is no IP, return after clearing AUTO flag of MAC. */
2133 if (!ipa_len) {
2134 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2135 return -1;
2136 }
2137 *macp = mac;
2138 return 0;
2139 }
2140
2141 int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
2142 struct zebra_evpn *zevpn,
2143 struct interface *ifp,
2144 const struct ethaddr *macaddr, vlanid_t vid,
2145 bool sticky, bool local_inactive,
2146 bool dp_static, struct zebra_mac *mac)
2147 {
2148 bool mac_sticky = false;
2149 bool inform_client = false;
2150 bool upd_neigh = false;
2151 bool is_dup_detect = false;
2152 struct in_addr vtep_ip = {.s_addr = 0};
2153 bool es_change = false;
2154 bool new_bgp_ready;
2155 /* assume inactive if not present or if not local */
2156 bool old_local_inactive = true;
2157 bool old_bgp_ready = false;
2158 bool inform_dataplane = false;
2159 bool new_static = false;
2160
2161 assert(ifp);
2162 /* Check if we need to create or update or it is a NO-OP. */
2163 if (!mac)
2164 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
2165 if (!mac) {
2166 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2167 zlog_debug(
2168 "ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s",
2169 sticky ? "sticky " : "", macaddr,
2170 ifp->name, ifp->ifindex, vid, zevpn->vni,
2171 local_inactive ? " local-inactive" : "");
2172
2173 mac = zebra_evpn_mac_add(zevpn, macaddr);
2174 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2175 es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
2176 if (sticky)
2177 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2178 inform_client = true;
2179 } else {
2180 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2181 char mac_buf[MAC_BUF_SIZE];
2182
2183 zlog_debug(
2184 "UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s",
2185 sticky ? "sticky " : "", macaddr,
2186 ifp->name, ifp->ifindex, vid, zevpn->vni,
2187 local_inactive ? "local-inactive " : "",
2188 zebra_evpn_zebra_mac_flag_dump(
2189 mac, mac_buf, sizeof(mac_buf)));
2190 }
2191
2192 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
2193 struct interface *old_ifp;
2194 vlanid_t old_vid;
2195 bool old_static;
2196
2197 zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
2198 old_bgp_ready =
2199 zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2200 old_local_inactive =
2201 !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
2202 old_static = zebra_evpn_mac_is_static(mac);
2203 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
2204 mac_sticky = true;
2205 es_change = zebra_evpn_local_mac_update_fwd_info(
2206 mac, ifp, vid);
2207
2208 /*
2209 * Update any changes and if changes are relevant to
2210 * BGP, note it.
2211 */
2212 if (mac_sticky == sticky && old_ifp == ifp
2213 && old_vid == vid
2214 && old_local_inactive == local_inactive
2215 && dp_static == old_static && !es_change) {
2216 if (IS_ZEBRA_DEBUG_VXLAN)
2217 zlog_debug(
2218 " Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
2219 "entry exists and has not changed ",
2220 sticky ? "sticky " : "",
2221 macaddr, ifp->name,
2222 ifp->ifindex, vid, zevpn->vni,
2223 local_inactive
2224 ? " local_inactive"
2225 : "");
2226 return 0;
2227 }
2228 if (mac_sticky != sticky) {
2229 if (sticky)
2230 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2231 else
2232 UNSET_FLAG(mac->flags,
2233 ZEBRA_MAC_STICKY);
2234 inform_client = true;
2235 }
2236
2237 /* If an es_change is detected we need to advertise
2238 * the route with a sequence that is one
2239 * greater. This is need to indicate a mac-move
2240 * to the ES peers
2241 */
2242 if (es_change) {
2243 /* update the sequence number only if the entry
2244 * is locally active
2245 */
2246 if (!local_inactive)
2247 mac->loc_seq = mac->loc_seq + 1;
2248 /* force drop the peer/sync info as it is
2249 * simply no longer relevant
2250 */
2251 if (CHECK_FLAG(mac->flags,
2252 ZEBRA_MAC_ALL_PEER_FLAGS)) {
2253 zebra_evpn_mac_clear_sync_info(mac);
2254 new_static =
2255 zebra_evpn_mac_is_static(mac);
2256 /* if we clear peer-flags we
2257 * also need to notify the dataplane
2258 * to drop the static flag
2259 */
2260 if (old_static != new_static)
2261 inform_dataplane = true;
2262 }
2263 }
2264 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
2265 || CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
2266 bool do_dad = false;
2267
2268 /*
2269 * MAC has either moved or was "internally" created due
2270 * to a neighbor learn and is now actually learnt. If
2271 * it was learnt as a remote sticky MAC, this is an
2272 * operator error.
2273 */
2274 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
2275 flog_warn(
2276 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
2277 "MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
2278 macaddr,
2279 &mac->fwd_info.r_vtep_ip,
2280 zevpn->vni);
2281 return 0;
2282 }
2283
2284 /* If an actual move, compute MAC's seq number */
2285 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
2286 mac->loc_seq =
2287 MAX(mac->rem_seq + 1, mac->loc_seq);
2288 vtep_ip = mac->fwd_info.r_vtep_ip;
2289 /* Trigger DAD for remote MAC */
2290 do_dad = true;
2291 }
2292
2293 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
2294 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2295 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2296 es_change = zebra_evpn_local_mac_update_fwd_info(
2297 mac, ifp, vid);
2298 if (sticky)
2299 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2300 else
2301 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2302 /*
2303 * We have to inform BGP of this MAC as well as process
2304 * all neighbors.
2305 */
2306 inform_client = true;
2307 upd_neigh = true;
2308
2309 zebra_evpn_dup_addr_detect_for_mac(
2310 zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
2311 true);
2312 if (is_dup_detect) {
2313 inform_client = false;
2314 upd_neigh = false;
2315 es_change = false;
2316 }
2317 }
2318 }
2319
2320 /* if the dataplane thinks the entry is sync but it is
2321 * not sync in zebra (or vice-versa) we need to re-install
2322 * to fixup
2323 */
2324 new_static = zebra_evpn_mac_is_static(mac);
2325 if (dp_static != new_static)
2326 inform_dataplane = true;
2327
2328 if (local_inactive)
2329 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
2330 else
2331 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
2332
2333 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2334 /* if local-activity has changed we need update bgp
2335 * even if bgp already knows about the mac
2336 */
2337 if ((old_local_inactive != local_inactive)
2338 || (new_bgp_ready != old_bgp_ready)) {
2339 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2340 char mac_buf[MAC_BUF_SIZE];
2341
2342 zlog_debug(
2343 "local mac vni %u mac %pEA es %s seq %d f %s%s",
2344 zevpn->vni, macaddr,
2345 mac->es ? mac->es->esi_str : "", mac->loc_seq,
2346 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
2347 sizeof(mac_buf)),
2348 local_inactive ? "local-inactive" : "");
2349 }
2350
2351 if (!is_dup_detect)
2352 inform_client = true;
2353 }
2354
2355 if (es_change) {
2356 inform_client = true;
2357 upd_neigh = true;
2358 }
2359
2360 /* Inform dataplane if required. */
2361 if (inform_dataplane)
2362 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
2363 false /* force_clear_static */,
2364 __func__);
2365
2366 /* Inform BGP if required. */
2367 if (inform_client)
2368 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
2369 new_bgp_ready);
2370
2371 /* Process all neighbors associated with this MAC, if required. */
2372 if (upd_neigh)
2373 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
2374 es_change);
2375
2376 return 0;
2377 }
2378
2379 int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac,
2380 bool clear_static)
2381 {
2382 bool old_bgp_ready;
2383 bool new_bgp_ready;
2384
2385 if (IS_ZEBRA_DEBUG_VXLAN)
2386 zlog_debug("DEL MAC %pEA VNI %u seq %u flags 0x%x nbr count %u",
2387 &mac->macaddr, zevpn->vni, mac->loc_seq, mac->flags,
2388 listcount(mac->neigh_list));
2389
2390 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2391 if (!clear_static && zebra_evpn_mac_is_static(mac)) {
2392 /* this is a synced entry and can only be removed when the
2393 * es-peers stop advertising it.
2394 */
2395 zebra_evpn_mac_clear_fwd_info(mac);
2396
2397 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2398 char mac_buf[MAC_BUF_SIZE];
2399
2400 zlog_debug(
2401 "re-add sync-mac vni %u mac %pEA es %s seq %d f %s",
2402 zevpn->vni, &mac->macaddr,
2403 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
2404 zebra_evpn_zebra_mac_flag_dump(
2405 mac, mac_buf, sizeof(mac_buf)));
2406 }
2407
2408 /* inform-bgp about change in local-activity if any */
2409 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
2410 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
2411 new_bgp_ready =
2412 zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2413 zebra_evpn_mac_send_add_del_to_client(
2414 mac, old_bgp_ready, new_bgp_ready);
2415 }
2416
2417 /* re-install the inactive entry in the kernel */
2418 zebra_evpn_sync_mac_dp_install(mac, true /* set_inactive */,
2419 false /* force_clear_static */,
2420 __func__);
2421
2422 return 0;
2423 }
2424
2425 /* flush the peer info */
2426 zebra_evpn_mac_clear_sync_info(mac);
2427
2428 /* Update all the neigh entries associated with this mac */
2429 zebra_evpn_process_neigh_on_local_mac_del(zevpn, mac);
2430
2431 /* Remove MAC from BGP. */
2432 zebra_evpn_mac_send_del_to_client(zevpn->vni, &mac->macaddr, mac->flags,
2433 false /* force */);
2434
2435 zebra_evpn_es_mac_deref_entry(mac);
2436
2437 /* remove links to the destination access port */
2438 zebra_evpn_mac_clear_fwd_info(mac);
2439
2440 /*
2441 * If there are no neigh associated with the mac delete the mac
2442 * else mark it as AUTO for forward reference
2443 */
2444 if (!listcount(mac->neigh_list)) {
2445 zebra_evpn_mac_del(zevpn, mac);
2446 } else {
2447 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
2448 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2449 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2450 }
2451
2452 return 0;
2453 }
2454
2455 int zebra_evpn_mac_gw_macip_add(struct interface *ifp, struct zebra_evpn *zevpn,
2456 const struct ipaddr *ip,
2457 struct zebra_mac **macp,
2458 const struct ethaddr *macaddr, vlanid_t vlan_id,
2459 bool def_gw)
2460 {
2461 struct zebra_mac *mac;
2462 ns_id_t local_ns_id = NS_DEFAULT;
2463 struct zebra_vrf *zvrf;
2464
2465 zvrf = ifp->vrf->info;
2466 if (zvrf && zvrf->zns)
2467 local_ns_id = zvrf->zns->ns_id;
2468
2469 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
2470 if (!mac)
2471 mac = zebra_evpn_mac_add(zevpn, macaddr);
2472
2473 /* Set "local" forwarding info. */
2474 zebra_evpn_mac_clear_fwd_info(mac);
2475 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2476 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2477 if (def_gw)
2478 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
2479 mac->fwd_info.local.ifindex = ifp->ifindex;
2480 mac->fwd_info.local.ns_id = local_ns_id;
2481 mac->fwd_info.local.vid = vlan_id;
2482
2483 *macp = mac;
2484
2485 return 0;
2486 }
2487
2488 void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
2489 {
2490 struct zebra_mac *mac;
2491 struct ethaddr macaddr;
2492 bool old_bgp_ready;
2493
2494 if (!zebra_evpn_mh_do_adv_svi_mac())
2495 return;
2496
2497 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2498 mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
2499 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI)) {
2500 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2501 zlog_debug("SVI %s mac free", ifp->name);
2502
2503 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2504 UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI);
2505 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
2506 false);
2507 zebra_evpn_deref_ip2mac(mac->zevpn, mac);
2508 }
2509 }
2510
2511 void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
2512 {
2513 struct zebra_mac *mac = NULL;
2514 struct ethaddr macaddr;
2515 struct zebra_if *zif = ifp->info;
2516 bool old_bgp_ready;
2517 bool new_bgp_ready;
2518
2519 if (!zebra_evpn_mh_do_adv_svi_mac()
2520 || !zebra_evpn_send_to_client_ok(zevpn))
2521 return;
2522
2523 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2524
2525 /* dup check */
2526 mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
2527 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
2528 return;
2529
2530 /* add/update mac */
2531 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2532 zlog_debug("SVI %s mac add", zif->ifp->name);
2533
2534 old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags))
2535 ? true
2536 : false;
2537
2538 mac = NULL;
2539 zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
2540 if (mac)
2541 SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
2542
2543 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2544 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
2545 new_bgp_ready);
2546 }