]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_evpn_mac.c
Merge pull request #10953 from leonshaw/fix/bgp-rm-leak
[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 /* force de-ref any ES entry linked to the MAC */
1145 zebra_evpn_es_mac_deref_entry(mac);
1146
1147 /* remove links to the destination access port */
1148 zebra_evpn_mac_clear_fwd_info(mac);
1149
1150 /* Cancel proxy hold timer */
1151 zebra_evpn_mac_stop_hold_timer(mac);
1152
1153 /* Cancel auto recovery */
1154 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
1155
1156 /* If the MAC is freed before the neigh we will end up
1157 * with a stale pointer against the neigh.
1158 * The situation can arise when a MAC is in remote state
1159 * and its associated neigh is local state.
1160 * zebra_evpn_cfg_cleanup() cleans up remote neighs and MACs.
1161 * Instead of deleting remote MAC, if its neigh list is non-empty
1162 * (associated to local neighs), mark the MAC as AUTO.
1163 */
1164 if (!list_isempty(mac->neigh_list)) {
1165 if (IS_ZEBRA_DEBUG_VXLAN)
1166 zlog_debug(
1167 "MAC %pEA (flags 0x%x vni %u) has non-empty neigh list "
1168 "count %u, mark MAC as AUTO",
1169 &mac->macaddr, mac->flags, zevpn->vni,
1170 listcount(mac->neigh_list));
1171
1172 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
1173 return 0;
1174 }
1175
1176 list_delete(&mac->neigh_list);
1177
1178 /* Free the VNI hash entry and allocated memory. */
1179 tmp_mac = hash_release(zevpn->mac_table, mac);
1180 XFREE(MTYPE_MAC, tmp_mac);
1181
1182 return 0;
1183 }
1184
1185 static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
1186 struct zebra_mac *mac)
1187 {
1188 if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
1189 return true;
1190 else if ((wctx->flags & DEL_REMOTE_MAC)
1191 && (mac->flags & ZEBRA_MAC_REMOTE))
1192 return true;
1193 else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
1194 && (mac->flags & ZEBRA_MAC_REMOTE)
1195 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
1196 return true;
1197 else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO)
1198 && !listcount(mac->neigh_list)) {
1199 if (IS_ZEBRA_DEBUG_VXLAN) {
1200 char mac_buf[MAC_BUF_SIZE];
1201
1202 zlog_debug(
1203 "%s: Del MAC %pEA flags %s", __func__,
1204 &mac->macaddr,
1205 zebra_evpn_zebra_mac_flag_dump(
1206 mac, mac_buf, sizeof(mac_buf)));
1207 }
1208 wctx->uninstall = 0;
1209
1210 return true;
1211 }
1212
1213 return false;
1214 }
1215
1216 /*
1217 * Free MAC hash entry (callback)
1218 */
1219 static void zebra_evpn_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
1220 {
1221 struct mac_walk_ctx *wctx = arg;
1222 struct zebra_mac *mac = bucket->data;
1223
1224 if (zebra_evpn_check_mac_del_from_db(wctx, mac)) {
1225 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
1226 zebra_evpn_mac_send_del_to_client(wctx->zevpn->vni,
1227 &mac->macaddr,
1228 mac->flags, false);
1229 }
1230 if (wctx->uninstall) {
1231 if (zebra_evpn_mac_is_static(mac))
1232 zebra_evpn_sync_mac_dp_install(
1233 mac, false /* set_inactive */,
1234 true /* force_clear_static */,
1235 __func__);
1236
1237 if (mac->flags & ZEBRA_MAC_REMOTE)
1238 zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac,
1239 false /*force*/);
1240 }
1241
1242 zebra_evpn_mac_del(wctx->zevpn, mac);
1243 }
1244
1245 return;
1246 }
1247
1248 /*
1249 * Delete all MAC entries for this EVPN.
1250 */
1251 void zebra_evpn_mac_del_all(struct zebra_evpn *zevpn, int uninstall,
1252 int upd_client, uint32_t flags)
1253 {
1254 struct mac_walk_ctx wctx;
1255
1256 if (!zevpn->mac_table)
1257 return;
1258
1259 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
1260 wctx.zevpn = zevpn;
1261 wctx.uninstall = uninstall;
1262 wctx.upd_client = upd_client;
1263 wctx.flags = flags;
1264
1265 hash_iterate(zevpn->mac_table, zebra_evpn_mac_del_hash_entry, &wctx);
1266 }
1267
1268 /*
1269 * Look up MAC hash entry.
1270 */
1271 struct zebra_mac *zebra_evpn_mac_lookup(struct zebra_evpn *zevpn,
1272 const struct ethaddr *mac)
1273 {
1274 struct zebra_mac tmp;
1275 struct zebra_mac *pmac;
1276
1277 memset(&tmp, 0, sizeof(tmp));
1278 memcpy(&tmp.macaddr, mac, ETH_ALEN);
1279 pmac = hash_lookup(zevpn->mac_table, &tmp);
1280
1281 return pmac;
1282 }
1283
1284 /*
1285 * Inform BGP about local MAC addition.
1286 */
1287 int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
1288 uint32_t mac_flags, uint32_t seq,
1289 struct zebra_evpn_es *es)
1290 {
1291 uint8_t flags = 0;
1292
1293 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
1294 /* host reachability has not been verified locally */
1295
1296 /* if no ES peer is claiming reachability we can't advertise the
1297 * entry
1298 */
1299 if (!CHECK_FLAG(mac_flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1300 return 0;
1301
1302 /* ES peers are claiming reachability; we will
1303 * advertise the entry but with a proxy flag
1304 */
1305 SET_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT);
1306 }
1307
1308 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
1309 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
1310 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
1311 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
1312
1313 return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, flags,
1314 seq, ZEBRA_NEIGH_ACTIVE, es,
1315 ZEBRA_MACIP_ADD);
1316 }
1317
1318 /*
1319 * Inform BGP about local MAC deletion.
1320 */
1321 int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
1322 uint32_t flags, bool force)
1323 {
1324 if (!force) {
1325 if (CHECK_FLAG(flags, ZEBRA_MAC_LOCAL_INACTIVE)
1326 && !CHECK_FLAG(flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1327 /* the host was not advertised - nothing to delete */
1328 return 0;
1329 }
1330
1331 return zebra_evpn_macip_send_msg_to_client(
1332 vni, macaddr, NULL, 0 /* flags */, 0 /* seq */,
1333 ZEBRA_NEIGH_ACTIVE, NULL, ZEBRA_MACIP_DEL);
1334 }
1335
1336 /*
1337 * wrapper to create a MAC hash table
1338 */
1339 struct hash *zebra_mac_db_create(const char *desc)
1340 {
1341 return hash_create_size(8, mac_hash_keymake, mac_cmp, desc);
1342 }
1343
1344 /* program sync mac flags in the dataplane */
1345 int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
1346 bool force_clear_static, const char *caller)
1347 {
1348 struct interface *ifp;
1349 bool sticky;
1350 bool set_static;
1351 struct zebra_evpn *zevpn = mac->zevpn;
1352 vlanid_t vid;
1353 struct zebra_if *zif;
1354 struct interface *br_ifp;
1355
1356 /* If the ES-EVI doesn't exist defer install. When the ES-EVI is
1357 * created we will attempt to install the mac entry again
1358 */
1359 if (mac->es) {
1360 struct zebra_evpn_es_evi *es_evi;
1361
1362 es_evi = zebra_evpn_es_evi_find(mac->es, mac->zevpn);
1363 if (!es_evi) {
1364 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
1365 zlog_debug(
1366 "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no es-evi",
1367 caller, zevpn->vni, &mac->macaddr,
1368 mac->es ? mac->es->esi_str : "-",
1369 mac->flags,
1370 set_inactive ? "inactive " : "");
1371 return -1;
1372 }
1373 }
1374
1375 /* get the access vlan from the vxlan_device */
1376 zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
1377
1378 if (!ifp) {
1379 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1380 char mac_buf[MAC_BUF_SIZE];
1381
1382 zlog_debug(
1383 "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port",
1384 caller, zevpn->vni, &mac->macaddr,
1385 mac->es ? mac->es->esi_str : "-",
1386 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1387 sizeof(mac_buf)),
1388 set_inactive ? "inactive " : "");
1389 }
1390 return -1;
1391 }
1392
1393 zif = ifp->info;
1394 br_ifp = zif->brslave_info.br_if;
1395 if (!br_ifp) {
1396 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1397 char mac_buf[MAC_BUF_SIZE];
1398
1399 zlog_debug(
1400 "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br",
1401 caller, zevpn->vni, &mac->macaddr,
1402 mac->es ? mac->es->esi_str : "-",
1403 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1404 sizeof(mac_buf)),
1405 set_inactive ? "inactive " : "");
1406 }
1407 return -1;
1408 }
1409
1410 sticky = !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY);
1411 if (force_clear_static)
1412 set_static = false;
1413 else
1414 set_static = zebra_evpn_mac_is_static(mac);
1415
1416 /* We can install a local mac that has been synced from the peer
1417 * over the VxLAN-overlay/network-port if fast failover is not
1418 * supported and if the local ES is oper-down.
1419 */
1420 if (mac->es && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
1421 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1422 char mac_buf[MAC_BUF_SIZE];
1423
1424 zlog_debug(
1425 "dp-%s sync-nw-mac vni %u mac %pEA es %s %s%s",
1426 set_static ? "install" : "uninstall",
1427 zevpn->vni, &mac->macaddr,
1428 mac->es ? mac->es->esi_str : "-",
1429 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1430 sizeof(mac_buf)),
1431 set_inactive ? "inactive " : "");
1432 }
1433 if (set_static)
1434 /* XXX - old_static needs to be computed more
1435 * accurately
1436 */
1437 zebra_evpn_rem_mac_install(zevpn, mac,
1438 true /* old_static */);
1439 else
1440 zebra_evpn_rem_mac_uninstall(zevpn, mac,
1441 false /* force */);
1442
1443 return 0;
1444 }
1445
1446 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1447 char mac_buf[MAC_BUF_SIZE];
1448
1449 zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s",
1450 zevpn->vni, &mac->macaddr,
1451 mac->es ? mac->es->esi_str : "-",
1452 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1453 sizeof(mac_buf)),
1454 set_static ? "static " : "",
1455 set_inactive ? "inactive " : "");
1456 }
1457
1458 dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
1459 set_static, set_inactive);
1460 return 0;
1461 }
1462
1463 void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac,
1464 bool old_bgp_ready,
1465 bool new_bgp_ready)
1466 {
1467 if (new_bgp_ready)
1468 zebra_evpn_mac_send_add_to_client(mac->zevpn->vni,
1469 &mac->macaddr, mac->flags,
1470 mac->loc_seq, mac->es);
1471 else if (old_bgp_ready)
1472 zebra_evpn_mac_send_del_to_client(mac->zevpn->vni,
1473 &mac->macaddr, mac->flags,
1474 true /* force */);
1475 }
1476
1477 /* MAC hold timer is used to age out peer-active flag.
1478 *
1479 * During this wait time we expect the dataplane component or an
1480 * external neighmgr daemon to probe existing hosts to independently
1481 * establish their presence on the ES.
1482 */
1483 static void zebra_evpn_mac_hold_exp_cb(struct thread *t)
1484 {
1485 struct zebra_mac *mac;
1486 bool old_bgp_ready;
1487 bool new_bgp_ready;
1488 bool old_static;
1489 bool new_static;
1490
1491 mac = THREAD_ARG(t);
1492 /* the purpose of the hold timer is to age out the peer-active
1493 * flag
1494 */
1495 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1496 return;
1497
1498 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1499 old_static = zebra_evpn_mac_is_static(mac);
1500 UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE);
1501 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1502 new_static = zebra_evpn_mac_is_static(mac);
1503
1504 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1505 char mac_buf[MAC_BUF_SIZE];
1506
1507 zlog_debug(
1508 "sync-mac vni %u mac %pEA es %s %shold expired",
1509 mac->zevpn->vni, &mac->macaddr,
1510 mac->es ? mac->es->esi_str : "-",
1511 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1512 sizeof(mac_buf)));
1513 }
1514
1515 /* re-program the local mac in the dataplane if the mac is no
1516 * longer static
1517 */
1518 if (old_static != new_static)
1519 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
1520 false /* force_clear_static */,
1521 __func__);
1522
1523 /* inform bgp if needed */
1524 if (old_bgp_ready != new_bgp_ready)
1525 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
1526 new_bgp_ready);
1527 }
1528
1529 static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
1530 {
1531 if (mac->hold_timer)
1532 return;
1533
1534 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1535 char mac_buf[MAC_BUF_SIZE];
1536
1537 zlog_debug(
1538 "sync-mac vni %u mac %pEA es %s %shold started",
1539 mac->zevpn->vni, &mac->macaddr,
1540 mac->es ? mac->es->esi_str : "-",
1541 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1542 sizeof(mac_buf)));
1543 }
1544 thread_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac,
1545 zmh_info->mac_hold_time, &mac->hold_timer);
1546 }
1547
1548 void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac)
1549 {
1550 if (!mac->hold_timer)
1551 return;
1552
1553 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1554 char mac_buf[MAC_BUF_SIZE];
1555
1556 zlog_debug(
1557 "sync-mac vni %u mac %pEA es %s %shold stopped",
1558 mac->zevpn->vni, &mac->macaddr,
1559 mac->es ? mac->es->esi_str : "-",
1560 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1561 sizeof(mac_buf)));
1562 }
1563
1564 THREAD_OFF(mac->hold_timer);
1565 }
1566
1567 void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
1568 {
1569 bool old_static;
1570 bool new_static;
1571
1572 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1573 char mac_buf[MAC_BUF_SIZE];
1574
1575 zlog_debug(
1576 "sync-mac del vni %u mac %pEA es %s seq %d f %s",
1577 mac->zevpn->vni, &mac->macaddr,
1578 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
1579 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1580 sizeof(mac_buf)));
1581 }
1582
1583 old_static = zebra_evpn_mac_is_static(mac);
1584 UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
1585 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
1586 zebra_evpn_mac_start_hold_timer(mac);
1587 new_static = zebra_evpn_mac_is_static(mac);
1588
1589 if (old_static != new_static)
1590 /* program the local mac in the kernel */
1591 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
1592 false /* force_clear_static */,
1593 __func__);
1594 }
1595
1596 static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
1597 struct zebra_mac *mac,
1598 uint32_t seq, uint16_t ipa_len,
1599 const struct ipaddr *ipaddr,
1600 bool sync)
1601 {
1602 char ipbuf[INET6_ADDRSTRLEN];
1603 uint32_t tmp_seq;
1604 const char *n_type;
1605
1606 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1607 tmp_seq = mac->loc_seq;
1608 n_type = "local";
1609 } else {
1610 tmp_seq = mac->rem_seq;
1611 n_type = "remote";
1612 }
1613
1614 if (seq < tmp_seq) {
1615 /* if the mac was never advertised to bgp we must accept
1616 * whatever sequence number bgp sends
1617 * XXX - check with Vivek
1618 */
1619 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
1620 && !zebra_evpn_mac_is_ready_for_bgp(mac->flags)) {
1621 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
1622 || IS_ZEBRA_DEBUG_VXLAN) {
1623 char mac_buf[MAC_BUF_SIZE];
1624
1625 zlog_debug(
1626 "%s-macip accept vni %u %s-mac %pEA%s%s lower seq %u f %s",
1627 sync ? "sync" : "rem", zevpn->vni,
1628 n_type,
1629 &mac->macaddr,
1630 ipa_len ? " IP " : "",
1631 ipa_len ? ipaddr2str(ipaddr, ipbuf,
1632 sizeof(ipbuf))
1633 : "",
1634 tmp_seq,
1635 zebra_evpn_zebra_mac_flag_dump(
1636 mac, mac_buf, sizeof(mac_buf)));
1637 }
1638
1639 return true;
1640 }
1641
1642 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) {
1643 char mac_buf[MAC_BUF_SIZE];
1644
1645 zlog_debug(
1646 "%s-macip ignore vni %u %s-mac %pEA%s%s as existing has higher seq %u f %s",
1647 sync ? "sync" : "rem", zevpn->vni, n_type,
1648 &mac->macaddr,
1649 ipa_len ? " IP " : "",
1650 ipa_len ? ipaddr2str(ipaddr, ipbuf,
1651 sizeof(ipbuf))
1652 : "",
1653 tmp_seq,
1654 zebra_evpn_zebra_mac_flag_dump(
1655 mac, mac_buf, sizeof(mac_buf)));
1656 }
1657 return false;
1658 }
1659
1660 return true;
1661 }
1662
1663 struct zebra_mac *zebra_evpn_proc_sync_mac_update(
1664 struct zebra_evpn *zevpn, const struct ethaddr *macaddr,
1665 uint16_t ipa_len, const struct ipaddr *ipaddr, uint8_t flags,
1666 uint32_t seq, const esi_t *esi, struct sync_mac_ip_ctx *ctx)
1667 {
1668 struct zebra_mac *mac;
1669 bool inform_bgp = false;
1670 bool inform_dataplane = false;
1671 bool seq_change = false;
1672 bool es_change = false;
1673 uint32_t tmp_seq;
1674 char ipbuf[INET6_ADDRSTRLEN];
1675 bool old_local = false;
1676 bool old_bgp_ready;
1677 bool new_bgp_ready;
1678
1679 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
1680 if (!mac) {
1681 /* if it is a new local path we need to inform both
1682 * the control protocol and the data-plane
1683 */
1684 inform_bgp = true;
1685 inform_dataplane = true;
1686 ctx->mac_created = true;
1687 ctx->mac_inactive = true;
1688
1689 /* create the MAC and associate it with the dest ES */
1690 mac = zebra_evpn_mac_add(zevpn, macaddr);
1691 zebra_evpn_es_mac_ref(mac, esi);
1692
1693 /* local mac activated by an ES peer */
1694 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
1695 /* if mac-only route setup peer flags */
1696 if (!ipa_len) {
1697 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
1698 SET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
1699 else
1700 SET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE);
1701 }
1702 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
1703 old_bgp_ready = false;
1704 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1705 } else {
1706 uint32_t old_flags;
1707 uint32_t new_flags;
1708 bool old_static;
1709 bool new_static;
1710 bool sticky;
1711 bool remote_gw;
1712
1713 mac->uptime = monotime(NULL);
1714
1715 old_flags = mac->flags;
1716 sticky = !!CHECK_FLAG(old_flags, ZEBRA_MAC_STICKY);
1717 remote_gw = !!CHECK_FLAG(old_flags, ZEBRA_MAC_REMOTE_DEF_GW);
1718 if (sticky || remote_gw) {
1719 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
1720 zlog_debug(
1721 "Ignore sync-macip vni %u mac %pEA%s%s%s%s",
1722 zevpn->vni, macaddr,
1723 ipa_len ? " IP " : "",
1724 ipa_len ? ipaddr2str(ipaddr, ipbuf,
1725 sizeof(ipbuf))
1726 : "",
1727 sticky ? " sticky" : "",
1728 remote_gw ? " remote_gw" : "");
1729 ctx->ignore_macip = true;
1730 return NULL;
1731 }
1732 if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, ipa_len,
1733 ipaddr, true)) {
1734 ctx->ignore_macip = true;
1735 return NULL;
1736 }
1737
1738 old_local = !!CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL);
1739 old_static = zebra_evpn_mac_is_static(mac);
1740
1741 /* re-build the mac flags */
1742 new_flags = 0;
1743 SET_FLAG(new_flags, ZEBRA_MAC_LOCAL);
1744 /* retain old local activity flag */
1745 if (old_flags & ZEBRA_MAC_LOCAL) {
1746 new_flags |= (old_flags & ZEBRA_MAC_LOCAL_INACTIVE);
1747 } else {
1748 new_flags |= ZEBRA_MAC_LOCAL_INACTIVE;
1749 ctx->mac_inactive = true;
1750 }
1751 if (ipa_len) {
1752 /* if mac-ip route do NOT update the peer flags
1753 * i.e. retain only flags as is
1754 */
1755 new_flags |= (old_flags & ZEBRA_MAC_ALL_PEER_FLAGS);
1756 } else {
1757 /* if mac-only route update peer flags */
1758 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
1759 SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_PROXY);
1760 /* if the mac was peer-active previously we
1761 * need to keep the flag and start the
1762 * holdtimer on it. the peer-active flag is
1763 * cleared on holdtimer expiry.
1764 */
1765 if (CHECK_FLAG(old_flags,
1766 ZEBRA_MAC_ES_PEER_ACTIVE)) {
1767 SET_FLAG(new_flags,
1768 ZEBRA_MAC_ES_PEER_ACTIVE);
1769 zebra_evpn_mac_start_hold_timer(mac);
1770 }
1771 } else {
1772 SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_ACTIVE);
1773 /* stop hold timer if a peer has verified
1774 * reachability
1775 */
1776 zebra_evpn_mac_stop_hold_timer(mac);
1777 }
1778 }
1779 mac->rem_seq = 0;
1780 zebra_evpn_mac_clear_fwd_info(mac);
1781 mac->flags = new_flags;
1782
1783 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) {
1784 char mac_buf[MAC_BUF_SIZE], omac_buf[MAC_BUF_SIZE];
1785 struct zebra_mac omac;
1786
1787 omac.flags = old_flags;
1788 zlog_debug(
1789 "sync-mac vni %u mac %pEA old_f %snew_f %s",
1790 zevpn->vni, macaddr,
1791 zebra_evpn_zebra_mac_flag_dump(
1792 &omac, omac_buf, sizeof(omac_buf)),
1793 zebra_evpn_zebra_mac_flag_dump(
1794 mac, mac_buf, sizeof(mac_buf)));
1795 }
1796
1797 /* update es */
1798 es_change = zebra_evpn_es_mac_ref(mac, esi);
1799 /* if mac dest change - inform both sides */
1800 if (es_change) {
1801 inform_bgp = true;
1802 inform_dataplane = true;
1803 ctx->mac_inactive = true;
1804 }
1805
1806 /* if peer-flag is being set notify dataplane that the
1807 * entry must not be expired because of local inactivity
1808 */
1809 new_static = zebra_evpn_mac_is_static(mac);
1810 if (old_static != new_static)
1811 inform_dataplane = true;
1812
1813 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(old_flags);
1814 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
1815 if (old_bgp_ready != new_bgp_ready)
1816 inform_bgp = true;
1817 }
1818
1819
1820 /* update sequence number; if that results in a new local sequence
1821 * inform bgp
1822 */
1823 tmp_seq = MAX(mac->loc_seq, seq);
1824 if (tmp_seq != mac->loc_seq) {
1825 mac->loc_seq = tmp_seq;
1826 seq_change = true;
1827 inform_bgp = true;
1828 }
1829
1830 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
1831 char mac_buf[MAC_BUF_SIZE];
1832
1833 zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s",
1834 ctx->mac_created ? "created" : "updated",
1835 zevpn->vni, macaddr,
1836 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
1837 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
1838 sizeof(mac_buf)),
1839 inform_bgp ? "inform_bgp" : "",
1840 inform_dataplane ? " inform_dp" : "");
1841 }
1842
1843 if (inform_bgp)
1844 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
1845 new_bgp_ready);
1846
1847 /* neighs using the mac may need to be re-sent to
1848 * bgp with updated info
1849 */
1850 if (seq_change || es_change || !old_local)
1851 zebra_evpn_process_neigh_on_local_mac_change(
1852 zevpn, mac, seq_change, es_change);
1853
1854 if (inform_dataplane) {
1855 if (ipa_len)
1856 /* if the mac is being created as a part of MAC-IP
1857 * route wait for the neigh to be updated or
1858 * created before programming the mac
1859 */
1860 ctx->mac_dp_update_deferred = true;
1861 else
1862 /* program the local mac in the kernel. when the ES
1863 * change we need to force the dataplane to reset
1864 * the activity as we are yet to establish activity
1865 * locally
1866 */
1867 zebra_evpn_sync_mac_dp_install(
1868 mac, ctx->mac_inactive,
1869 false /* force_clear_static */, __func__);
1870 }
1871
1872 return mac;
1873 }
1874
1875 /* update local forwarding info. return true if a dest-ES change
1876 * is detected
1877 */
1878 static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac,
1879 struct interface *ifp,
1880 vlanid_t vid)
1881 {
1882 struct zebra_if *zif = ifp->info;
1883 bool es_change;
1884 ns_id_t local_ns_id = NS_DEFAULT;
1885 struct zebra_vrf *zvrf;
1886 struct zebra_evpn_es *es;
1887
1888 zvrf = ifp->vrf->info;
1889 if (zvrf && zvrf->zns)
1890 local_ns_id = zvrf->zns->ns_id;
1891
1892 zebra_evpn_mac_clear_fwd_info(mac);
1893
1894 es = zif->es_info.es;
1895 if (es && (es->flags & ZEBRA_EVPNES_BYPASS))
1896 es = NULL;
1897 es_change = zebra_evpn_es_mac_ref_entry(mac, es);
1898
1899 if (!mac->es) {
1900 /* if es is set fwd_info is not-relevant/taped-out */
1901 mac->fwd_info.local.ifindex = ifp->ifindex;
1902 mac->fwd_info.local.ns_id = local_ns_id;
1903 mac->fwd_info.local.vid = vid;
1904 zebra_evpn_mac_ifp_link(mac, ifp);
1905 }
1906
1907 return es_change;
1908 }
1909
1910 /* Notify Local MACs to the clienti, skips GW MAC */
1911 static void zebra_evpn_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
1912 void *arg)
1913 {
1914 struct mac_walk_ctx *wctx = arg;
1915 struct zebra_mac *zmac = bucket->data;
1916
1917 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_DEF_GW))
1918 return;
1919
1920 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
1921 zebra_evpn_mac_send_add_to_client(wctx->zevpn->vni,
1922 &zmac->macaddr, zmac->flags,
1923 zmac->loc_seq, zmac->es);
1924 }
1925
1926 /* Iterator to Notify Local MACs of a EVPN */
1927 void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevpn)
1928 {
1929 struct mac_walk_ctx wctx;
1930
1931 if (!zevpn->mac_table)
1932 return;
1933
1934 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
1935 wctx.zevpn = zevpn;
1936
1937 hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client,
1938 &wctx);
1939 }
1940
1941 void zebra_evpn_rem_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
1942 {
1943 zebra_evpn_process_neigh_on_remote_mac_del(zevpn, mac);
1944 /* the remote sequence number in the auto mac entry
1945 * needs to be reset to 0 as the mac entry may have
1946 * been removed on all VTEPs (including
1947 * the originating one)
1948 */
1949 mac->rem_seq = 0;
1950
1951 /* If all remote neighbors referencing a remote MAC
1952 * go away, we need to uninstall the MAC.
1953 */
1954 if (remote_neigh_count(mac) == 0) {
1955 zebra_evpn_rem_mac_uninstall(zevpn, mac, false /*force*/);
1956 zebra_evpn_es_mac_deref_entry(mac);
1957 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
1958 }
1959
1960 if (list_isempty(mac->neigh_list))
1961 zebra_evpn_mac_del(zevpn, mac);
1962 else
1963 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
1964 }
1965
1966 /* Print Duplicate MAC */
1967 void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
1968 {
1969 struct zebra_mac *mac;
1970
1971 mac = (struct zebra_mac *)bucket->data;
1972 if (!mac)
1973 return;
1974
1975 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1976 zebra_evpn_print_mac_hash(bucket, ctxt);
1977 }
1978
1979 /* Print Duplicate MAC in detail */
1980 void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
1981 void *ctxt)
1982 {
1983 struct zebra_mac *mac;
1984
1985 mac = (struct zebra_mac *)bucket->data;
1986 if (!mac)
1987 return;
1988
1989 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1990 zebra_evpn_print_mac_hash_detail(bucket, ctxt);
1991 }
1992
1993 int zebra_evpn_mac_remote_macip_add(
1994 struct zebra_evpn *zevpn, struct zebra_vrf *zvrf,
1995 const struct ethaddr *macaddr, uint16_t ipa_len,
1996 const struct ipaddr *ipaddr, struct zebra_mac **macp,
1997 struct in_addr vtep_ip, uint8_t flags, uint32_t seq, const esi_t *esi)
1998 {
1999 char buf1[INET6_ADDRSTRLEN];
2000 bool sticky;
2001 bool remote_gw;
2002 int update_mac = 0;
2003 bool do_dad = false;
2004 bool is_dup_detect = false;
2005 esi_t *old_esi;
2006 bool old_static = false;
2007 struct zebra_mac *mac;
2008 bool old_es_present;
2009 bool new_es_present;
2010
2011 sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
2012 remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2013
2014 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
2015
2016 /* Ignore if the mac is already present as a gateway mac */
2017 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)
2018 && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
2019 if (IS_ZEBRA_DEBUG_VXLAN)
2020 zlog_debug(
2021 "Ignore remote MACIP ADD VNI %u MAC %pEA%s%s as MAC is already configured as gateway MAC",
2022 zevpn->vni, macaddr,
2023 ipa_len ? " IP " : "",
2024 ipa_len ? ipaddr2str(ipaddr, buf1, sizeof(buf1))
2025 : "");
2026 return -1;
2027 }
2028
2029 old_esi = (mac && mac->es) ? &mac->es->esi : zero_esi;
2030
2031 /* check if the remote MAC is unknown or has a change.
2032 * If so, that needs to be updated first. Note that client could
2033 * install MAC and MACIP separately or just install the latter.
2034 */
2035 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
2036 || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
2037 || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
2038 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
2039 || memcmp(old_esi, esi, sizeof(esi_t)) || seq != mac->rem_seq)
2040 update_mac = 1;
2041
2042 if (update_mac) {
2043 if (!mac) {
2044 mac = zebra_evpn_mac_add(zevpn, macaddr);
2045 zebra_evpn_es_mac_ref(mac, esi);
2046
2047 /* Is this MAC created for a MACIP? */
2048 if (ipa_len)
2049 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2050 } else {
2051 /* When host moves but changes its (MAC,IP)
2052 * binding, BGP may install a MACIP entry that
2053 * corresponds to "older" location of the host
2054 * in transient situations (because {IP1,M1}
2055 * is a different route from {IP1,M2}). Check
2056 * the sequence number and ignore this update
2057 * if appropriate.
2058 */
2059 if (!zebra_evpn_mac_is_bgp_seq_ok(
2060 zevpn, mac, seq, ipa_len, ipaddr, false))
2061 return -1;
2062
2063 old_es_present = !!mac->es;
2064 zebra_evpn_es_mac_ref(mac, esi);
2065 new_es_present = !!mac->es;
2066 /* XXX - dataplane is curently not able to handle a MAC
2067 * replace if the destination changes from L2-NHG to
2068 * single VTEP and vice-versa. So delete the old entry
2069 * and re-install
2070 */
2071 if (old_es_present != new_es_present)
2072 zebra_evpn_rem_mac_uninstall(zevpn, mac, false);
2073 }
2074
2075 /* Check MAC's curent state is local (this is the case
2076 * where MAC has moved from L->R) and check previous
2077 * detection started via local learning.
2078 * RFC-7432: A PE/VTEP that detects a MAC mobility
2079 * event via local learning starts an M-second timer.
2080 *
2081 * VTEP-IP or seq. change alone is not considered
2082 * for dup. detection.
2083 *
2084 * MAC is already marked duplicate set dad, then
2085 * is_dup_detect will be set to not install the entry.
2086 */
2087 if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
2088 && mac->dad_count)
2089 || CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
2090 do_dad = true;
2091
2092 /* Remove local MAC from BGP. */
2093 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
2094 /* force drop the sync flags */
2095 old_static = zebra_evpn_mac_is_static(mac);
2096 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2097 char mac_buf[MAC_BUF_SIZE];
2098
2099 zlog_debug(
2100 "sync-mac->remote vni %u mac %pEA es %s seq %d f %s",
2101 zevpn->vni, macaddr,
2102 mac->es ? mac->es->esi_str : "-",
2103 mac->loc_seq,
2104 zebra_evpn_zebra_mac_flag_dump(
2105 mac, mac_buf, sizeof(mac_buf)));
2106 }
2107
2108 zebra_evpn_mac_clear_sync_info(mac);
2109 zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr,
2110 mac->flags,
2111 false /* force */);
2112 }
2113
2114 /* Set "auto" and "remote" forwarding info. */
2115 zebra_evpn_mac_clear_fwd_info(mac);
2116 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
2117 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
2118 mac->fwd_info.r_vtep_ip = vtep_ip;
2119
2120 if (sticky)
2121 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2122 else
2123 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2124
2125 if (remote_gw)
2126 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
2127 else
2128 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
2129
2130 zebra_evpn_dup_addr_detect_for_mac(
2131 zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad,
2132 &is_dup_detect, false);
2133
2134 if (!is_dup_detect) {
2135 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
2136 /* Install the entry. */
2137 zebra_evpn_rem_mac_install(zevpn, mac, old_static);
2138 }
2139 }
2140
2141 /* Update seq number. */
2142 mac->rem_seq = seq;
2143
2144 /* If there is no IP, return after clearing AUTO flag of MAC. */
2145 if (!ipa_len) {
2146 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2147 return -1;
2148 }
2149 *macp = mac;
2150 return 0;
2151 }
2152
2153 int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
2154 struct zebra_evpn *zevpn,
2155 struct interface *ifp,
2156 const struct ethaddr *macaddr, vlanid_t vid,
2157 bool sticky, bool local_inactive,
2158 bool dp_static, struct zebra_mac *mac)
2159 {
2160 bool mac_sticky = false;
2161 bool inform_client = false;
2162 bool upd_neigh = false;
2163 bool is_dup_detect = false;
2164 struct in_addr vtep_ip = {.s_addr = 0};
2165 bool es_change = false;
2166 bool new_bgp_ready;
2167 /* assume inactive if not present or if not local */
2168 bool old_local_inactive = true;
2169 bool old_bgp_ready = false;
2170 bool inform_dataplane = false;
2171 bool new_static = false;
2172
2173 assert(ifp);
2174 /* Check if we need to create or update or it is a NO-OP. */
2175 if (!mac)
2176 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
2177 if (!mac) {
2178 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
2179 zlog_debug(
2180 "ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s",
2181 sticky ? "sticky " : "", macaddr,
2182 ifp->name, ifp->ifindex, vid, zevpn->vni,
2183 local_inactive ? " local-inactive" : "");
2184
2185 mac = zebra_evpn_mac_add(zevpn, macaddr);
2186 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2187 es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
2188 if (sticky)
2189 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2190 inform_client = true;
2191 } else {
2192 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2193 char mac_buf[MAC_BUF_SIZE];
2194
2195 zlog_debug(
2196 "UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s",
2197 sticky ? "sticky " : "", macaddr,
2198 ifp->name, ifp->ifindex, vid, zevpn->vni,
2199 local_inactive ? "local-inactive " : "",
2200 zebra_evpn_zebra_mac_flag_dump(
2201 mac, mac_buf, sizeof(mac_buf)));
2202 }
2203
2204 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
2205 struct interface *old_ifp;
2206 vlanid_t old_vid;
2207 bool old_static;
2208
2209 zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
2210 old_bgp_ready =
2211 zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2212 old_local_inactive =
2213 !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
2214 old_static = zebra_evpn_mac_is_static(mac);
2215 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
2216 mac_sticky = true;
2217 es_change = zebra_evpn_local_mac_update_fwd_info(
2218 mac, ifp, vid);
2219
2220 /*
2221 * Update any changes and if changes are relevant to
2222 * BGP, note it.
2223 */
2224 if (mac_sticky == sticky && old_ifp == ifp
2225 && old_vid == vid
2226 && old_local_inactive == local_inactive
2227 && dp_static == old_static && !es_change) {
2228 if (IS_ZEBRA_DEBUG_VXLAN)
2229 zlog_debug(
2230 " Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
2231 "entry exists and has not changed ",
2232 sticky ? "sticky " : "",
2233 macaddr, ifp->name,
2234 ifp->ifindex, vid, zevpn->vni,
2235 local_inactive
2236 ? " local_inactive"
2237 : "");
2238 return 0;
2239 }
2240 if (mac_sticky != sticky) {
2241 if (sticky)
2242 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2243 else
2244 UNSET_FLAG(mac->flags,
2245 ZEBRA_MAC_STICKY);
2246 inform_client = true;
2247 }
2248
2249 /* If an es_change is detected we need to advertise
2250 * the route with a sequence that is one
2251 * greater. This is need to indicate a mac-move
2252 * to the ES peers
2253 */
2254 if (es_change) {
2255 /* update the sequence number only if the entry
2256 * is locally active
2257 */
2258 if (!local_inactive)
2259 mac->loc_seq = mac->loc_seq + 1;
2260 /* force drop the peer/sync info as it is
2261 * simply no longer relevant
2262 */
2263 if (CHECK_FLAG(mac->flags,
2264 ZEBRA_MAC_ALL_PEER_FLAGS)) {
2265 zebra_evpn_mac_clear_sync_info(mac);
2266 new_static =
2267 zebra_evpn_mac_is_static(mac);
2268 /* if we clear peer-flags we
2269 * also need to notify the dataplane
2270 * to drop the static flag
2271 */
2272 if (old_static != new_static)
2273 inform_dataplane = true;
2274 }
2275 }
2276 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
2277 || CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
2278 bool do_dad = false;
2279
2280 /*
2281 * MAC has either moved or was "internally" created due
2282 * to a neighbor learn and is now actually learnt. If
2283 * it was learnt as a remote sticky MAC, this is an
2284 * operator error.
2285 */
2286 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
2287 flog_warn(
2288 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
2289 "MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
2290 macaddr,
2291 &mac->fwd_info.r_vtep_ip,
2292 zevpn->vni);
2293 return 0;
2294 }
2295
2296 /* If an actual move, compute MAC's seq number */
2297 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
2298 mac->loc_seq =
2299 MAX(mac->rem_seq + 1, mac->loc_seq);
2300 vtep_ip = mac->fwd_info.r_vtep_ip;
2301 /* Trigger DAD for remote MAC */
2302 do_dad = true;
2303 }
2304
2305 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
2306 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2307 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2308 es_change = zebra_evpn_local_mac_update_fwd_info(
2309 mac, ifp, vid);
2310 if (sticky)
2311 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2312 else
2313 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2314 /*
2315 * We have to inform BGP of this MAC as well as process
2316 * all neighbors.
2317 */
2318 inform_client = true;
2319 upd_neigh = true;
2320
2321 zebra_evpn_dup_addr_detect_for_mac(
2322 zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
2323 true);
2324 if (is_dup_detect) {
2325 inform_client = false;
2326 upd_neigh = false;
2327 es_change = false;
2328 }
2329 }
2330 }
2331
2332 /* if the dataplane thinks the entry is sync but it is
2333 * not sync in zebra (or vice-versa) we need to re-install
2334 * to fixup
2335 */
2336 new_static = zebra_evpn_mac_is_static(mac);
2337 if (dp_static != new_static)
2338 inform_dataplane = true;
2339
2340 if (local_inactive)
2341 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
2342 else
2343 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
2344
2345 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2346 /* if local-activity has changed we need update bgp
2347 * even if bgp already knows about the mac
2348 */
2349 if ((old_local_inactive != local_inactive)
2350 || (new_bgp_ready != old_bgp_ready)) {
2351 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2352 char mac_buf[MAC_BUF_SIZE];
2353
2354 zlog_debug(
2355 "local mac vni %u mac %pEA es %s seq %d f %s%s",
2356 zevpn->vni, macaddr,
2357 mac->es ? mac->es->esi_str : "", mac->loc_seq,
2358 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
2359 sizeof(mac_buf)),
2360 local_inactive ? "local-inactive" : "");
2361 }
2362
2363 if (!is_dup_detect)
2364 inform_client = true;
2365 }
2366
2367 if (es_change) {
2368 inform_client = true;
2369 upd_neigh = true;
2370 }
2371
2372 /* Inform dataplane if required. */
2373 if (inform_dataplane)
2374 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
2375 false /* force_clear_static */,
2376 __func__);
2377
2378 /* Inform BGP if required. */
2379 if (inform_client)
2380 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
2381 new_bgp_ready);
2382
2383 /* Process all neighbors associated with this MAC, if required. */
2384 if (upd_neigh)
2385 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
2386 es_change);
2387
2388 return 0;
2389 }
2390
2391 int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac,
2392 bool clear_static)
2393 {
2394 bool old_bgp_ready;
2395 bool new_bgp_ready;
2396
2397 if (IS_ZEBRA_DEBUG_VXLAN)
2398 zlog_debug("DEL MAC %pEA VNI %u seq %u flags 0x%x nbr count %u",
2399 &mac->macaddr, zevpn->vni, mac->loc_seq, mac->flags,
2400 listcount(mac->neigh_list));
2401
2402 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2403 if (!clear_static && zebra_evpn_mac_is_static(mac)) {
2404 /* this is a synced entry and can only be removed when the
2405 * es-peers stop advertising it.
2406 */
2407 zebra_evpn_mac_clear_fwd_info(mac);
2408
2409 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
2410 char mac_buf[MAC_BUF_SIZE];
2411
2412 zlog_debug(
2413 "re-add sync-mac vni %u mac %pEA es %s seq %d f %s",
2414 zevpn->vni, &mac->macaddr,
2415 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
2416 zebra_evpn_zebra_mac_flag_dump(
2417 mac, mac_buf, sizeof(mac_buf)));
2418 }
2419
2420 /* inform-bgp about change in local-activity if any */
2421 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
2422 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
2423 new_bgp_ready =
2424 zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2425 zebra_evpn_mac_send_add_del_to_client(
2426 mac, old_bgp_ready, new_bgp_ready);
2427 }
2428
2429 /* re-install the inactive entry in the kernel */
2430 zebra_evpn_sync_mac_dp_install(mac, true /* set_inactive */,
2431 false /* force_clear_static */,
2432 __func__);
2433
2434 return 0;
2435 }
2436
2437 /* flush the peer info */
2438 zebra_evpn_mac_clear_sync_info(mac);
2439
2440 /* Update all the neigh entries associated with this mac */
2441 zebra_evpn_process_neigh_on_local_mac_del(zevpn, mac);
2442
2443 /* Remove MAC from BGP. */
2444 zebra_evpn_mac_send_del_to_client(zevpn->vni, &mac->macaddr, mac->flags,
2445 false /* force */);
2446
2447 zebra_evpn_es_mac_deref_entry(mac);
2448
2449 /* remove links to the destination access port */
2450 zebra_evpn_mac_clear_fwd_info(mac);
2451
2452 /*
2453 * If there are no neigh associated with the mac delete the mac
2454 * else mark it as AUTO for forward reference
2455 */
2456 if (!listcount(mac->neigh_list)) {
2457 zebra_evpn_mac_del(zevpn, mac);
2458 } else {
2459 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
2460 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
2461 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2462 }
2463
2464 return 0;
2465 }
2466
2467 void zebra_evpn_mac_gw_macip_add(struct interface *ifp,
2468 struct zebra_evpn *zevpn,
2469 const struct ipaddr *ip,
2470 struct zebra_mac **macp,
2471 const struct ethaddr *macaddr,
2472 vlanid_t vlan_id, bool def_gw)
2473 {
2474 struct zebra_mac *mac;
2475 ns_id_t local_ns_id = NS_DEFAULT;
2476 struct zebra_vrf *zvrf;
2477
2478 zvrf = ifp->vrf->info;
2479 if (zvrf && zvrf->zns)
2480 local_ns_id = zvrf->zns->ns_id;
2481
2482 if (!*macp) {
2483 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
2484 if (!mac)
2485 mac = zebra_evpn_mac_add(zevpn, macaddr);
2486 *macp = mac;
2487 } else
2488 mac = *macp;
2489
2490 /* Set "local" forwarding info. */
2491 zebra_evpn_mac_clear_fwd_info(mac);
2492 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2493 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2494 if (def_gw)
2495 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
2496 else
2497 SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
2498 mac->fwd_info.local.ifindex = ifp->ifindex;
2499 mac->fwd_info.local.ns_id = local_ns_id;
2500 mac->fwd_info.local.vid = vlan_id;
2501 }
2502
2503 void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
2504 {
2505 struct zebra_mac *mac;
2506 struct ethaddr macaddr;
2507 bool old_bgp_ready;
2508
2509 if (!zebra_evpn_mh_do_adv_svi_mac())
2510 return;
2511
2512 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2513 mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
2514 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI)) {
2515 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2516 zlog_debug("SVI %s mac free", ifp->name);
2517
2518 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2519 UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI);
2520 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
2521 false);
2522 zebra_evpn_deref_ip2mac(mac->zevpn, mac);
2523 }
2524 }
2525
2526 void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
2527 {
2528 struct zebra_mac *mac = NULL;
2529 struct ethaddr macaddr;
2530 struct zebra_if *zif = ifp->info;
2531 bool old_bgp_ready;
2532 bool new_bgp_ready;
2533
2534 if (!zebra_evpn_mh_do_adv_svi_mac()
2535 || !zebra_evpn_send_to_client_ok(zevpn))
2536 return;
2537
2538 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2539
2540 /* dup check */
2541 mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
2542 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
2543 return;
2544
2545 /* add/update mac */
2546 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
2547 zlog_debug("SVI %s mac add", zif->ifp->name);
2548
2549 old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags))
2550 ? true
2551 : false;
2552
2553 zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
2554
2555 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
2556 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
2557 new_bgp_ready);
2558 }