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