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