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