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