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