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