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