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