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