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