]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
bgpd: Allow non-default instance to be EVPN one
[mirror_frr.git] / zebra / zebra_vxlan.c
CommitLineData
13d60d35 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
43e52561 25#include "hash.h"
13d60d35 26#include "if.h"
43e52561 27#include "jhash.h"
13d60d35 28#include "linklist.h"
43e52561
QY
29#include "log.h"
30#include "memory.h"
31#include "prefix.h"
13d60d35 32#include "stream.h"
43e52561 33#include "table.h"
13d60d35 34#include "vlan.h"
35#include "vxlan.h"
68e33151
CS
36#ifdef GNU_LINUX
37#include <linux/neighbour.h>
38#endif
13d60d35 39
89272910 40#include "zebra/zebra_router.h"
43e52561
QY
41#include "zebra/debug.h"
42#include "zebra/interface.h"
13d60d35 43#include "zebra/rib.h"
44#include "zebra/rt.h"
43e52561
QY
45#include "zebra/rt_netlink.h"
46#include "zebra/zebra_errors.h"
47#include "zebra/zebra_l2.h"
48#include "zebra/zebra_memory.h"
13d60d35 49#include "zebra/zebra_ns.h"
13d60d35 50#include "zebra/zebra_vrf.h"
13d60d35 51#include "zebra/zebra_vxlan.h"
43e52561 52#include "zebra/zebra_vxlan_private.h"
3801e764 53#include "zebra/zebra_router.h"
13d60d35 54
6134fd82 55DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
d62a17ae 56DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
b7cfce93 57DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
13d60d35 58DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP");
d62a17ae 59DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC");
60DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
13d60d35 61
62/* definitions */
63
13d60d35 64/* static function declarations */
996c9314
LB
65static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
66 uint16_t cmd);
cd233079 67static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
e3b78da8
TB
68static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt);
69static void zvni_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt);
70static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket,
cd233079 71 void **args);
c0e519d3
MK
72static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
73 json_object *json);
316f4ca4
MK
74static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
75 json_object *json);
24cdbd0d 76static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json);
e3b78da8
TB
77static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt);
78static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt);
cd233079 79static void zvni_print(zebra_vni_t *zvni, void **ctxt);
e3b78da8 80static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[]);
d62a17ae 81
996c9314 82static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
d7c0a89a 83 struct ipaddr *ip, uint8_t flags,
2c476b72 84 uint32_t seq, int state, uint16_t cmd);
d62a17ae 85static unsigned int neigh_hash_keymake(void *p);
d62a17ae 86static void *zvni_neigh_alloc(void *p);
b6938a74
MK
87static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
88 struct ethaddr *mac);
d62a17ae 89static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n);
d62a17ae 90static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
91 struct in_addr *r_vtep_ip);
996c9314 92static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
d7c0a89a 93 uint32_t flags);
d62a17ae 94static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip);
996c9314 95static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
d7c0a89a 96 struct ethaddr *macaddr,
f07e1c99 97 uint8_t flags, uint32_t seq);
996c9314 98static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
d7c0a89a 99 struct ethaddr *macaddr,
2c476b72 100 uint8_t flags, int state);
d62a17ae 101static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
102static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
44bc8ae5 103static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n);
b7cfce93 104static zebra_vni_t *zvni_from_svi(struct interface *ifp,
996c9314
LB
105 struct interface *br_if);
106static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if);
d62a17ae 107
b7cfce93 108/* l3-vni next-hop neigh related APIs */
2dbad57f 109static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni,
b7cfce93
MK
110 struct ipaddr *ip);
111static void *zl3vni_nh_alloc(void *p);
112static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni,
113 struct ipaddr *vtep_ip,
114 struct ethaddr *rmac);
115static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
116static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
2dbad57f 117static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
b7cfce93
MK
118
119/* l3-vni rmac related APIs */
e3b78da8 120static void zl3vni_print_rmac_hash(struct hash_bucket *, void *);
2dbad57f 121static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
b7cfce93
MK
122 struct ethaddr *rmac);
123static void *zl3vni_rmac_alloc(void *p);
124static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni,
125 struct ethaddr *rmac);
126static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
127static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
996c9314 128static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
b7cfce93
MK
129
130/* l3-vni related APIs*/
b7cfce93
MK
131static zebra_l3vni_t *zl3vni_lookup(vni_t vni);
132static void *zl3vni_alloc(void *p);
133static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
134static int zl3vni_del(zebra_l3vni_t *zl3vni);
135static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t);
b7cfce93
MK
136static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
137static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
b7cfce93
MK
138static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni);
139static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni);
140
d62a17ae 141static unsigned int mac_hash_keymake(void *p);
74df8d6d 142static bool mac_cmp(const void *p1, const void *p2);
d62a17ae 143static void *zvni_mac_alloc(void *p);
144static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr);
145static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac);
d62a17ae 146static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
147 struct in_addr *r_vtep_ip);
996c9314 148static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
d7c0a89a 149 uint32_t flags);
d62a17ae 150static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
996c9314 151static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
f07e1c99 152 uint8_t flags, uint32_t seq);
e98e4b88 153static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr);
d62a17ae 154static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
155 struct interface *br_if, vlanid_t vid);
156static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
d63c1b18 157static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac);
e3b78da8 158static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt);
d62a17ae 159
160static unsigned int vni_hash_keymake(void *p);
d62a17ae 161static void *zvni_alloc(void *p);
2853fed6 162static zebra_vni_t *zvni_lookup(vni_t vni);
163static zebra_vni_t *zvni_add(vni_t vni);
164static int zvni_del(zebra_vni_t *zvni);
165static int zvni_send_add_to_client(zebra_vni_t *zvni);
166static int zvni_send_del_to_client(vni_t vni);
4d762f26 167static void zvni_build_hash_table(void);
d62a17ae 168static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
169static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
170static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
171static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep);
172static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall);
173static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip);
174static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip);
1a98c087
MK
175static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
176static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
177static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
178 struct ethaddr *macaddr, struct ipaddr *ip);
179static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
180 struct ipaddr *ip);
181struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
2853fed6 182static int advertise_gw_macip_enabled(zebra_vni_t *zvni);
278e26de 183static int advertise_svi_macip_enabled(zebra_vni_t *zvni);
e22a946a
CS
184static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
185 zebra_mac_t *old_zmac,
186 zebra_mac_t *new_zmac,
187 zebra_neigh_t *nbr);
fe697c6b 188static int remote_neigh_count(zebra_mac_t *zmac);
189static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac);
c80a972c
CS
190static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t);
191static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t);
7510e459
CS
192static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
193 zebra_neigh_t *nbr,
194 struct in_addr vtep_ip,
195 bool do_dad,
196 bool *is_dup_detect,
197 bool is_local);
bdca1974
CS
198static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
199 zebra_mac_t *mac,
200 struct in_addr vtep_ip,
201 bool do_dad,
202 bool *is_dup_detect,
203 bool is_local);
13d60d35 204
205/* Private functions */
5e1b0650 206static int host_rb_entry_compare(const struct host_rb_entry *hle1,
85442b09 207 const struct host_rb_entry *hle2)
5e1b0650
DS
208{
209 if (hle1->p.family < hle2->p.family)
210 return -1;
211
212 if (hle1->p.family > hle2->p.family)
213 return 1;
214
215 if (hle1->p.prefixlen < hle2->p.prefixlen)
216 return -1;
217
218 if (hle1->p.prefixlen > hle2->p.prefixlen)
219 return 1;
220
221 if (hle1->p.family == AF_INET) {
222 if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr)
223 return -1;
224
225 if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr)
226 return 1;
227
228 return 0;
2acc2310
DS
229 } else if (hle1->p.family == AF_INET6) {
230 return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
231 IPV6_MAX_BYTELEN);
5e1b0650 232 } else {
9df414fe
QY
233 zlog_debug("%s: Unexpected family type: %d",
234 __PRETTY_FUNCTION__, hle1->p.family);
5e1b0650
DS
235 return 0;
236 }
237}
85442b09 238RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare);
5e1b0650 239
85442b09 240static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
5e1b0650
DS
241{
242 struct host_rb_entry *hle;
243 uint32_t count = 0;
244
85442b09 245 RB_FOREACH (hle, host_rb_tree_entry, hrbe)
5e1b0650
DS
246 count++;
247
248 return count;
249}
13d60d35 250
790f8dc5 251/*
252 * Return number of valid MACs in a VNI's MAC hash table - all
253 * remote MACs and non-internal (auto) local MACs count.
254 */
d7c0a89a 255static uint32_t num_valid_macs(zebra_vni_t *zvni)
790f8dc5 256{
257 unsigned int i;
d7c0a89a 258 uint32_t num_macs = 0;
790f8dc5 259 struct hash *hash;
e3b78da8 260 struct hash_bucket *hb;
790f8dc5 261 zebra_mac_t *mac;
262
263 hash = zvni->mac_table;
264 if (!hash)
265 return num_macs;
266 for (i = 0; i < hash->size; i++) {
267 for (hb = hash->index[i]; hb; hb = hb->next) {
268 mac = (zebra_mac_t *)hb->data;
269 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
63ce2ee7 270 || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
790f8dc5 271 || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
272 num_macs++;
273 }
274 }
275
276 return num_macs;
277}
278
1374d4db
CS
279static uint32_t num_dup_detected_macs(zebra_vni_t *zvni)
280{
281 unsigned int i;
282 uint32_t num_macs = 0;
283 struct hash *hash;
e3b78da8 284 struct hash_bucket *hb;
1374d4db
CS
285 zebra_mac_t *mac;
286
287 hash = zvni->mac_table;
288 if (!hash)
289 return num_macs;
290 for (i = 0; i < hash->size; i++) {
291 for (hb = hash->index[i]; hb; hb = hb->next) {
292 mac = (zebra_mac_t *)hb->data;
293 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
294 num_macs++;
295 }
296 }
297
298 return num_macs;
299}
300
301static uint32_t num_dup_detected_neighs(zebra_vni_t *zvni)
302{
303 unsigned int i;
304 uint32_t num_neighs = 0;
305 struct hash *hash;
e3b78da8 306 struct hash_bucket *hb;
1374d4db
CS
307 zebra_neigh_t *nbr;
308
309 hash = zvni->neigh_table;
310 if (!hash)
311 return num_neighs;
312 for (i = 0; i < hash->size; i++) {
313 for (hb = hash->index[i]; hb; hb = hb->next) {
314 nbr = (zebra_neigh_t *)hb->data;
315 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
316 num_neighs++;
317 }
318 }
319
320 return num_neighs;
321}
322
2853fed6 323static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
1a98c087 324{
2853fed6 325 struct zebra_vrf *zvrf;
326
327 zvrf = vrf_info_lookup(VRF_DEFAULT);
1a98c087
MK
328 if (zvrf && zvrf->advertise_gw_macip)
329 return 1;
330
331 if (zvni && zvni->advertise_gw_macip)
332 return 1;
333
334 return 0;
335}
336
278e26de
CS
337static int advertise_svi_macip_enabled(zebra_vni_t *zvni)
338{
339 struct zebra_vrf *zvrf;
340
341 zvrf = vrf_info_lookup(VRF_DEFAULT);
342 if (zvrf && zvrf->advertise_svi_macip)
343 return 1;
344
345 if (zvni && zvni->advertise_svi_macip)
346 return 1;
347
348 return 0;
349}
350
e22a946a 351/* As part Duplicate Address Detection (DAD) for IP mobility
979777b2
CS
352 * MAC binding changes, ensure to inherit duplicate flag
353 * from MAC.
e22a946a
CS
354 */
355static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
356 zebra_mac_t *old_zmac,
357 zebra_mac_t *new_zmac,
358 zebra_neigh_t *nbr)
359{
360 bool is_old_mac_dup = false;
361 bool is_new_mac_dup = false;
362
363 if (!zvrf->dup_addr_detect)
364 return 0;
365 /* Check old or new MAC is detected as duplicate
366 * mark this neigh as duplicate
367 */
368 if (old_zmac)
369 is_old_mac_dup = CHECK_FLAG(old_zmac->flags,
370 ZEBRA_MAC_DUPLICATE);
371 if (new_zmac)
372 is_new_mac_dup = CHECK_FLAG(new_zmac->flags,
373 ZEBRA_MAC_DUPLICATE);
374 /* Old and/or new MAC can be in duplicate state,
375 * based on that IP/Neigh Inherits the flag.
376 * If New MAC is marked duplicate, inherit to the IP.
377 * If old MAC is duplicate but new MAC is not, clear
378 * duplicate flag for IP and reset detection params
379 * and let IP DAD retrigger.
380 */
381 if (is_new_mac_dup && !CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
382 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
383 /* Capture Duplicate detection time */
384 nbr->dad_dup_detect_time = monotime(NULL);
385 return 1;
386 } else if (is_old_mac_dup && !is_new_mac_dup) {
387 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
388 nbr->dad_count = 0;
389 nbr->detect_start_time.tv_sec = 0;
390 nbr->detect_start_time.tv_usec = 0;
391 }
392 return 0;
393}
394
bdca1974
CS
395static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
396 zebra_mac_t *mac,
397 struct in_addr vtep_ip,
398 bool do_dad,
399 bool *is_dup_detect,
400 bool is_local)
401{
402 zebra_neigh_t *nbr;
403 struct listnode *node = NULL;
404 struct timeval elapsed = {0, 0};
405 char buf[ETHER_ADDR_STRLEN];
406 char buf1[INET6_ADDRSTRLEN];
407 bool reset_params = false;
408
409 if (!(zvrf->dup_addr_detect && do_dad))
410 return;
411
412 /* MAC is detected as duplicate,
413 * Local MAC event -> hold on advertising to BGP.
414 * Remote MAC event -> hold on installing it.
415 */
416 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
417 if (IS_ZEBRA_DEBUG_VXLAN)
418 zlog_debug(
419 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
420 __PRETTY_FUNCTION__,
421 prefix_mac2str(&mac->macaddr, buf,
422 sizeof(buf)),
423 mac->flags, mac->dad_count,
424 zvrf->dad_freeze_time);
425
426 /* For duplicate MAC do not update
427 * client but update neigh due to
428 * this MAC update.
429 */
430 if (zvrf->dad_freeze)
a4445ece 431 *is_dup_detect = true;
bdca1974
CS
432
433 return;
434 }
435
436 /* Check if detection time (M-secs) expired.
437 * Reset learn count and detection start time.
438 */
439 monotime_since(&mac->detect_start_time, &elapsed);
440 reset_params = (elapsed.tv_sec > zvrf->dad_time);
441 if (is_local && !reset_params) {
442 /* RFC-7432: A PE/VTEP that detects a MAC mobility
443 * event via LOCAL learning starts an M-second timer.
444 *
445 * NOTE: This is the START of the probe with count is
446 * 0 during LOCAL learn event.
447 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
448 */
449 reset_params = !mac->dad_count;
450 }
451
452 if (reset_params) {
453 if (IS_ZEBRA_DEBUG_VXLAN)
454 zlog_debug(
455 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
456 , __PRETTY_FUNCTION__,
457 prefix_mac2str(&mac->macaddr, buf,
458 sizeof(buf)),
459 mac->flags, mac->dad_count);
460
461 mac->dad_count = 0;
462 /* Start dup. addr detection (DAD) start time,
463 * ONLY during LOCAL learn.
464 */
465 if (is_local)
466 monotime(&mac->detect_start_time);
467
468 } else if (!is_local) {
469 /* For REMOTE MAC, increment detection count
470 * ONLY while in probe window, once window passed,
471 * next local learn event should trigger DAD.
472 */
473 mac->dad_count++;
474 }
475
476 /* For LOCAL MAC learn event, once count is reset above via either
477 * initial/start detection time or passed the probe time, the count
478 * needs to be incremented.
479 */
480 if (is_local)
481 mac->dad_count++;
482
bdca1974
CS
483 if (mac->dad_count >= zvrf->dad_max_moves) {
484 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
485 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
486 mac->zvni->vni,
487 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
488 is_local ? "local update, last" :
489 "remote update, from", inet_ntoa(vtep_ip));
490
491 SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
492
493 /* Capture Duplicate detection time */
494 mac->dad_dup_detect_time = monotime(NULL);
495
496 /* Mark all IPs/Neighs as duplicate
497 * associcated with this MAC
498 */
499 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
500
501 /* Ony Mark IPs which are Local */
502 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
503 continue;
504
505 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
506
507 nbr->dad_dup_detect_time = monotime(NULL);
508
509 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
510 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
511 mac->zvni->vni,
512 prefix_mac2str(&mac->macaddr,
513 buf, sizeof(buf)),
514 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
515 is_local ? "local" : "remote");
516 }
517
518 /* Start auto recovery timer for this MAC */
519 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
520 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
521 if (IS_ZEBRA_DEBUG_VXLAN)
522 zlog_debug(
523 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
524 , __PRETTY_FUNCTION__,
525 prefix_mac2str(&mac->macaddr, buf,
526 sizeof(buf)),
527 mac->flags, zvrf->dad_freeze_time);
528
3801e764 529 thread_add_timer(zrouter.master,
bdca1974
CS
530 zebra_vxlan_dad_mac_auto_recovery_exp,
531 mac, zvrf->dad_freeze_time,
532 &mac->dad_mac_auto_recovery_timer);
533 }
534
a4445ece 535 /* In case of local update, do not inform to client (BGPd),
bdca1974
CS
536 * upd_neigh for neigh sequence change.
537 */
538 if (zvrf->dad_freeze)
a4445ece 539 *is_dup_detect = true;
bdca1974
CS
540 }
541}
542
7510e459
CS
543static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
544 zebra_neigh_t *nbr,
545 struct in_addr vtep_ip,
546 bool do_dad,
547 bool *is_dup_detect,
548 bool is_local)
549{
550
551 struct timeval elapsed = {0, 0};
552 char buf[ETHER_ADDR_STRLEN];
553 char buf1[INET6_ADDRSTRLEN];
554 bool reset_params = false;
555
556 if (!zvrf->dup_addr_detect)
557 return;
558
559 /* IP is detected as duplicate or inherit dup
560 * state, hold on to install as remote entry
561 * only if freeze is enabled.
562 */
563 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
564 if (IS_ZEBRA_DEBUG_VXLAN)
565 zlog_debug(
566 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
567 __PRETTY_FUNCTION__,
568 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
569 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
570 nbr->flags, nbr->dad_count,
571 zvrf->dad_freeze_time);
572
573 if (zvrf->dad_freeze)
574 *is_dup_detect = true;
753ad4fe 575
7510e459
CS
576 /* warn-only action, neigh will be installed.
577 * freeze action, it wil not be installed.
578 */
579 return;
580 }
581
582 if (!do_dad)
583 return;
584
585 /* Check if detection time (M-secs) expired.
586 * Reset learn count and detection start time.
587 * During remote mac add, count should already be 1
588 * via local learning.
589 */
590 monotime_since(&nbr->detect_start_time, &elapsed);
591 reset_params = (elapsed.tv_sec > zvrf->dad_time);
592
593 if (is_local && !reset_params) {
594 /* RFC-7432: A PE/VTEP that detects a MAC mobility
595 * event via LOCAL learning starts an M-second timer.
596 *
597 * NOTE: This is the START of the probe with count is
598 * 0 during LOCAL learn event.
599 */
600 reset_params = !nbr->dad_count;
601 }
602
603 if (reset_params) {
604 if (IS_ZEBRA_DEBUG_VXLAN)
605 zlog_debug(
606 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
607 __PRETTY_FUNCTION__,
608 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
609 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
610 nbr->flags, nbr->dad_count);
611 /* Reset learn count but do not start detection
612 * during REMOTE learn event.
613 */
614 nbr->dad_count = 0;
615 /* Start dup. addr detection (DAD) start time,
616 * ONLY during LOCAL learn.
617 */
618 if (is_local)
619 monotime(&nbr->detect_start_time);
620
621 } else if (!is_local) {
622 /* For REMOTE IP/Neigh, increment detection count
623 * ONLY while in probe window, once window passed,
624 * next local learn event should trigger DAD.
625 */
626 nbr->dad_count++;
627 }
628
629 /* For LOCAL IP/Neigh learn event, once count is reset above via either
630 * initial/start detection time or passed the probe time, the count
631 * needs to be incremented.
632 */
633 if (is_local)
634 nbr->dad_count++;
635
636 if (nbr->dad_count >= zvrf->dad_max_moves) {
637 flog_warn(EC_ZEBRA_DUP_IP_DETECTED,
638 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
639 nbr->zvni->vni,
640 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
641 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
642 is_local ? "local update, last" :
643 "remote update, from",
644 inet_ntoa(vtep_ip));
645
646 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
647
648 /* Capture Duplicate detection time */
649 nbr->dad_dup_detect_time = monotime(NULL);
650
651 /* Start auto recovery timer for this IP */
652 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
653 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
654 if (IS_ZEBRA_DEBUG_VXLAN)
655 zlog_debug(
656 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
657 __PRETTY_FUNCTION__,
658 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
659 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
660 nbr->flags, zvrf->dad_freeze_time);
661
3801e764 662 thread_add_timer(zrouter.master,
7510e459
CS
663 zebra_vxlan_dad_ip_auto_recovery_exp,
664 nbr, zvrf->dad_freeze_time,
665 &nbr->dad_ip_auto_recovery_timer);
666 }
667 if (zvrf->dad_freeze)
668 *is_dup_detect = true;
669 }
670}
671
cec2e17d 672/*
673 * Helper function to determine maximum width of neighbor IP address for
674 * display - just because we're dealing with IPv6 addresses that can
675 * widely vary.
676 */
e3b78da8 677static void zvni_find_neigh_addr_width(struct hash_bucket *bucket, void *ctxt)
cec2e17d 678{
d62a17ae 679 zebra_neigh_t *n;
680 char buf[INET6_ADDRSTRLEN];
681 struct neigh_walk_ctx *wctx = ctxt;
682 int width;
cec2e17d 683
e3b78da8 684 n = (zebra_neigh_t *)bucket->data;
cec2e17d 685
1445b43c
A
686 ipaddr2str(&n->ip, buf, sizeof(buf));
687 width = strlen(buf);
d62a17ae 688 if (width > wctx->addr_width)
689 wctx->addr_width = width;
68e33151 690
cec2e17d 691}
692
693/*
694 * Print a specific neighbor entry.
695 */
cd233079 696static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
cec2e17d 697{
d62a17ae 698 struct vty *vty;
699 char buf1[ETHER_ADDR_STRLEN];
700 char buf2[INET6_ADDRSTRLEN];
1a8c5c38 701 const char *type_str;
702 const char *state_str;
703 bool flags_present = false;
979777b2 704 struct zebra_vrf *zvrf = NULL;
87454e6b 705 struct timeval detect_start_time = {0, 0};
cec2e17d 706
6005fe55 707 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
979777b2
CS
708 if (!zvrf)
709 return;
710
6005fe55 711 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
cd233079
CS
712 ipaddr2str(&n->ip, buf2, sizeof(buf2));
713 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
1a8c5c38 714 type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ?
715 "local" : "remote";
716 state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
cd233079
CS
717 vty = (struct vty *)ctxt;
718 if (json == NULL) {
719 vty_out(vty, "IP: %s\n",
720 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1a8c5c38 721 vty_out(vty, " Type: %s\n", type_str);
722 vty_out(vty, " State: %s\n", state_str);
723 vty_out(vty, " MAC: %s\n",
cd233079
CS
724 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
725 } else {
726 json_object_string_add(json, "ip", buf2);
1a8c5c38 727 json_object_string_add(json, "type", type_str);
728 json_object_string_add(json, "state", state_str);
cd233079
CS
729 json_object_string_add(json, "mac", buf1);
730 }
731 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
b6938a74 732 if (json == NULL) {
1a8c5c38 733 vty_out(vty, " Remote VTEP: %s\n",
cd233079 734 inet_ntoa(n->r_vtep_ip));
b6938a74 735 } else
cd233079
CS
736 json_object_string_add(json, "remoteVtep",
737 inet_ntoa(n->r_vtep_ip));
738 }
ead40654 739 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
1a8c5c38 740 if (!json) {
741 vty_out(vty, " Flags: Default-gateway");
742 flags_present = true;
743 } else
ead40654
MK
744 json_object_boolean_true_add(json, "defaultGateway");
745 }
68e33151 746 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
1a8c5c38 747 if (!json) {
748 vty_out(vty,
749 flags_present ? " ,Router" : " Flags: Router");
750 flags_present = true;
751 }
68e33151 752 }
f07e1c99 753 if (json == NULL) {
1a8c5c38 754 if (flags_present)
755 vty_out(vty, "\n");
756 vty_out(vty, " Local Seq: %u Remote Seq: %u\n",
f07e1c99 757 n->loc_seq, n->rem_seq);
87454e6b
CS
758
759 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
760 vty_out(vty, " Duplicate, detected at %s",
761 time_to_string(n->dad_dup_detect_time));
762 } else if (n->dad_count) {
763 monotime_since(&n->detect_start_time,
764 &detect_start_time);
765 if (detect_start_time.tv_sec <= zvrf->dad_time) {
37a04040
CS
766 char *buf = time_to_string(
767 n->detect_start_time.tv_sec);
87454e6b
CS
768 char tmp_buf[30];
769
138a4965 770 strlcpy(tmp_buf, buf, sizeof(tmp_buf));
87454e6b
CS
771 vty_out(vty,
772 " Duplicate detection started at %s, detection count %u\n",
773 tmp_buf, n->dad_count);
774 }
775 }
1a8c5c38 776 } else {
777 json_object_int_add(json, "localSequence", n->loc_seq);
778 json_object_int_add(json, "remoteSequence", n->rem_seq);
87454e6b
CS
779 json_object_int_add(json, "detectionCount",
780 n->dad_count);
781 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
782 json_object_boolean_true_add(json, "isDuplicate");
783 else
784 json_object_boolean_false_add(json, "isDuplicate");
785
786
68e33151 787 }
cec2e17d 788}
789
790/*
791 * Print neighbor hash entry - called for display of all neighbors.
792 */
e3b78da8 793static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt)
d62a17ae 794{
795 struct vty *vty;
cd233079 796 json_object *json_vni = NULL, *json_row = NULL;
d62a17ae 797 zebra_neigh_t *n;
798 char buf1[ETHER_ADDR_STRLEN];
799 char buf2[INET6_ADDRSTRLEN];
800 struct neigh_walk_ctx *wctx = ctxt;
1a8c5c38 801 const char *state_str;
d62a17ae 802
803 vty = wctx->vty;
cd233079 804 json_vni = wctx->json;
e3b78da8 805 n = (zebra_neigh_t *)bucket->data;
d62a17ae 806
cd233079
CS
807 if (json_vni)
808 json_row = json_object_new_object();
809
d62a17ae 810 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
811 ipaddr2str(&n->ip, buf2, sizeof(buf2));
1a8c5c38 812 state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
813 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
814 if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
815 return;
816
cd233079 817 if (json_vni == NULL) {
1a8c5c38 818 vty_out(vty, "%*s %-6s %-8s %-17s\n",
819 -wctx->addr_width, buf2, "local",
820 state_str, buf1);
cd233079
CS
821 } else {
822 json_object_string_add(json_row, "type", "local");
1a8c5c38 823 json_object_string_add(json_row, "state", state_str);
cd233079 824 json_object_string_add(json_row, "mac", buf1);
1a8c5c38 825 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
826 json_object_boolean_true_add(
827 json_row, "defaultGateway");
828 json_object_int_add(json_row, "localSequence",
829 n->loc_seq);
830 json_object_int_add(json_row, "remoteSequence",
831 n->rem_seq);
87454e6b
CS
832 json_object_int_add(json_row, "detectionCount",
833 n->dad_count);
834 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
835 json_object_boolean_true_add(json_row,
836 "isDuplicate");
837 else
838 json_object_boolean_false_add(json_row,
839 "isDuplicate");
cd233079 840 }
d62a17ae 841 wctx->count++;
1a8c5c38 842 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
843 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) &&
844 !IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))
845 return;
846
847 if (json_vni == NULL) {
848 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) &&
849 (wctx->count == 0))
850 vty_out(vty,
851 "%*s %-6s %-8s %-17s %-21s\n",
852 -wctx->addr_width, "Neighbor", "Type",
853 "State", "MAC", "Remote VTEP");
854 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
855 -wctx->addr_width, buf2, "remote", state_str,
856 buf1, inet_ntoa(n->r_vtep_ip));
cd233079 857 } else {
1a8c5c38 858 json_object_string_add(json_row, "type", "remote");
859 json_object_string_add(json_row, "state", state_str);
860 json_object_string_add(json_row, "mac", buf1);
861 json_object_string_add(json_row, "remoteVtep",
862 inet_ntoa(n->r_vtep_ip));
863 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
864 json_object_boolean_true_add(json_row,
865 "defaultGateway");
866 json_object_int_add(json_row, "localSequence",
867 n->loc_seq);
868 json_object_int_add(json_row, "remoteSequence",
869 n->rem_seq);
87454e6b
CS
870 json_object_int_add(json_row, "detectionCount",
871 n->dad_count);
872 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
873 json_object_boolean_true_add(json_row,
874 "isDuplicate");
875 else
876 json_object_boolean_false_add(json_row,
877 "isDuplicate");
d62a17ae 878 }
1a8c5c38 879 wctx->count++;
d62a17ae 880 }
cd233079
CS
881
882 if (json_vni)
883 json_object_object_add(json_vni, buf2, json_row);
cec2e17d 884}
885
e3fac919
NS
886/*
887 * Print neighbor hash entry in detail - called for display of all neighbors.
888 */
e3b78da8 889static void zvni_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt)
e3fac919
NS
890{
891 struct vty *vty;
892 json_object *json_vni = NULL, *json_row = NULL;
893 zebra_neigh_t *n;
894 char buf[INET6_ADDRSTRLEN];
895 struct neigh_walk_ctx *wctx = ctxt;
896
897 vty = wctx->vty;
898 json_vni = wctx->json;
e3b78da8 899 n = (zebra_neigh_t *)bucket->data;
e3fac919
NS
900 if (!n)
901 return;
902
903 ipaddr2str(&n->ip, buf, sizeof(buf));
904 if (json_vni)
905 json_row = json_object_new_object();
906
907 zvni_print_neigh(n, vty, json_row);
908
909 if (json_vni)
910 json_object_object_add(json_vni, buf, json_row);
911}
912
cec2e17d 913/*
914 * Print neighbors for all VNI.
915 */
e3b78da8 916static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket,
cd233079 917 void **args)
cec2e17d 918{
d62a17ae 919 struct vty *vty;
cd233079 920 json_object *json = NULL, *json_vni = NULL;
d62a17ae 921 zebra_vni_t *zvni;
d7c0a89a 922 uint32_t num_neigh;
d62a17ae 923 struct neigh_walk_ctx wctx;
cd233079 924 char vni_str[VNI_STR_LEN];
1374d4db 925 uint32_t print_dup;
cd233079
CS
926
927 vty = (struct vty *)args[0];
928 json = (json_object *)args[1];
1374d4db 929 print_dup = (uint32_t)(uintptr_t)args[2];
cec2e17d 930
e3b78da8 931 zvni = (zebra_vni_t *)bucket->data;
9ea660be 932
d62a17ae 933 num_neigh = hashcount(zvni->neigh_table);
1374d4db
CS
934
935 if (print_dup)
936 num_neigh = num_dup_detected_neighs(zvni);
937
68e33151 938 if (json == NULL) {
cd233079
CS
939 vty_out(vty,
940 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
941 zvni->vni, num_neigh);
68e33151 942 } else {
cd233079
CS
943 json_vni = json_object_new_object();
944 json_object_int_add(json_vni, "numArpNd", num_neigh);
945 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
946 }
1374d4db 947
cd233079
CS
948 if (!num_neigh) {
949 if (json)
950 json_object_object_add(json, vni_str, json_vni);
d62a17ae 951 return;
cd233079 952 }
cec2e17d 953
d62a17ae 954 /* Since we have IPv6 addresses to deal with which can vary widely in
955 * size, we try to be a bit more elegant in display by first computing
956 * the maximum width.
957 */
958 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
959 wctx.zvni = zvni;
960 wctx.vty = vty;
961 wctx.addr_width = 15;
cd233079 962 wctx.json = json_vni;
d62a17ae 963 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
cec2e17d 964
68e33151 965 if (json == NULL) {
1a8c5c38 966 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
967 -wctx.addr_width, "IP", "Type",
968 "State", "MAC", "Remote VTEP");
68e33151 969 }
1374d4db
CS
970 if (print_dup)
971 hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash,
972 &wctx);
973 else
974 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
975
976 if (json)
977 json_object_object_add(json, vni_str, json_vni);
cec2e17d 978}
979
e3b78da8 980static void zvni_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt)
1374d4db
CS
981{
982 zebra_neigh_t *nbr;
983
e3b78da8 984 nbr = (zebra_neigh_t *)bucket->data;
1374d4db
CS
985 if (!nbr)
986 return;
987
988 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
e3b78da8 989 zvni_print_neigh_hash(bucket, ctxt);
1374d4db
CS
990}
991
e3b78da8 992static void zvni_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
e3fac919
NS
993 void *ctxt)
994{
995 zebra_neigh_t *nbr;
996
e3b78da8 997 nbr = (zebra_neigh_t *)bucket->data;
e3fac919
NS
998 if (!nbr)
999 return;
1000
1001 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
e3b78da8 1002 zvni_print_neigh_hash_detail(bucket, ctxt);
e3fac919
NS
1003}
1004
1005/*
1006 * Print neighbors for all VNIs in detail.
1007 */
e3b78da8 1008static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket *bucket,
e3fac919
NS
1009 void **args)
1010{
1011 struct vty *vty;
1012 json_object *json = NULL, *json_vni = NULL;
1013 zebra_vni_t *zvni;
1014 uint32_t num_neigh;
1015 struct neigh_walk_ctx wctx;
1016 char vni_str[VNI_STR_LEN];
1017 uint32_t print_dup;
1018
1019 vty = (struct vty *)args[0];
1020 json = (json_object *)args[1];
1021 print_dup = (uint32_t)(uintptr_t)args[2];
1022
e3b78da8 1023 zvni = (zebra_vni_t *)bucket->data;
e3fac919
NS
1024 if (!zvni) {
1025 if (json)
1026 vty_out(vty, "{}\n");
1027 return;
1028 }
1029 num_neigh = hashcount(zvni->neigh_table);
1030
1031 if (print_dup && num_dup_detected_neighs(zvni) == 0)
1032 return;
1033
1034 if (json == NULL) {
1035 vty_out(vty,
1036 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1037 zvni->vni, num_neigh);
1038 } else {
1039 json_vni = json_object_new_object();
1040 json_object_int_add(json_vni, "numArpNd", num_neigh);
1041 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
1042 }
1043 if (!num_neigh) {
1044 if (json)
1045 json_object_object_add(json, vni_str, json_vni);
1046 return;
1047 }
1048
1049 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
1050 wctx.zvni = zvni;
1051 wctx.vty = vty;
1052 wctx.addr_width = 15;
1053 wctx.json = json_vni;
1054
1055 if (print_dup)
1056 hash_iterate(zvni->neigh_table,
1057 zvni_print_dad_neigh_hash_detail, &wctx);
1058 else
1059 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash_detail,
1060 &wctx);
1061
1062 if (json)
1063 json_object_object_add(json, vni_str, json_vni);
1064}
1065
9aa741ea 1066/* print a specific next hop for an l3vni */
996c9314 1067static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
c0e519d3 1068 json_object *json)
9aa741ea
MK
1069{
1070 char buf1[ETHER_ADDR_STRLEN];
1071 char buf2[INET6_ADDRSTRLEN];
c0e519d3 1072 json_object *json_hosts = NULL;
f2a503f0 1073 struct host_rb_entry *hle;
9aa741ea 1074
c0e519d3
MK
1075 if (!json) {
1076 vty_out(vty, "Ip: %s\n",
1077 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1078 vty_out(vty, " RMAC: %s\n",
996c9314 1079 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
f2a503f0
DS
1080 vty_out(vty, " Refcount: %d\n",
1081 rb_host_count(&n->host_rb));
4cce389e 1082 vty_out(vty, " Prefixes:\n");
85442b09 1083 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
c0e519d3 1084 vty_out(vty, " %s\n",
f2a503f0 1085 prefix2str(&hle->p, buf2, sizeof(buf2)));
c0e519d3
MK
1086 } else {
1087 json_hosts = json_object_new_array();
996c9314
LB
1088 json_object_string_add(
1089 json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2)));
1090 json_object_string_add(
1091 json, "routerMac",
1092 prefix_mac2str(&n->emac, buf2, sizeof(buf2)));
f2a503f0
DS
1093 json_object_int_add(json, "refCount",
1094 rb_host_count(&n->host_rb));
85442b09 1095 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
c0e519d3 1096 json_object_array_add(json_hosts,
996c9314 1097 json_object_new_string(prefix2str(
f2a503f0 1098 &hle->p, buf2, sizeof(buf2))));
4cce389e 1099 json_object_object_add(json, "prefixList", json_hosts);
c0e519d3 1100 }
9aa741ea
MK
1101}
1102
1103/* Print a specific RMAC entry */
996c9314 1104static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
316f4ca4 1105 json_object *json)
9aa741ea
MK
1106{
1107 char buf1[ETHER_ADDR_STRLEN];
1108 char buf2[PREFIX_STRLEN];
316f4ca4 1109 json_object *json_hosts = NULL;
5e1b0650 1110 struct host_rb_entry *hle;
9aa741ea 1111
316f4ca4
MK
1112 if (!json) {
1113 vty_out(vty, "MAC: %s\n",
1114 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
1115 vty_out(vty, " Remote VTEP: %s\n",
1116 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
41db76c2 1117 vty_out(vty, " Refcount: %d\n", rb_host_count(&zrmac->host_rb));
4cce389e 1118 vty_out(vty, " Prefixes:\n");
85442b09 1119 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
316f4ca4 1120 vty_out(vty, " %s\n",
5e1b0650 1121 prefix2str(&hle->p, buf2, sizeof(buf2)));
316f4ca4
MK
1122 } else {
1123 json_hosts = json_object_new_array();
996c9314
LB
1124 json_object_string_add(
1125 json, "routerMac",
1126 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
4cce389e 1127 json_object_string_add(json, "vtepIp",
316f4ca4 1128 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
41db76c2
DS
1129 json_object_int_add(json, "refCount",
1130 rb_host_count(&zrmac->host_rb));
1a8c5c38 1131 json_object_int_add(json, "localSequence", zrmac->loc_seq);
1132 json_object_int_add(json, "remoteSequence", zrmac->rem_seq);
85442b09 1133 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
5e1b0650
DS
1134 json_object_array_add(
1135 json_hosts,
1136 json_object_new_string(prefix2str(
1137 &hle->p, buf2, sizeof(buf2))));
4cce389e 1138 json_object_object_add(json, "prefixList", json_hosts);
316f4ca4 1139 }
9aa741ea
MK
1140}
1141
cec2e17d 1142/*
1143 * Print a specific MAC entry.
1144 */
24cdbd0d 1145static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
d62a17ae 1146{
1147 struct vty *vty;
b6938a74
MK
1148 zebra_neigh_t *n = NULL;
1149 struct listnode *node = NULL;
138a4965 1150 char buf1[ETHER_ADDR_STRLEN];
b6938a74 1151 char buf2[INET6_ADDRSTRLEN];
87454e6b
CS
1152 struct zebra_vrf *zvrf;
1153 struct timeval detect_start_time = {0, 0};
1154
6005fe55 1155 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
d62a17ae 1156
1157 vty = (struct vty *)ctxt;
24cdbd0d 1158 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
d62a17ae 1159
24cdbd0d
DS
1160 if (json) {
1161 json_object *json_mac = json_object_new_object();
1162
1163 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1164 struct zebra_ns *zns;
1165 struct interface *ifp;
1166 ifindex_t ifindex;
1167
1168 ifindex = mac->fwd_info.local.ifindex;
1169 zns = zebra_ns_lookup(NS_DEFAULT);
1170 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1171 if (!ifp)
1172 return;
1173 json_object_string_add(json_mac, "type", "local");
1174 json_object_string_add(json_mac, "intf", ifp->name);
1175 json_object_int_add(json_mac, "ifindex", ifindex);
1176 if (mac->fwd_info.local.vid)
1177 json_object_int_add(json_mac, "vlan",
1178 mac->fwd_info.local.vid);
1179 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
1180 json_object_string_add(json_mac, "type", "remote");
1181 json_object_string_add(
1182 json_mac, "remoteVtep",
1183 inet_ntoa(mac->fwd_info.r_vtep_ip));
1184 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
29611019 1185 json_object_string_add(json_mac, "type", "auto");
b6938a74 1186
24cdbd0d
DS
1187 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
1188 json_object_boolean_true_add(json_mac, "stickyMac");
ead40654 1189
24cdbd0d
DS
1190 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
1191 json_object_boolean_true_add(json_mac,
1192 "defaultGateway");
ead40654 1193
24cdbd0d
DS
1194 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
1195 json_object_boolean_true_add(json_mac,
1196 "remoteGatewayMac");
51f4dab4 1197
24cdbd0d
DS
1198 json_object_int_add(json_mac, "localSequence", mac->loc_seq);
1199 json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
f07e1c99 1200
87454e6b
CS
1201 json_object_int_add(json_mac, "detectionCount", mac->dad_count);
1202 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1203 json_object_boolean_true_add(json_mac, "isDuplicate");
1204 else
1205 json_object_boolean_false_add(json_mac, "isDuplicate");
1206
24cdbd0d
DS
1207 /* print all the associated neigh */
1208 if (!listcount(mac->neigh_list))
1209 json_object_string_add(json_mac, "neighbors", "none");
1210 else {
1211 json_object *json_active_nbrs = json_object_new_array();
1212 json_object *json_inactive_nbrs =
1213 json_object_new_array();
1214 json_object *json_nbrs = json_object_new_object();
1215
1216 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
1217 if (IS_ZEBRA_NEIGH_ACTIVE(n))
1218 json_object_array_add(
1219 json_active_nbrs,
1220 json_object_new_string(
1221 ipaddr2str(
1222 &n->ip, buf2,
1223 sizeof(buf2))));
1224 else
1225 json_object_array_add(
1226 json_inactive_nbrs,
1227 json_object_new_string(
1228 ipaddr2str(
1229 &n->ip, buf2,
1230 sizeof(buf2))));
1231 }
1232
1233 json_object_object_add(json_nbrs, "active",
1234 json_active_nbrs);
1235 json_object_object_add(json_nbrs, "inactive",
1236 json_inactive_nbrs);
1237 json_object_object_add(json_mac, "neighbors",
1238 json_nbrs);
b6938a74 1239 }
b6938a74 1240
24cdbd0d 1241 json_object_object_add(json, buf1, json_mac);
24cdbd0d
DS
1242 } else {
1243 vty_out(vty, "MAC: %s\n", buf1);
1244
1245 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1246 struct zebra_ns *zns;
1247 struct interface *ifp;
1248 ifindex_t ifindex;
1249
1250 ifindex = mac->fwd_info.local.ifindex;
1251 zns = zebra_ns_lookup(NS_DEFAULT);
1252 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1253 if (!ifp)
1254 return;
1255 vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex);
1256 if (mac->fwd_info.local.vid)
1257 vty_out(vty, " VLAN: %u",
1258 mac->fwd_info.local.vid);
1259 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
1260 vty_out(vty, " Remote VTEP: %s",
1261 inet_ntoa(mac->fwd_info.r_vtep_ip));
1262 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
1263 vty_out(vty, " Auto Mac ");
1264 }
1265
1266 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
1267 vty_out(vty, " Sticky Mac ");
1268
1269 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
1270 vty_out(vty, " Default-gateway Mac ");
1271
1272 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
1273 vty_out(vty, " Remote-gateway Mac ");
1274
1275 vty_out(vty, "\n");
1276 vty_out(vty, " Local Seq: %u Remote Seq: %u", mac->loc_seq,
1277 mac->rem_seq);
1278 vty_out(vty, "\n");
1279
87454e6b
CS
1280 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
1281 vty_out(vty, " Duplicate, detected at %s",
1282 time_to_string(mac->dad_dup_detect_time));
1283 } else if (mac->dad_count) {
1284 monotime_since(&mac->detect_start_time,
1285 &detect_start_time);
1286 if (detect_start_time.tv_sec <= zvrf->dad_time) {
37a04040
CS
1287 char *buf = time_to_string(
1288 mac->detect_start_time.tv_sec);
87454e6b
CS
1289 char tmp_buf[30];
1290
138a4965 1291 strlcpy(tmp_buf, buf, sizeof(tmp_buf));
87454e6b
CS
1292 vty_out(vty,
1293 " Duplicate detection started at %s, detection count %u\n",
1294 tmp_buf, mac->dad_count);
1295 }
1296 }
1297
24cdbd0d
DS
1298 /* print all the associated neigh */
1299 vty_out(vty, " Neighbors:\n");
1300 if (!listcount(mac->neigh_list))
1301 vty_out(vty, " No Neighbors\n");
1302 else {
1303 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
1304 vty_out(vty, " %s %s\n",
1305 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
1306 (IS_ZEBRA_NEIGH_ACTIVE(n)
1307 ? "Active"
1308 : "Inactive"));
1309 }
1310 }
1311
1312 vty_out(vty, "\n");
1313 }
cec2e17d 1314}
1315
1316/*
1317 * Print MAC hash entry - called for display of all MACs.
1318 */
e3b78da8 1319static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
d62a17ae 1320{
1321 struct vty *vty;
cd233079 1322 json_object *json_mac_hdr = NULL, *json_mac = NULL;
d62a17ae 1323 zebra_mac_t *mac;
138a4965 1324 char buf1[ETHER_ADDR_STRLEN];
d62a17ae 1325 struct mac_walk_ctx *wctx = ctxt;
1326
1327 vty = wctx->vty;
cd233079 1328 json_mac_hdr = wctx->json;
e3b78da8 1329 mac = (zebra_mac_t *)bucket->data;
d62a17ae 1330
1331 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
cd233079
CS
1332
1333 if (json_mac_hdr)
1334 json_mac = json_object_new_object();
1335
1a8c5c38 1336 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
d62a17ae 1337 struct zebra_ns *zns;
1338 ifindex_t ifindex;
1339 struct interface *ifp;
1340 vlanid_t vid;
1341
1a8c5c38 1342 if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
1343 return;
1344
d62a17ae 1345 zns = zebra_ns_lookup(NS_DEFAULT);
1346 ifindex = mac->fwd_info.local.ifindex;
1347 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1348 if (!ifp) // unexpected
1349 return;
1350 vid = mac->fwd_info.local.vid;
cd233079
CS
1351 if (json_mac_hdr == NULL)
1352 vty_out(vty, "%-17s %-6s %-21s", buf1, "local",
1353 ifp->name);
1354 else {
1355 json_object_string_add(json_mac, "type", "local");
1356 json_object_string_add(json_mac, "intf", ifp->name);
1357 }
1358 if (vid) {
1359 if (json_mac_hdr == NULL)
1360 vty_out(vty, " %-5u", vid);
1361 else
1362 json_object_int_add(json_mac, "vlan", vid);
1363 }
1a8c5c38 1364 if (json_mac_hdr == NULL) {
cd233079 1365 vty_out(vty, "\n");
1a8c5c38 1366 } else {
1367 json_object_int_add(json_mac, "localSequence",
1368 mac->loc_seq);
1369 json_object_int_add(json_mac, "remoteSequence",
1370 mac->rem_seq);
87454e6b
CS
1371 json_object_int_add(json_mac, "detectionCount",
1372 mac->dad_count);
1373 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1374 json_object_boolean_true_add(json_mac,
1375 "isDuplicate");
1376 else
1377 json_object_boolean_false_add(json_mac,
1378 "isDuplicate");
cd233079 1379 json_object_object_add(json_mac_hdr, buf1, json_mac);
1a8c5c38 1380 }
1381
d62a17ae 1382 wctx->count++;
1a8c5c38 1383
b6938a74 1384 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
1a8c5c38 1385
1386 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) &&
1387 !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
1388 &wctx->r_vtep_ip))
1389 return;
1390
1391 if (json_mac_hdr == NULL) {
1392 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) &&
1393 (wctx->count == 0)) {
1394 vty_out(vty, "\nVNI %u\n\n", wctx->zvni->vni);
1395 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC",
1396 "Type", "Intf/Remote VTEP", "VLAN");
d62a17ae 1397 }
1a8c5c38 1398 vty_out(vty, "%-17s %-6s %-21s\n", buf1, "remote",
1399 inet_ntoa(mac->fwd_info.r_vtep_ip));
d62a17ae 1400 } else {
1a8c5c38 1401 json_object_string_add(json_mac, "type", "remote");
1402 json_object_string_add(json_mac, "remoteVtep",
cd233079 1403 inet_ntoa(mac->fwd_info.r_vtep_ip));
1a8c5c38 1404 json_object_object_add(json_mac_hdr, buf1, json_mac);
1405 json_object_int_add(json_mac, "localSequence",
1406 mac->loc_seq);
1407 json_object_int_add(json_mac, "remoteSequence",
1408 mac->rem_seq);
87454e6b
CS
1409 json_object_int_add(json_mac, "detectionCount",
1410 mac->dad_count);
1411 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1412 json_object_boolean_true_add(json_mac,
1413 "isDuplicate");
1414 else
1415 json_object_boolean_false_add(json_mac,
1416 "isDuplicate");
1417
d62a17ae 1418 }
1a8c5c38 1419
1420 wctx->count++;
d62a17ae 1421 }
cec2e17d 1422}
1423
1374d4db 1424/* Print Duplicate MAC */
e3b78da8 1425static void zvni_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
1374d4db
CS
1426{
1427 zebra_mac_t *mac;
1428
e3b78da8 1429 mac = (zebra_mac_t *)bucket->data;
1374d4db
CS
1430 if (!mac)
1431 return;
1432
1433 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
e3b78da8 1434 zvni_print_mac_hash(bucket, ctxt);
1374d4db
CS
1435}
1436
cffe7580
NS
1437/*
1438 * Print MAC hash entry in detail - called for display of all MACs.
1439 */
e3b78da8 1440static void zvni_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
cffe7580
NS
1441{
1442 struct vty *vty;
1443 json_object *json_mac_hdr = NULL;
1444 zebra_mac_t *mac;
1445 struct mac_walk_ctx *wctx = ctxt;
138a4965 1446 char buf1[ETHER_ADDR_STRLEN];
cffe7580
NS
1447
1448 vty = wctx->vty;
1449 json_mac_hdr = wctx->json;
e3b78da8 1450 mac = (zebra_mac_t *)bucket->data;
cffe7580
NS
1451 if (!mac)
1452 return;
1453
1454 wctx->count++;
1455 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
1456
1457 zvni_print_mac(mac, vty, json_mac_hdr);
1458}
1459
1460/* Print Duplicate MAC in detail */
e3b78da8 1461static void zvni_print_dad_mac_hash_detail(struct hash_bucket *bucket,
cffe7580
NS
1462 void *ctxt)
1463{
1464 zebra_mac_t *mac;
1465
e3b78da8 1466 mac = (zebra_mac_t *)bucket->data;
cffe7580
NS
1467 if (!mac)
1468 return;
1469
1470 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
e3b78da8 1471 zvni_print_mac_hash_detail(bucket, ctxt);
cffe7580
NS
1472}
1473
cec2e17d 1474/*
1475 * Print MACs for all VNI.
1476 */
e3b78da8 1477static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt)
cec2e17d 1478{
d62a17ae 1479 struct vty *vty;
cd233079
CS
1480 json_object *json = NULL, *json_vni = NULL;
1481 json_object *json_mac = NULL;
d62a17ae 1482 zebra_vni_t *zvni;
d7c0a89a 1483 uint32_t num_macs;
d62a17ae 1484 struct mac_walk_ctx *wctx = ctxt;
cd233079 1485 char vni_str[VNI_STR_LEN];
cec2e17d 1486
d62a17ae 1487 vty = (struct vty *)wctx->vty;
cd233079 1488 json = (struct json_object *)wctx->json;
cec2e17d 1489
e3b78da8 1490 zvni = (zebra_vni_t *)bucket->data;
d62a17ae 1491 wctx->zvni = zvni;
cec2e17d 1492
d62a17ae 1493 /*We are iterating over a new VNI, set the count to 0*/
1494 wctx->count = 0;
cec2e17d 1495
790f8dc5 1496 num_macs = num_valid_macs(zvni);
d62a17ae 1497 if (!num_macs)
1498 return;
cd233079 1499
1374d4db
CS
1500 if (wctx->print_dup)
1501 num_macs = num_dup_detected_macs(zvni);
1502
cd233079
CS
1503 if (json) {
1504 json_vni = json_object_new_object();
1505 json_mac = json_object_new_object();
1506 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
d62a17ae 1507 }
cec2e17d 1508
cd233079
CS
1509 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
1510 if (json == NULL) {
1511 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
1512 zvni->vni, num_macs);
1513 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1514 "Intf/Remote VTEP", "VLAN");
1515 } else
1516 json_object_int_add(json_vni, "numMacs", num_macs);
1517 }
1374d4db
CS
1518
1519 if (!num_macs) {
1520 if (json) {
1521 json_object_int_add(json_vni, "numMacs", num_macs);
1522 json_object_object_add(json, vni_str, json_vni);
1523 }
1524 return;
1525 }
1526
cd233079
CS
1527 /* assign per-vni to wctx->json object to fill macs
1528 * under the vni. Re-assign primary json object to fill
1529 * next vni information.
1530 */
1531 wctx->json = json_mac;
1374d4db
CS
1532 if (wctx->print_dup)
1533 hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, wctx);
1534 else
1535 hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
cd233079
CS
1536 wctx->json = json;
1537 if (json) {
1538 if (wctx->count)
1539 json_object_object_add(json_vni, "macs", json_mac);
1540 json_object_object_add(json, vni_str, json_vni);
1541 }
cec2e17d 1542}
1543
cffe7580
NS
1544/*
1545 * Print MACs in detail for all VNI.
1546 */
e3b78da8 1547static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket *bucket,
cffe7580
NS
1548 void *ctxt)
1549{
1550 struct vty *vty;
1551 json_object *json = NULL, *json_vni = NULL;
1552 json_object *json_mac = NULL;
1553 zebra_vni_t *zvni;
1554 uint32_t num_macs;
1555 struct mac_walk_ctx *wctx = ctxt;
1556 char vni_str[VNI_STR_LEN];
1557
1558 vty = (struct vty *)wctx->vty;
1559 json = (struct json_object *)wctx->json;
1560
e3b78da8 1561 zvni = (zebra_vni_t *)bucket->data;
cffe7580
NS
1562 if (!zvni) {
1563 if (json)
1564 vty_out(vty, "{}\n");
1565 return;
1566 }
1567 wctx->zvni = zvni;
1568
1569 /*We are iterating over a new VNI, set the count to 0*/
1570 wctx->count = 0;
1571
1572 num_macs = num_valid_macs(zvni);
1573 if (!num_macs)
1574 return;
1575
1576 if (wctx->print_dup && (num_dup_detected_macs(zvni) == 0))
1577 return;
1578
1579 if (json) {
1580 json_vni = json_object_new_object();
1581 json_mac = json_object_new_object();
1582 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
1583 }
1584
1585 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
1586 if (json == NULL) {
1587 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
1588 zvni->vni, num_macs);
1589 } else
1590 json_object_int_add(json_vni, "numMacs", num_macs);
1591 }
1592 /* assign per-vni to wctx->json object to fill macs
1593 * under the vni. Re-assign primary json object to fill
1594 * next vni information.
1595 */
1596 wctx->json = json_mac;
1597 if (wctx->print_dup)
1598 hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash_detail,
1599 wctx);
1600 else
1601 hash_iterate(zvni->mac_table, zvni_print_mac_hash_detail, wctx);
1602 wctx->json = json;
1603 if (json) {
1604 if (wctx->count)
1605 json_object_object_add(json_vni, "macs", json_mac);
1606 json_object_object_add(json, vni_str, json_vni);
1607 }
1608}
1609
e3b78da8 1610static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx)
b7cfce93
MK
1611{
1612 struct nh_walk_ctx *wctx = NULL;
1613 struct vty *vty = NULL;
32798965 1614 struct json_object *json_vni = NULL;
b7cfce93
MK
1615 struct json_object *json_nh = NULL;
1616 zebra_neigh_t *n = NULL;
1617 char buf1[ETHER_ADDR_STRLEN];
2dbad57f 1618 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
1619
1620 wctx = (struct nh_walk_ctx *)ctx;
1621 vty = wctx->vty;
32798965
MK
1622 json_vni = wctx->json;
1623 if (json_vni)
b7cfce93 1624 json_nh = json_object_new_object();
e3b78da8 1625 n = (zebra_neigh_t *)bucket->data;
b7cfce93 1626
32798965 1627 if (!json_vni) {
4cce389e 1628 vty_out(vty, "%-15s %-17s\n",
2dbad57f 1629 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
4cce389e 1630 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
b7cfce93 1631 } else {
4cce389e 1632 json_object_string_add(json_nh, "nexthopIp",
32798965 1633 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
996c9314
LB
1634 json_object_string_add(
1635 json_nh, "routerMac",
1636 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
32798965
MK
1637 json_object_object_add(json_vni,
1638 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
1639 json_nh);
b7cfce93
MK
1640 }
1641}
1642
e3b78da8 1643static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket,
32798965 1644 void **args)
2dbad57f 1645{
1646 struct vty *vty = NULL;
1647 json_object *json = NULL;
1648 json_object *json_vni = NULL;
2dbad57f 1649 zebra_l3vni_t *zl3vni = NULL;
1650 uint32_t num_nh = 0;
32798965 1651 struct nh_walk_ctx wctx;
2dbad57f 1652 char vni_str[VNI_STR_LEN];
1653
32798965
MK
1654 vty = (struct vty *)args[0];
1655 json = (struct json_object *)args[1];
2dbad57f 1656
e3b78da8 1657 zl3vni = (zebra_l3vni_t *)bucket->data;
2dbad57f 1658
1659 num_nh = hashcount(zl3vni->nh_table);
1660 if (!num_nh)
1661 return;
1662
1663 if (json) {
1664 json_vni = json_object_new_object();
2dbad57f 1665 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1666 }
1667
1668 if (json == NULL) {
996c9314 1669 vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh);
4cce389e 1670 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
2dbad57f 1671 } else
4cce389e 1672 json_object_int_add(json_vni, "numNextHops", num_nh);
2dbad57f 1673
32798965
MK
1674 memset(&wctx, 0, sizeof(struct nh_walk_ctx));
1675 wctx.vty = vty;
1676 wctx.json = json_vni;
1677 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
1678 if (json)
2dbad57f 1679 json_object_object_add(json, vni_str, json_vni);
2dbad57f 1680}
1681
e3b78da8 1682static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket,
c0b4eaa4 1683 void **args)
b7cfce93
MK
1684{
1685 struct vty *vty = NULL;
1686 json_object *json = NULL;
1687 json_object *json_vni = NULL;
b7cfce93 1688 zebra_l3vni_t *zl3vni = NULL;
d7c0a89a 1689 uint32_t num_rmacs;
c0b4eaa4 1690 struct rmac_walk_ctx wctx;
b7cfce93
MK
1691 char vni_str[VNI_STR_LEN];
1692
c0b4eaa4
MK
1693 vty = (struct vty *)args[0];
1694 json = (struct json_object *)args[1];
b7cfce93 1695
e3b78da8 1696 zl3vni = (zebra_l3vni_t *)bucket->data;
b7cfce93
MK
1697
1698 num_rmacs = hashcount(zl3vni->rmac_table);
1699 if (!num_rmacs)
1700 return;
1701
1702 if (json) {
1703 json_vni = json_object_new_object();
b7cfce93
MK
1704 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1705 }
1706
1707 if (json == NULL) {
996c9314 1708 vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs);
4cce389e 1709 vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
b7cfce93
MK
1710 } else
1711 json_object_int_add(json_vni, "numRmacs", num_rmacs);
1712
1713 /* assign per-vni to wctx->json object to fill macs
1714 * under the vni. Re-assign primary json object to fill
1715 * next vni information.
1716 */
c0b4eaa4
MK
1717 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
1718 wctx.vty = vty;
1719 wctx.json = json_vni;
1720 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
1721 if (json)
b7cfce93 1722 json_object_object_add(json, vni_str, json_vni);
b7cfce93
MK
1723}
1724
e3b78da8 1725static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx)
b7cfce93
MK
1726{
1727 zebra_mac_t *zrmac = NULL;
1728 struct rmac_walk_ctx *wctx = NULL;
1729 struct vty *vty = NULL;
1730 struct json_object *json = NULL;
1731 struct json_object *json_rmac = NULL;
1732 char buf[ETHER_ADDR_STRLEN];
1733
1734 wctx = (struct rmac_walk_ctx *)ctx;
1735 vty = wctx->vty;
1736 json = wctx->json;
1737 if (json)
1738 json_rmac = json_object_new_object();
e3b78da8 1739 zrmac = (zebra_mac_t *)bucket->data;
b7cfce93
MK
1740
1741 if (!json) {
4cce389e 1742 vty_out(vty, "%-17s %-21s\n",
b7cfce93 1743 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
996c9314 1744 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
b7cfce93 1745 } else {
996c9314
LB
1746 json_object_string_add(
1747 json_rmac, "routerMac",
1748 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
4cce389e 1749 json_object_string_add(json_rmac, "vtepIp",
b7cfce93 1750 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
996c9314
LB
1751 json_object_object_add(
1752 json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
1753 json_rmac);
b7cfce93
MK
1754 }
1755}
1756
1757/* print a specific L3 VNI entry */
1758static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx)
1759{
1760 char buf[ETHER_ADDR_STRLEN];
1761 struct vty *vty = NULL;
1762 json_object *json = NULL;
1763 zebra_vni_t *zvni = NULL;
1764 json_object *json_vni_list = NULL;
1765 struct listnode *node = NULL, *nnode = NULL;
1766
1767 vty = ctx[0];
1768 json = ctx[1];
1769
1770 if (!json) {
1771 vty_out(vty, "VNI: %u\n", zl3vni->vni);
4cce389e 1772 vty_out(vty, " Type: %s\n", "L3");
996c9314 1773 vty_out(vty, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
4cce389e 1774 vty_out(vty, " Local Vtep Ip: %s\n",
b67a60d2 1775 inet_ntoa(zl3vni->local_vtep_ip));
b7cfce93
MK
1776 vty_out(vty, " Vxlan-Intf: %s\n",
1777 zl3vni_vxlan_if_name(zl3vni));
996c9314
LB
1778 vty_out(vty, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni));
1779 vty_out(vty, " State: %s\n", zl3vni_state2str(zl3vni));
c48d9f5f 1780 vty_out(vty, " VNI Filter: %s\n",
996c9314
LB
1781 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
1782 ? "prefix-routes-only"
1783 : "none");
4cce389e 1784 vty_out(vty, " Router MAC: %s\n",
b7cfce93 1785 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 1786 vty_out(vty, " L2 VNIs: ");
b7cfce93
MK
1787 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni))
1788 vty_out(vty, "%u ", zvni->vni);
1789 vty_out(vty, "\n");
1790 } else {
1791 json_vni_list = json_object_new_array();
1792 json_object_int_add(json, "vni", zl3vni->vni);
4cce389e
MK
1793 json_object_string_add(json, "type", "L3");
1794 json_object_string_add(json, "localVtepIp",
b67a60d2 1795 inet_ntoa(zl3vni->local_vtep_ip));
4cce389e 1796 json_object_string_add(json, "vxlanIntf",
b7cfce93 1797 zl3vni_vxlan_if_name(zl3vni));
4cce389e 1798 json_object_string_add(json, "sviIntf",
b7cfce93 1799 zl3vni_svi_if_name(zl3vni));
996c9314
LB
1800 json_object_string_add(json, "state", zl3vni_state2str(zl3vni));
1801 json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
1802 json_object_string_add(
1803 json, "routerMac",
1804 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
1805 json_object_string_add(
1806 json, "vniFilter",
1807 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
1808 ? "prefix-routes-only"
1809 : "none");
b7cfce93
MK
1810 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni)) {
1811 json_object_array_add(json_vni_list,
1812 json_object_new_int(zvni->vni));
1813 }
4cce389e 1814 json_object_object_add(json, "l2Vnis", json_vni_list);
b7cfce93
MK
1815 }
1816}
1817
cec2e17d 1818/*
1819 * Print a specific VNI entry.
1820 */
cd233079 1821static void zvni_print(zebra_vni_t *zvni, void **ctxt)
d62a17ae 1822{
1823 struct vty *vty;
1824 zebra_vtep_t *zvtep;
d7c0a89a
QY
1825 uint32_t num_macs;
1826 uint32_t num_neigh;
cd233079
CS
1827 json_object *json = NULL;
1828 json_object *json_vtep_list = NULL;
1829 json_object *json_ip_str = NULL;
d62a17ae 1830
cd233079
CS
1831 vty = ctxt[0];
1832 json = ctxt[1];
1833
b7cfce93 1834 if (json == NULL) {
cd233079 1835 vty_out(vty, "VNI: %u\n", zvni->vni);
4cce389e
MK
1836 vty_out(vty, " Type: %s\n", "L2");
1837 vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zvni->vrf_id));
b7cfce93 1838 } else {
cd233079 1839 json_object_int_add(json, "vni", zvni->vni);
4cce389e 1840 json_object_string_add(json, "type", "L2");
b7cfce93
MK
1841 json_object_string_add(json, "vrf",
1842 vrf_id_to_name(zvni->vrf_id));
1843 }
d62a17ae 1844
d62a17ae 1845 if (!zvni->vxlan_if) { // unexpected
cd233079
CS
1846 if (json == NULL)
1847 vty_out(vty, " VxLAN interface: unknown\n");
d62a17ae 1848 return;
1849 }
790f8dc5 1850 num_macs = num_valid_macs(zvni);
cd233079 1851 num_neigh = hashcount(zvni->neigh_table);
4cce389e 1852 if (json == NULL) {
996c9314 1853 vty_out(vty, " VxLAN interface: %s\n", zvni->vxlan_if->name);
4cce389e 1854 vty_out(vty, " VxLAN ifIndex: %u\n", zvni->vxlan_if->ifindex);
996c9314 1855 vty_out(vty, " Local VTEP IP: %s\n",
cd233079 1856 inet_ntoa(zvni->local_vtep_ip));
4cce389e 1857 } else {
cd233079
CS
1858 json_object_string_add(json, "vxlanInterface",
1859 zvni->vxlan_if->name);
1860 json_object_int_add(json, "ifindex", zvni->vxlan_if->ifindex);
1861 json_object_string_add(json, "vtepIp",
1862 inet_ntoa(zvni->local_vtep_ip));
ddd16ed5
MK
1863 json_object_string_add(json, "advertiseGatewayMacip",
1864 zvni->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
1865 json_object_int_add(json, "numMacs", num_macs);
1866 json_object_int_add(json, "numArpNd", num_neigh);
1867 }
d62a17ae 1868 if (!zvni->vteps) {
cd233079
CS
1869 if (json == NULL)
1870 vty_out(vty, " No remote VTEPs known for this VNI\n");
d62a17ae 1871 } else {
cd233079
CS
1872 if (json == NULL)
1873 vty_out(vty, " Remote VTEPs for this VNI:\n");
1874 else
1875 json_vtep_list = json_object_new_array();
1876 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
1877 if (json == NULL)
1878 vty_out(vty, " %s\n",
1879 inet_ntoa(zvtep->vtep_ip));
1880 else {
1881 json_ip_str = json_object_new_string(
1882 inet_ntoa(zvtep->vtep_ip));
1883 json_object_array_add(json_vtep_list,
1884 json_ip_str);
1885 }
1886 }
1887 if (json)
1888 json_object_object_add(json, "numRemoteVteps",
1889 json_vtep_list);
1890 }
1891 if (json == NULL) {
1892 vty_out(vty,
1893 " Number of MACs (local and remote) known for this VNI: %u\n",
1894 num_macs);
1895 vty_out(vty,
1896 " Number of ARPs (IPv4 and IPv6, local and remote) "
1897 "known for this VNI: %u\n",
1898 num_neigh);
ddd16ed5
MK
1899 vty_out(vty, " Advertise-gw-macip: %s\n",
1900 zvni->advertise_gw_macip ? "Yes" : "No");
d62a17ae 1901 }
cec2e17d 1902}
1903
b7cfce93 1904/* print a L3 VNI hash entry */
e3b78da8 1905static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])
b7cfce93 1906{
b7cfce93
MK
1907 struct vty *vty = NULL;
1908 json_object *json = NULL;
51d8de8f 1909 json_object *json_vni = NULL;
b7cfce93
MK
1910 zebra_l3vni_t *zl3vni = NULL;
1911
51d8de8f
MK
1912 vty = (struct vty *)ctx[0];
1913 json = (json_object *)ctx[1];
b7cfce93 1914
e3b78da8 1915 zl3vni = (zebra_l3vni_t *)bucket->data;
b7cfce93
MK
1916
1917 if (!json) {
996c9314
LB
1918 vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1919 zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni),
4cce389e 1920 hashcount(zl3vni->rmac_table),
996c9314 1921 hashcount(zl3vni->nh_table), "n/a",
4cce389e 1922 zl3vni_vrf_name(zl3vni));
b7cfce93 1923 } else {
51d8de8f
MK
1924 char vni_str[VNI_STR_LEN];
1925
1926 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1927 json_vni = json_object_new_object();
1928 json_object_int_add(json_vni, "vni", zl3vni->vni);
4cce389e 1929 json_object_string_add(json_vni, "vxlanIf",
b7cfce93 1930 zl3vni_vxlan_if_name(zl3vni));
4cce389e
MK
1931 json_object_int_add(json_vni, "numMacs",
1932 hashcount(zl3vni->rmac_table));
1933 json_object_int_add(json_vni, "numArpNd",
1934 hashcount(zl3vni->nh_table));
1935 json_object_string_add(json_vni, "numRemoteVteps", "n/a");
1936 json_object_string_add(json_vni, "type", "L3");
1937 json_object_string_add(json_vni, "tenantVrf",
b7cfce93 1938 zl3vni_vrf_name(zl3vni));
51d8de8f 1939 json_object_object_add(json, vni_str, json_vni);
b7cfce93 1940 }
b7cfce93
MK
1941}
1942
09af6961
NS
1943/* Private Structure to pass callback data for hash iterator */
1944struct zvni_evpn_show {
1945 struct vty *vty;
1946 json_object *json;
1947 struct zebra_vrf *zvrf;
1948};
1949
1950/* print a L3 VNI hash entry in detail*/
e3b78da8 1951static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)
09af6961
NS
1952{
1953 struct vty *vty = NULL;
1954 zebra_l3vni_t *zl3vni = NULL;
1955 json_object *json = NULL;
1956 bool use_json = false;
1957 struct zvni_evpn_show *zes = data;
1958
1959 vty = zes->vty;
1960 json = zes->json;
1961
1962 if (json)
1963 use_json = true;
1964
e3b78da8 1965 zl3vni = (zebra_l3vni_t *)bucket->data;
09af6961
NS
1966
1967 zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni, use_json);
1968 vty_out(vty, "\n");
1969}
1970
1971
cec2e17d 1972/*
1973 * Print a VNI hash entry - called for display of all VNIs.
1974 */
e3b78da8 1975static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[])
cec2e17d 1976{
d62a17ae 1977 struct vty *vty;
1978 zebra_vni_t *zvni;
1979 zebra_vtep_t *zvtep;
d7c0a89a
QY
1980 uint32_t num_vteps = 0;
1981 uint32_t num_macs = 0;
1982 uint32_t num_neigh = 0;
cd233079
CS
1983 json_object *json = NULL;
1984 json_object *json_vni = NULL;
1985 json_object *json_ip_str = NULL;
1986 json_object *json_vtep_list = NULL;
1987
1988 vty = ctxt[0];
1989 json = ctxt[1];
cec2e17d 1990
e3b78da8 1991 zvni = (zebra_vni_t *)bucket->data;
cec2e17d 1992
d62a17ae 1993 zvtep = zvni->vteps;
1994 while (zvtep) {
1995 num_vteps++;
1996 zvtep = zvtep->next;
1997 }
cec2e17d 1998
790f8dc5 1999 num_macs = num_valid_macs(zvni);
d62a17ae 2000 num_neigh = hashcount(zvni->neigh_table);
cd233079 2001 if (json == NULL)
996c9314 2002 vty_out(vty, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
4cce389e 2003 zvni->vni, "L2",
cd233079 2004 zvni->vxlan_if ? zvni->vxlan_if->name : "unknown",
996c9314 2005 num_macs, num_neigh, num_vteps,
b7cfce93 2006 vrf_id_to_name(zvni->vrf_id));
cd233079
CS
2007 else {
2008 char vni_str[VNI_STR_LEN];
2009 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
2010 json_vni = json_object_new_object();
4cce389e
MK
2011 json_object_int_add(json_vni, "vni", zvni->vni);
2012 json_object_string_add(json_vni, "type", "L2");
cd233079
CS
2013 json_object_string_add(json_vni, "vxlanIf",
2014 zvni->vxlan_if ? zvni->vxlan_if->name
2015 : "unknown");
cd233079
CS
2016 json_object_int_add(json_vni, "numMacs", num_macs);
2017 json_object_int_add(json_vni, "numArpNd", num_neigh);
2018 json_object_int_add(json_vni, "numRemoteVteps", num_vteps);
4cce389e
MK
2019 json_object_string_add(json_vni, "tenantVrf",
2020 vrf_id_to_name(zvni->vrf_id));
cd233079
CS
2021 if (num_vteps) {
2022 json_vtep_list = json_object_new_array();
2023 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2024 json_ip_str = json_object_new_string(
2025 inet_ntoa(zvtep->vtep_ip));
2026 json_object_array_add(json_vtep_list,
2027 json_ip_str);
2028 }
2029 json_object_object_add(json_vni, "remoteVteps",
2030 json_vtep_list);
2031 }
2032 json_object_object_add(json, vni_str, json_vni);
2033 }
cec2e17d 2034}
2035
09af6961
NS
2036/*
2037 * Print a VNI hash entry in detail - called for display of all VNIs.
2038 */
e3b78da8 2039static void zvni_print_hash_detail(struct hash_bucket *bucket, void *data)
09af6961
NS
2040{
2041 struct vty *vty;
2042 zebra_vni_t *zvni;
2043 json_object *json = NULL;
2044 bool use_json = false;
2045 struct zvni_evpn_show *zes = data;
2046
2047 vty = zes->vty;
2048 json = zes->json;
2049
2050 if (json)
2051 use_json = true;
2052
e3b78da8 2053 zvni = (zebra_vni_t *)bucket->data;
09af6961
NS
2054
2055 zebra_vxlan_print_vni(vty, zes->zvrf, zvni->vni, use_json);
2056 vty_out(vty, "\n");
2057}
2058
13d60d35 2059/*
2232a77c 2060 * Inform BGP about local MACIP.
2061 */
996c9314 2062static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
d7c0a89a 2063 struct ipaddr *ip, uint8_t flags,
2c476b72 2064 uint32_t seq, int state, uint16_t cmd)
d62a17ae 2065{
d62a17ae 2066 char buf[ETHER_ADDR_STRLEN];
2067 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
2068 int ipa_len;
2069 struct zserv *client = NULL;
2070 struct stream *s = NULL;
d62a17ae 2071
21ccc0cf 2072 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
d62a17ae 2073 /* BGP may not be running. */
2074 if (!client)
2075 return 0;
2076
1002497a 2077 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
d62a17ae 2078
7cf15b25 2079 zclient_create_header(s, cmd, VRF_DEFAULT);
d62a17ae 2080 stream_putl(s, vni);
ff8b7eb8 2081 stream_put(s, macaddr->octet, ETH_ALEN);
d62a17ae 2082 if (ip) {
2083 ipa_len = 0;
2084 if (IS_IPADDR_V4(ip))
2085 ipa_len = IPV4_MAX_BYTELEN;
2086 else if (IS_IPADDR_V6(ip))
2087 ipa_len = IPV6_MAX_BYTELEN;
2088
2089 stream_putl(s, ipa_len); /* IP address length */
2090 if (ipa_len)
2091 stream_put(s, &ip->ip.addr, ipa_len); /* IP address */
2092 } else
2093 stream_putl(s, 0); /* Just MAC. */
2094
f07e1c99 2095 if (cmd == ZEBRA_MACIP_ADD) {
2096 stream_putc(s, flags); /* sticky mac/gateway mac */
2097 stream_putl(s, seq); /* sequence number */
2c476b72
AK
2098 } else {
2099 stream_putl(s, state); /* state - active/inactive */
f07e1c99 2100 }
d62a17ae 2101
b7cfce93 2102
d62a17ae 2103 /* Write packet size. */
2104 stream_putw_at(s, 0, stream_get_endp(s));
2105
2106 if (IS_ZEBRA_DEBUG_VXLAN)
1a98c087 2107 zlog_debug(
f07e1c99 2108 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
996c9314
LB
2109 (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags,
2110 prefix_mac2str(macaddr, buf, sizeof(buf)),
f07e1c99 2111 ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni,
1a98c087 2112 zebra_route_string(client->proto));
d62a17ae 2113
2114 if (cmd == ZEBRA_MACIP_ADD)
2115 client->macipadd_cnt++;
2116 else
2117 client->macipdel_cnt++;
2118
21ccc0cf 2119 return zserv_send_message(client, s);
2232a77c 2120}
2121
2122/*
2123 * Make hash key for neighbors.
13d60d35 2124 */
d62a17ae 2125static unsigned int neigh_hash_keymake(void *p)
13d60d35 2126{
d62a17ae 2127 zebra_neigh_t *n = p;
2128 struct ipaddr *ip = &n->ip;
13d60d35 2129
d62a17ae 2130 if (IS_IPADDR_V4(ip))
2131 return jhash_1word(ip->ipaddr_v4.s_addr, 0);
2232a77c 2132
d62a17ae 2133 return jhash2(ip->ipaddr_v6.s6_addr32,
2134 ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0);
13d60d35 2135}
2136
2137/*
2232a77c 2138 * Compare two neighbor hash structures.
13d60d35 2139 */
74df8d6d 2140static bool neigh_cmp(const void *p1, const void *p2)
13d60d35 2141{
d62a17ae 2142 const zebra_neigh_t *n1 = p1;
2143 const zebra_neigh_t *n2 = p2;
13d60d35 2144
d62a17ae 2145 if (n1 == NULL && n2 == NULL)
74df8d6d 2146 return true;
2232a77c 2147
d62a17ae 2148 if (n1 == NULL || n2 == NULL)
74df8d6d 2149 return false;
2232a77c 2150
d62a17ae 2151 return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0);
13d60d35 2152}
2153
27fa3398
DS
2154static int neigh_list_cmp(void *p1, void *p2)
2155{
2156 const zebra_neigh_t *n1 = p1;
2157 const zebra_neigh_t *n2 = p2;
2158
2159 return memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr));
2160}
2161
13d60d35 2162/*
2232a77c 2163 * Callback to allocate neighbor hash entry.
13d60d35 2164 */
d62a17ae 2165static void *zvni_neigh_alloc(void *p)
13d60d35 2166{
d62a17ae 2167 const zebra_neigh_t *tmp_n = p;
2168 zebra_neigh_t *n;
13d60d35 2169
d62a17ae 2170 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
2171 *n = *tmp_n;
2232a77c 2172
d62a17ae 2173 return ((void *)n);
13d60d35 2174}
2175
2176/*
2232a77c 2177 * Add neighbor entry.
13d60d35 2178 */
b6938a74
MK
2179static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
2180 struct ethaddr *mac)
13d60d35 2181{
d62a17ae 2182 zebra_neigh_t tmp_n;
2183 zebra_neigh_t *n = NULL;
b6938a74 2184 zebra_mac_t *zmac = NULL;
13d60d35 2185
d62a17ae 2186 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
2187 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
2188 n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
2189 assert(n);
13d60d35 2190
b6938a74
MK
2191 memcpy(&n->emac, mac, ETH_ALEN);
2192 n->state = ZEBRA_NEIGH_INACTIVE;
2193
2194 /* Associate the neigh to mac */
2195 zmac = zvni_mac_lookup(zvni, mac);
2196 if (zmac)
2197 listnode_add_sort(zmac->neigh_list, n);
2198
d62a17ae 2199 return n;
13d60d35 2200}
2201
2202/*
2232a77c 2203 * Delete neighbor entry.
13d60d35 2204 */
d62a17ae 2205static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
13d60d35 2206{
d62a17ae 2207 zebra_neigh_t *tmp_n;
b6938a74
MK
2208 zebra_mac_t *zmac = NULL;
2209
2210 zmac = zvni_mac_lookup(zvni, &n->emac);
2211 if (zmac)
2212 listnode_delete(zmac->neigh_list, n);
13d60d35 2213
d62a17ae 2214 /* Free the VNI hash entry and allocated memory. */
2215 tmp_n = hash_release(zvni->neigh_table, n);
0a22ddfb 2216 XFREE(MTYPE_NEIGH, tmp_n);
13d60d35 2217
d62a17ae 2218 return 0;
13d60d35 2219}
2220
2221/*
2232a77c 2222 * Free neighbor hash entry (callback)
13d60d35 2223 */
e3b78da8 2224static void zvni_neigh_del_hash_entry(struct hash_bucket *bucket, void *arg)
13d60d35 2225{
d62a17ae 2226 struct neigh_walk_ctx *wctx = arg;
e3b78da8 2227 zebra_neigh_t *n = bucket->data;
2232a77c 2228
d62a17ae 2229 if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL))
2230 || ((wctx->flags & DEL_REMOTE_NEIGH)
2231 && (n->flags & ZEBRA_NEIGH_REMOTE))
2232 || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP)
2233 && (n->flags & ZEBRA_NEIGH_REMOTE)
2234 && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
2235 if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
2853fed6 2236 zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
2c476b72 2237 &n->emac, 0, n->state);
13d60d35 2238
d62a17ae 2239 if (wctx->uninstall)
2240 zvni_neigh_uninstall(wctx->zvni, n);
13d60d35 2241
b1599bb6 2242 zvni_neigh_del(wctx->zvni, n);
d62a17ae 2243 }
13d60d35 2244
b1599bb6 2245 return;
13d60d35 2246}
2247
2248/*
2232a77c 2249 * Delete all neighbor entries from specific VTEP for a particular VNI.
13d60d35 2250 */
d62a17ae 2251static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
2252 struct in_addr *r_vtep_ip)
13d60d35 2253{
d62a17ae 2254 struct neigh_walk_ctx wctx;
13d60d35 2255
d62a17ae 2256 if (!zvni->neigh_table)
2257 return;
13d60d35 2258
d62a17ae 2259 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2260 wctx.zvni = zvni;
2261 wctx.uninstall = uninstall;
2262 wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP;
2263 wctx.r_vtep_ip = *r_vtep_ip;
13d60d35 2264
b1599bb6 2265 hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx);
2232a77c 2266}
13d60d35 2267
2232a77c 2268/*
2269 * Delete all neighbor entries for this VNI.
2270 */
996c9314 2271static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
d7c0a89a 2272 uint32_t flags)
2232a77c 2273{
d62a17ae 2274 struct neigh_walk_ctx wctx;
13d60d35 2275
d62a17ae 2276 if (!zvni->neigh_table)
2277 return;
13d60d35 2278
d62a17ae 2279 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2280 wctx.zvni = zvni;
d62a17ae 2281 wctx.uninstall = uninstall;
2282 wctx.upd_client = upd_client;
2283 wctx.flags = flags;
2232a77c 2284
b1599bb6 2285 hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx);
13d60d35 2286}
2287
2288/*
2232a77c 2289 * Look up neighbor hash entry.
2290 */
d62a17ae 2291static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip)
2232a77c 2292{
d62a17ae 2293 zebra_neigh_t tmp;
2294 zebra_neigh_t *n;
2232a77c 2295
d62a17ae 2296 memset(&tmp, 0, sizeof(tmp));
2297 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
2298 n = hash_lookup(zvni->neigh_table, &tmp);
2232a77c 2299
d62a17ae 2300 return n;
2232a77c 2301}
2302
f07e1c99 2303/*
2304 * Process all neighbors associated with a MAC upon the MAC being learnt
2305 * locally or undergoing any other change (such as sequence number).
2306 */
2307static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni,
2308 zebra_mac_t *zmac,
2309 bool seq_change)
b6938a74
MK
2310{
2311 zebra_neigh_t *n = NULL;
2312 struct listnode *node = NULL;
c80a972c 2313 struct zebra_vrf *zvrf = NULL;
b6938a74 2314 char buf[ETHER_ADDR_STRLEN];
b6938a74 2315
6005fe55 2316 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
c80a972c 2317
f07e1c99 2318 if (IS_ZEBRA_DEBUG_VXLAN)
2319 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2320 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
2321 seq_change ? "CHANGE" : "ADD", zvni->vni);
2322
2323 /* Walk all neighbors and mark any inactive local neighbors as
2324 * active and/or update sequence number upon a move, and inform BGP.
2325 * The action for remote neighbors is TBD.
2326 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2327 * accidentally end up deleting a just-learnt local neighbor.
2328 */
b6938a74
MK
2329 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
2330 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
f07e1c99 2331 if (IS_ZEBRA_NEIGH_INACTIVE(n) || seq_change) {
b6938a74 2332 ZEBRA_NEIGH_SET_ACTIVE(n);
f07e1c99 2333 n->loc_seq = zmac->loc_seq;
c80a972c
CS
2334 if (!(zvrf->dup_addr_detect &&
2335 zvrf->dad_freeze && !!CHECK_FLAG(n->flags,
2336 ZEBRA_NEIGH_DUPLICATE)))
2337 zvni_neigh_send_add_to_client(
2338 zvni->vni, &n->ip, &n->emac,
2339 n->flags, n->loc_seq);
b6938a74 2340 }
b6938a74
MK
2341 }
2342 }
2343}
2344
f07e1c99 2345/*
2346 * Process all neighbors associated with a local MAC upon the MAC being
2347 * deleted.
2348 */
2853fed6 2349static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni,
b6938a74
MK
2350 zebra_mac_t *zmac)
2351{
2352 zebra_neigh_t *n = NULL;
2353 struct listnode *node = NULL;
2354 char buf[ETHER_ADDR_STRLEN];
b6938a74 2355
f07e1c99 2356 if (IS_ZEBRA_DEBUG_VXLAN)
2357 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2358 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
2359 zvni->vni);
2360
2361 /* Walk all local neighbors and mark as inactive and inform
2362 * BGP, if needed.
2363 * TBD: There is currently no handling for remote neighbors. We
2364 * don't expect them to exist, if they do, do we install the MAC
2365 * as a remote MAC and the neighbor as remote?
2366 */
b6938a74
MK
2367 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
2368 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2369 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
b6938a74 2370 ZEBRA_NEIGH_SET_INACTIVE(n);
f07e1c99 2371 n->loc_seq = 0;
996c9314 2372 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
2c476b72 2373 &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
b6938a74 2374 }
b6938a74
MK
2375 }
2376 }
2377}
2378
f07e1c99 2379/*
2380 * Process all neighbors associated with a MAC upon the MAC being remotely
2381 * learnt.
2382 */
2853fed6 2383static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni,
b6938a74
MK
2384 zebra_mac_t *zmac)
2385{
2386 zebra_neigh_t *n = NULL;
2387 struct listnode *node = NULL;
2388 char buf[ETHER_ADDR_STRLEN];
b6938a74 2389
f07e1c99 2390 if (IS_ZEBRA_DEBUG_VXLAN)
2391 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2392 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
2393 zvni->vni);
2394
2395 /* Walk all local neighbors and mark as inactive and inform
2396 * BGP, if needed.
2397 */
b6938a74
MK
2398 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
2399 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2400 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
b6938a74 2401 ZEBRA_NEIGH_SET_INACTIVE(n);
f07e1c99 2402 n->loc_seq = 0;
996c9314 2403 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
2c476b72 2404 &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
b6938a74
MK
2405 }
2406 }
2407 }
2408}
2409
f07e1c99 2410/*
2411 * Process all neighbors associated with a remote MAC upon the MAC being
2412 * deleted.
2413 */
2853fed6 2414static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
b6938a74
MK
2415 zebra_mac_t *zmac)
2416{
f07e1c99 2417 /* NOTE: Currently a NO-OP. */
b6938a74
MK
2418}
2419
44bc8ae5
CS
2420static void zvni_probe_neigh_on_mac_add(zebra_vni_t *zvni, zebra_mac_t *zmac)
2421{
2422 zebra_neigh_t *nbr = NULL;
2423 struct listnode *node = NULL;
2424
2425 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, nbr)) {
2426 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL) &&
2427 IS_ZEBRA_NEIGH_INACTIVE(nbr))
2428 zvni_neigh_probe(zvni, nbr);
2429 }
2430}
2431
2232a77c 2432/*
2433 * Inform BGP about local neighbor addition.
13d60d35 2434 */
996c9314 2435static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
ead40654 2436 struct ethaddr *macaddr,
f07e1c99 2437 uint8_t neigh_flags,
2438 uint32_t seq)
13d60d35 2439{
d7c0a89a 2440 uint8_t flags = 0;
ead40654
MK
2441
2442 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
2443 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
68e33151
CS
2444 /* Set router flag (R-bit) based on local neigh entry add */
2445 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
2446 SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
ead40654 2447
2853fed6 2448 return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
2c476b72 2449 seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
2232a77c 2450}
13d60d35 2451
2232a77c 2452/*
2453 * Inform BGP about local neighbor deletion.
2454 */
996c9314 2455static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
2c476b72
AK
2456 struct ethaddr *macaddr, uint8_t flags,
2457 int state)
2232a77c 2458{
2853fed6 2459 return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
2c476b72 2460 0, state, ZEBRA_MACIP_DEL);
2232a77c 2461}
2462
2463/*
2464 * Install remote neighbor into the kernel.
2465 */
d62a17ae 2466static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
2232a77c 2467{
d62a17ae 2468 struct zebra_if *zif;
2469 struct zebra_l2info_vxlan *vxl;
2470 struct interface *vlan_if;
f7dae312 2471#ifdef GNU_LINUX
68e33151 2472 uint8_t flags;
f7dae312 2473#endif
68e33151 2474 int ret = 0;
2232a77c 2475
d62a17ae 2476 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
2477 return 0;
13d60d35 2478
d62a17ae 2479 zif = zvni->vxlan_if->info;
2480 if (!zif)
2481 return -1;
2482 vxl = &zif->l2info.vxl;
13d60d35 2483
2853fed6 2484 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
d62a17ae 2485 if (!vlan_if)
2486 return -1;
68e33151
CS
2487#ifdef GNU_LINUX
2488 flags = NTF_EXT_LEARNED;
2489 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
2490 flags |= NTF_ROUTER;
f07e1c99 2491 ZEBRA_NEIGH_SET_ACTIVE(n);
68e33151
CS
2492 ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags);
2493#endif
2494 return ret;
2232a77c 2495}
13d60d35 2496
2232a77c 2497/*
2498 * Uninstall remote neighbor from the kernel.
2499 */
d62a17ae 2500static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
2232a77c 2501{
d62a17ae 2502 struct zebra_if *zif;
2503 struct zebra_l2info_vxlan *vxl;
2504 struct interface *vlan_if;
13d60d35 2505
d62a17ae 2506 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
2507 return 0;
2232a77c 2508
d62a17ae 2509 if (!zvni->vxlan_if) {
9df414fe
QY
2510 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2511 zvni->vni, zvni);
d62a17ae 2512 return -1;
2513 }
2232a77c 2514
d62a17ae 2515 zif = zvni->vxlan_if->info;
2516 if (!zif)
2517 return -1;
2518 vxl = &zif->l2info.vxl;
2853fed6 2519 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
d62a17ae 2520 if (!vlan_if)
2521 return -1;
2232a77c 2522
f07e1c99 2523 ZEBRA_NEIGH_SET_INACTIVE(n);
2524 n->loc_seq = 0;
d62a17ae 2525 return kernel_del_neigh(vlan_if, &n->ip);
13d60d35 2526}
2527
44bc8ae5
CS
2528/*
2529 * Probe neighbor from the kernel.
2530 */
2531static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n)
2532{
2533 struct zebra_if *zif;
2534 struct zebra_l2info_vxlan *vxl;
2535 struct interface *vlan_if;
2536
2537 zif = zvni->vxlan_if->info;
2538 if (!zif)
2539 return -1;
2540 vxl = &zif->l2info.vxl;
2541
2542 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
2543 if (!vlan_if)
2544 return -1;
2545
2546#ifdef GNU_LINUX
2547 return kernel_upd_neigh(vlan_if, &n->ip, &n->emac,
2548 0, NUD_PROBE);
2549#else
2550 return 0;
2551#endif
2552}
2553
13d60d35 2554/*
2232a77c 2555 * Install neighbor hash entry - called upon access VLAN change.
13d60d35 2556 */
e3b78da8 2557static void zvni_install_neigh_hash(struct hash_bucket *bucket, void *ctxt)
13d60d35 2558{
d62a17ae 2559 zebra_neigh_t *n;
2560 struct neigh_walk_ctx *wctx = ctxt;
13d60d35 2561
e3b78da8 2562 n = (zebra_neigh_t *)bucket->data;
13d60d35 2563
d62a17ae 2564 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
2565 zvni_neigh_install(wctx->zvni, n);
2232a77c 2566}
13d60d35 2567
1a98c087
MK
2568/* Get the VRR interface for SVI if any */
2569struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp)
2570{
2571 struct zebra_vrf *zvrf = NULL;
2572 struct interface *tmp_if = NULL;
2573 struct zebra_if *zif = NULL;
1a98c087
MK
2574
2575 zvrf = vrf_info_lookup(ifp->vrf_id);
2576 assert(zvrf);
2577
451fda4f 2578 FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) {
1a98c087
MK
2579 zif = tmp_if->info;
2580 if (!zif)
2581 continue;
2582
2583 if (!IS_ZEBRA_IF_MACVLAN(tmp_if))
2584 continue;
2585
2586 if (zif->link == ifp)
2587 return tmp_if;
2588 }
2589
2590 return NULL;
2591}
2592
2593static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
2594{
1a98c087
MK
2595 struct listnode *cnode = NULL, *cnnode = NULL;
2596 struct connected *c = NULL;
2597 struct ethaddr macaddr;
2598
1a98c087
MK
2599 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2600
2601 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
2602 struct ipaddr ip;
2603
2604 memset(&ip, 0, sizeof(struct ipaddr));
2605 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
2606 continue;
2607
2608 if (c->address->family == AF_INET) {
2609 ip.ipa_type = IPADDR_V4;
2610 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
2611 sizeof(struct in_addr));
2612 } else if (c->address->family == AF_INET6) {
2613 ip.ipa_type = IPADDR_V6;
2614 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
2615 sizeof(struct in6_addr));
2616 } else {
2617 continue;
2618 }
2619
2620 zvni_gw_macip_del(ifp, zvni, &ip);
2621 }
2622
2623 return 0;
2624}
2625
2626static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
2627{
1a98c087
MK
2628 struct listnode *cnode = NULL, *cnnode = NULL;
2629 struct connected *c = NULL;
2630 struct ethaddr macaddr;
2631
1a98c087
MK
2632 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2633
2634 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
2635 struct ipaddr ip;
2636
2637 memset(&ip, 0, sizeof(struct ipaddr));
2638 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
2639 continue;
2640
2641 if (c->address->family == AF_INET) {
2642 ip.ipa_type = IPADDR_V4;
2643 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
2644 sizeof(struct in_addr));
2645 } else if (c->address->family == AF_INET6) {
2646 ip.ipa_type = IPADDR_V6;
2647 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
2648 sizeof(struct in6_addr));
2649 } else {
2650 continue;
2651 }
2652
2653 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
2654 }
31310b25
MK
2655 return 0;
2656}
2657
2658
996c9314 2659static int zvni_advertise_subnet(zebra_vni_t *zvni, struct interface *ifp,
31310b25
MK
2660 int advertise)
2661{
2662 struct listnode *cnode = NULL, *cnnode = NULL;
2663 struct connected *c = NULL;
2664 struct ethaddr macaddr;
2665
2666 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2667
2668 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
2669 struct prefix p;
1a98c087 2670
31310b25
MK
2671 memcpy(&p, c->address, sizeof(struct prefix));
2672
2673 /* skip link local address */
2674 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
2675 continue;
2676
2677 apply_mask(&p);
2678 if (advertise)
2679 ip_prefix_send_to_client(ifp->vrf_id, &p,
996c9314 2680 ZEBRA_IP_PREFIX_ROUTE_ADD);
31310b25
MK
2681 else
2682 ip_prefix_send_to_client(ifp->vrf_id, &p,
2683 ZEBRA_IP_PREFIX_ROUTE_DEL);
2684 }
1a98c087
MK
2685 return 0;
2686}
2687
2688/*
2689 * zvni_gw_macip_add_to_client
2690 */
2691static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
2692 struct ethaddr *macaddr, struct ipaddr *ip)
2693{
1a98c087
MK
2694 char buf[ETHER_ADDR_STRLEN];
2695 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
2696 zebra_neigh_t *n = NULL;
2697 zebra_mac_t *mac = NULL;
2698 struct zebra_if *zif = NULL;
2699 struct zebra_l2info_vxlan *vxl = NULL;
2700
1a98c087
MK
2701 zif = zvni->vxlan_if->info;
2702 if (!zif)
2703 return -1;
2704
2705 vxl = &zif->l2info.vxl;
2706
2707 mac = zvni_mac_lookup(zvni, macaddr);
2708 if (!mac) {
2709 mac = zvni_mac_add(zvni, macaddr);
2710 if (!mac) {
e914ccbe 2711 flog_err(EC_ZEBRA_MAC_ADD_FAILED,
1c50c1c0
QY
2712 "Failed to add MAC %s intf %s(%u) VID %u",
2713 prefix_mac2str(macaddr, buf, sizeof(buf)),
2714 ifp->name, ifp->ifindex, vxl->access_vlan);
1a98c087
MK
2715 return -1;
2716 }
2717 }
2718
2719 /* Set "local" forwarding info. */
2720 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2721 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
ead40654 2722 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
1a98c087
MK
2723 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
2724 mac->fwd_info.local.ifindex = ifp->ifindex;
2725 mac->fwd_info.local.vid = vxl->access_vlan;
2726
2727 n = zvni_neigh_lookup(zvni, ip);
2728 if (!n) {
b6938a74 2729 n = zvni_neigh_add(zvni, ip, macaddr);
1a98c087 2730 if (!n) {
af4c2728 2731 flog_err(
e914ccbe 2732 EC_ZEBRA_MAC_ADD_FAILED,
2853fed6 2733 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2734 ipaddr2str(ip, buf2, sizeof(buf2)),
0af35d90 2735 prefix_mac2str(macaddr, buf, sizeof(buf)),
1a98c087
MK
2736 ifp->name, ifp->ifindex, zvni->vni);
2737 return -1;
2738 }
2739 }
2740
2741 /* Set "local" forwarding info. */
2742 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
ead40654 2743 SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
1a8c5c38 2744 ZEBRA_NEIGH_SET_ACTIVE(n);
68e33151
CS
2745 /* Set Router flag (R-bit) */
2746 if (ip->ipa_type == IPADDR_V6)
2747 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
1a98c087
MK
2748 memcpy(&n->emac, macaddr, ETH_ALEN);
2749 n->ifindex = ifp->ifindex;
2750
ead40654
MK
2751 /* Only advertise in BGP if the knob is enabled */
2752 if (!advertise_gw_macip_enabled(zvni))
2753 return 0;
2754
1a98c087
MK
2755 if (IS_ZEBRA_DEBUG_VXLAN)
2756 zlog_debug(
68e33151 2757 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2853fed6 2758 ifp->name, ifp->ifindex, zvni->vni,
1e9f448f 2759 prefix_mac2str(macaddr, buf, sizeof(buf)),
68e33151 2760 ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
1a98c087 2761
f07e1c99 2762 zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
2763 n->flags, n->loc_seq);
1a98c087
MK
2764
2765 return 0;
2766}
2767
2768/*
2769 * zvni_gw_macip_del_from_client
2770 */
2771static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
2772 struct ipaddr *ip)
2773{
0af35d90 2774 char buf1[ETHER_ADDR_STRLEN];
1a98c087 2775 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
2776 zebra_neigh_t *n = NULL;
2777 zebra_mac_t *mac = NULL;
2778
1a98c087
MK
2779 /* If the neigh entry is not present nothing to do*/
2780 n = zvni_neigh_lookup(zvni, ip);
2781 if (!n)
2782 return 0;
2783
2784 /* mac entry should be present */
2785 mac = zvni_mac_lookup(zvni, &n->emac);
0af35d90 2786 if (!mac) {
0437e105 2787 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
9df414fe
QY
2788 prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
2789 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
0af35d90
RW
2790 return -1;
2791 }
1a98c087
MK
2792
2793 /* If the entry is not local nothing to do*/
2794 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
2795 return -1;
2796
ead40654 2797 /* only need to delete the entry from bgp if we sent it before */
01a6143b 2798 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
2799 zlog_debug(
2800 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2801 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
ee496c3b 2802 prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
996c9314 2803 ipaddr2str(ip, buf2, sizeof(buf2)));
01a6143b
MK
2804
2805 /* Remove neighbor from BGP. */
2806 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
2c476b72 2807 ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE);
1a98c087
MK
2808
2809 /* Delete this neighbor entry. */
2810 zvni_neigh_del(zvni, n);
2811
2812 /* see if the mac needs to be deleted as well*/
1e9f448f 2813 if (mac)
fe697c6b 2814 zvni_deref_ip2mac(zvni, mac);
1a98c087
MK
2815
2816 return 0;
2817}
2818
e3b78da8 2819static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket *bucket,
2853fed6 2820 void *ctxt)
1a98c087
MK
2821{
2822 zebra_vni_t *zvni = NULL;
2823 struct zebra_if *zif = NULL;
2824 struct zebra_l2info_vxlan zl2_info;
2825 struct interface *vlan_if = NULL;
2826 struct interface *vrr_if = NULL;
b5ebdc9b 2827 struct interface *ifp;
1a98c087
MK
2828
2829 /* Add primary SVI MAC*/
e3b78da8 2830 zvni = (zebra_vni_t *)bucket->data;
1a98c087 2831
b5ebdc9b 2832 ifp = zvni->vxlan_if;
2833 if (!ifp)
2834 return;
2835 zif = ifp->info;
2836
2837 /* If down or not mapped to a bridge, we're done. */
b682f6de 2838 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 2839 return;
2840
1a98c087
MK
2841 zl2_info = zif->l2info.vxl;
2842
996c9314
LB
2843 vlan_if =
2844 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
1a98c087
MK
2845 if (!vlan_if)
2846 return;
2847
2848 /* Del primary MAC-IP */
2849 zvni_del_macip_for_intf(vlan_if, zvni);
2850
2851 /* Del VRR MAC-IP - if any*/
2852 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2853 if (vrr_if)
2854 zvni_del_macip_for_intf(vrr_if, zvni);
2855
2856 return;
2857}
2858
e3b78da8 2859static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket *bucket,
2853fed6 2860 void *ctxt)
1a98c087
MK
2861{
2862 zebra_vni_t *zvni = NULL;
2863 struct zebra_if *zif = NULL;
2864 struct zebra_l2info_vxlan zl2_info;
2865 struct interface *vlan_if = NULL;
2866 struct interface *vrr_if = NULL;
b5ebdc9b 2867 struct interface *ifp = NULL;
1a98c087 2868
e3b78da8 2869 zvni = (zebra_vni_t *)bucket->data;
1a98c087 2870
b5ebdc9b 2871 ifp = zvni->vxlan_if;
2872 if (!ifp)
2873 return;
2874 zif = ifp->info;
2875
2876 /* If down or not mapped to a bridge, we're done. */
b682f6de 2877 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 2878 return;
1a98c087
MK
2879 zl2_info = zif->l2info.vxl;
2880
996c9314
LB
2881 vlan_if =
2882 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
1a98c087
MK
2883 if (!vlan_if)
2884 return;
2885
1a98c087
MK
2886 /* Add primary SVI MAC-IP */
2887 zvni_add_macip_for_intf(vlan_if, zvni);
2888
278e26de
CS
2889 if (advertise_gw_macip_enabled(zvni)) {
2890 /* Add VRR MAC-IP - if any*/
2891 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2892 if (vrr_if)
2893 zvni_add_macip_for_intf(vrr_if, zvni);
2894 }
2895
2896 return;
2897}
2898
e3b78da8 2899static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket *bucket,
278e26de
CS
2900 void *ctxt)
2901{
2902 zebra_vni_t *zvni = NULL;
2903 struct zebra_if *zif = NULL;
2904 struct zebra_l2info_vxlan zl2_info;
2905 struct interface *vlan_if = NULL;
2906 struct interface *ifp;
2907
2908 /* Add primary SVI MAC*/
e3b78da8 2909 zvni = (zebra_vni_t *)bucket->data;
278e26de
CS
2910 if (!zvni)
2911 return;
2912
2913 ifp = zvni->vxlan_if;
2914 if (!ifp)
2915 return;
2916 zif = ifp->info;
2917
2918 /* If down or not mapped to a bridge, we're done. */
2919 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
2920 return;
2921
2922 zl2_info = zif->l2info.vxl;
2923
2924 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
2925 zif->brslave_info.br_if);
2926 if (!vlan_if)
2927 return;
2928
2929 /* Del primary MAC-IP */
2930 zvni_del_macip_for_intf(vlan_if, zvni);
1a98c087
MK
2931
2932 return;
2933}
2934
ee69da27
MK
2935static int zvni_local_neigh_update(zebra_vni_t *zvni,
2936 struct interface *ifp,
2937 struct ipaddr *ip,
68e33151 2938 struct ethaddr *macaddr,
a37f4598 2939 bool is_router)
ee69da27
MK
2940{
2941 char buf[ETHER_ADDR_STRLEN];
2942 char buf2[INET6_ADDRSTRLEN];
e22a946a 2943 struct zebra_vrf *zvrf;
ee69da27
MK
2944 zebra_neigh_t *n = NULL;
2945 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
f07e1c99 2946 uint32_t old_mac_seq = 0, mac_new_seq = 0;
2947 bool upd_mac_seq = false;
2948 bool neigh_mac_change = false;
e22a946a
CS
2949 bool neigh_on_hold = false;
2950 bool neigh_was_remote = false;
7510e459 2951 bool do_dad = false;
e22a946a 2952 struct in_addr vtep_ip = {.s_addr = 0};
ee69da27 2953
f07e1c99 2954 /* Check if the MAC exists. */
ee69da27
MK
2955 zmac = zvni_mac_lookup(zvni, macaddr);
2956 if (!zmac) {
f07e1c99 2957 /* create a dummy MAC if the MAC is not already present */
ee69da27
MK
2958 if (IS_ZEBRA_DEBUG_VXLAN)
2959 zlog_debug(
2960 "AUTO MAC %s created for neigh %s on VNI %u",
2961 prefix_mac2str(macaddr, buf, sizeof(buf)),
2962 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
2963
2964 zmac = zvni_mac_add(zvni, macaddr);
2965 if (!zmac) {
9df414fe
QY
2966 zlog_debug("Failed to add MAC %s VNI %u",
2967 prefix_mac2str(macaddr, buf, sizeof(buf)),
2968 zvni->vni);
ee69da27
MK
2969 return -1;
2970 }
2971
2972 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
2973 memset(&zmac->flags, 0, sizeof(uint32_t));
2974 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
f07e1c99 2975 } else {
2976 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
2977 /*
2978 * We don't change the MAC to local upon a neighbor
2979 * learn event, we wait for the explicit local MAC
2980 * learn. However, we have to compute its sequence
2981 * number in preparation for when it actually turns
2982 * local.
2983 */
2984 upd_mac_seq = true;
2985 }
ee69da27
MK
2986 }
2987
6005fe55 2988 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
e22a946a
CS
2989 if (!zvrf)
2990 return -1;
2991
f07e1c99 2992 /* Check if the neighbor exists. */
ee69da27 2993 n = zvni_neigh_lookup(zvni, ip);
f07e1c99 2994 if (!n) {
2995 /* New neighbor - create */
2996 n = zvni_neigh_add(zvni, ip, macaddr);
2997 if (!n) {
2998 flog_err(
e914ccbe 2999 EC_ZEBRA_MAC_ADD_FAILED,
f07e1c99 3000 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3001 ipaddr2str(ip, buf2, sizeof(buf2)),
3002 prefix_mac2str(macaddr, buf, sizeof(buf)),
3003 ifp->name, ifp->ifindex, zvni->vni);
3004 return -1;
3005 }
3006 /* Set "local" forwarding info. */
3007 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3008 n->ifindex = ifp->ifindex;
3009 } else {
ee69da27 3010 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
66e37987 3011 bool mac_different;
3012 bool cur_is_router;
3013
3014 /* Note any changes and see if of interest to BGP. */
3015 mac_different = (memcmp(n->emac.octet,
3016 macaddr->octet, ETH_ALEN) != 0) ? 1 : 0;
3017 cur_is_router = !!CHECK_FLAG(n->flags,
3018 ZEBRA_NEIGH_ROUTER_FLAG);
3019 if (!mac_different && is_router == cur_is_router) {
ee69da27 3020 n->ifindex = ifp->ifindex;
66e37987 3021 return 0;
3022 }
ee69da27 3023
66e37987 3024 if (!mac_different) {
e22a946a
CS
3025 bool is_neigh_freezed = false;
3026
66e37987 3027 /* Only the router flag has changed. */
3028 if (is_router)
3029 SET_FLAG(n->flags,
3030 ZEBRA_NEIGH_ROUTER_FLAG);
3031 else
3032 UNSET_FLAG(n->flags,
3033 ZEBRA_NEIGH_ROUTER_FLAG);
ee69da27 3034
e22a946a
CS
3035 /* Neigh is in freeze state and freeze action
3036 * is enabled, do not send update to client.
3037 */
3038 is_neigh_freezed = (zvrf->dup_addr_detect &&
3039 zvrf->dad_freeze &&
3040 CHECK_FLAG(n->flags,
3041 ZEBRA_NEIGH_DUPLICATE));
3042
3043 if (IS_ZEBRA_NEIGH_ACTIVE(n) &&
3044 !is_neigh_freezed)
66e37987 3045 return zvni_neigh_send_add_to_client(
3046 zvni->vni, ip, macaddr,
3047 n->flags, n->loc_seq);
3048 return 0;
3049 }
3050
3051 /* The MAC has changed, need to issue a delete
3052 * first as this means a different MACIP route.
3053 * Also, need to do some unlinking/relinking.
3054 * We also need to update the MAC's sequence number
3055 * in different situations.
3056 */
3057 if (IS_ZEBRA_NEIGH_ACTIVE(n))
3058 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
2c476b72 3059 &n->emac, 0, n->state);
66e37987 3060 old_zmac = zvni_mac_lookup(zvni, &n->emac);
3061 if (old_zmac) {
3062 old_mac_seq = CHECK_FLAG(old_zmac->flags,
3063 ZEBRA_MAC_REMOTE) ?
3064 old_zmac->rem_seq : old_zmac->loc_seq;
3065 neigh_mac_change = upd_mac_seq = true;
3066 listnode_delete(old_zmac->neigh_list, n);
3067 zvni_deref_ip2mac(zvni, old_zmac);
29c2ce7c 3068 }
ee69da27 3069
66e37987 3070 /* Update the forwarding info. */
3071 n->ifindex = ifp->ifindex;
3072 memcpy(&n->emac, macaddr, ETH_ALEN);
3073
3074 /* Link to new MAC */
3075 listnode_add_sort(zmac->neigh_list, n);
f07e1c99 3076 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
3077 /*
3078 * Neighbor has moved from remote to local. Its
3079 * MAC could have also changed as part of the move.
3080 */
ee69da27
MK
3081 if (memcmp(n->emac.octet, macaddr->octet,
3082 ETH_ALEN) != 0) {
3083 old_zmac = zvni_mac_lookup(zvni, &n->emac);
3084 if (old_zmac) {
9df2b997 3085 old_mac_seq = CHECK_FLAG(
3086 old_zmac->flags,
3087 ZEBRA_MAC_REMOTE) ?
f07e1c99 3088 old_zmac->rem_seq :
3089 old_zmac->loc_seq;
3090 neigh_mac_change = upd_mac_seq = true;
9fc1522c
DS
3091 listnode_delete(old_zmac->neigh_list,
3092 n);
fe697c6b 3093 zvni_deref_ip2mac(zvni, old_zmac);
ee69da27
MK
3094 }
3095
3096 /* Link to new MAC */
3097 memcpy(&n->emac, macaddr, ETH_ALEN);
3098 listnode_add_sort(zmac->neigh_list, n);
3099 }
e22a946a
CS
3100 /* Based on Mobility event Scenario-B from the
3101 * draft, neigh's previous state was remote treat this
3102 * event for DAD.
3103 */
3104 neigh_was_remote = true;
3105 vtep_ip = n->r_vtep_ip;
ee69da27
MK
3106 /* Mark appropriately */
3107 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3108 n->r_vtep_ip.s_addr = 0;
3109 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3110 n->ifindex = ifp->ifindex;
3111 }
f07e1c99 3112 }
3113
3114 /* If MAC was previously remote, or the neighbor had a different
3115 * MAC earlier, recompute the sequence number.
3116 */
3117 if (upd_mac_seq) {
3118 uint32_t seq1, seq2;
3119
3120 seq1 = CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE) ?
3121 zmac->rem_seq + 1 : zmac->loc_seq;
3122 seq2 = neigh_mac_change ? old_mac_seq + 1 : 0;
3123 mac_new_seq = zmac->loc_seq < MAX(seq1, seq2) ?
3124 MAX(seq1, seq2) : zmac->loc_seq;
ee69da27
MK
3125 }
3126
e22a946a 3127 /* Mark Router flag (R-bit) */
a37f4598 3128 if (is_router)
54c17425
CS
3129 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
3130 else
3131 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
3132
e22a946a
CS
3133 /* Check old and/or new MAC detected as duplicate mark
3134 * the neigh as duplicate
3135 */
3136 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) {
3137 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
3138 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3139 zvni->vni,
3140 prefix_mac2str(macaddr, buf, sizeof(buf)),
3141 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
3142 }
3143
7510e459
CS
3144 /* For IP Duplicate Address Detection (DAD) is trigger,
3145 * when the event is extended mobility based on scenario-B
3146 * from the draft, IP/Neigh's MAC binding changed and
3147 * neigh's previous state was remote.
e22a946a 3148 */
7510e459
CS
3149 if (neigh_mac_change && neigh_was_remote)
3150 do_dad = true;
e22a946a 3151
7510e459
CS
3152 zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n, vtep_ip, do_dad,
3153 &neigh_on_hold, true);
c80a972c 3154
ee69da27 3155 /* Before we program this in BGP, we need to check if MAC is locally
f07e1c99 3156 * learnt. If not, force neighbor to be inactive and reset its seq.
ee69da27
MK
3157 */
3158 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
8b44d564 3159 ZEBRA_NEIGH_SET_INACTIVE(n);
f07e1c99 3160 n->loc_seq = 0;
3161 zmac->loc_seq = mac_new_seq;
ee69da27
MK
3162 return 0;
3163 }
3164
f07e1c99 3165 /* If the MAC's sequence number has changed, inform the MAC and all
3166 * neighbors associated with the MAC to BGP, else just inform this
3167 * neighbor.
3168 */
3169 if (upd_mac_seq && zmac->loc_seq != mac_new_seq) {
29c2ce7c 3170 if (IS_ZEBRA_DEBUG_VXLAN)
f07e1c99 3171 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3172 prefix_mac2str(macaddr, buf, sizeof(buf)),
3173 zvni->vni, zmac->loc_seq, mac_new_seq);
3174 zmac->loc_seq = mac_new_seq;
3175 if (zvni_mac_send_add_to_client(zvni->vni, macaddr,
3176 zmac->flags, zmac->loc_seq))
3177 return -1;
3178 zvni_process_neigh_on_local_mac_change(zvni, zmac, 1);
29c2ce7c
CS
3179 return 0;
3180 }
3181
ee69da27 3182 ZEBRA_NEIGH_SET_ACTIVE(n);
f07e1c99 3183 n->loc_seq = zmac->loc_seq;
ee69da27 3184
e22a946a
CS
3185 if (!neigh_on_hold)
3186 return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
f07e1c99 3187 n->flags, n->loc_seq);
e22a946a 3188 return 0;
ee69da27
MK
3189}
3190
3191static int zvni_remote_neigh_update(zebra_vni_t *zvni,
3192 struct interface *ifp,
3193 struct ipaddr *ip,
3194 struct ethaddr *macaddr,
3195 uint16_t state)
3196{
3197 char buf[ETHER_ADDR_STRLEN];
3198 char buf2[INET6_ADDRSTRLEN];
3199 zebra_neigh_t *n = NULL;
3200 zebra_mac_t *zmac = NULL;
3201
3202 /* If the neighbor is unknown, there is no further action. */
3203 n = zvni_neigh_lookup(zvni, ip);
3204 if (!n)
3205 return 0;
3206
3207 /* If a remote entry, see if it needs to be refreshed */
3208 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
e9d2cbde 3209#ifdef GNU_LINUX
ee69da27
MK
3210 if (state & NUD_STALE)
3211 zvni_neigh_install(zvni, n);
e9d2cbde 3212#endif
ee69da27
MK
3213 } else {
3214 /* We got a "remote" neighbor notification for an entry
3215 * we think is local. This can happen in a multihoming
3216 * scenario - but only if the MAC is already "remote".
3217 * Just mark our entry as "remote".
3218 */
3219 zmac = zvni_mac_lookup(zvni, macaddr);
3220 if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
9df414fe 3221 zlog_debug(
43e52561
QY
3222 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3223 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
3224 prefix_mac2str(macaddr, buf, sizeof(buf)),
3225 zvni->vni);
ee69da27
MK
3226 return -1;
3227 }
3228
3229 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3230 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
4fd5ea4b 3231 ZEBRA_NEIGH_SET_ACTIVE(n);
ee69da27
MK
3232 n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
3233 }
3234
3235 return 0;
3236}
3237
2232a77c 3238/*
3239 * Make hash key for MAC.
3240 */
d62a17ae 3241static unsigned int mac_hash_keymake(void *p)
2232a77c 3242{
d62a17ae 3243 zebra_mac_t *pmac = p;
25331def
DS
3244 const void *pnt = (void *)pmac->macaddr.octet;
3245
ff8b7eb8 3246 return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
2232a77c 3247}
13d60d35 3248
2232a77c 3249/*
3250 * Compare two MAC addresses.
3251 */
74df8d6d 3252static bool mac_cmp(const void *p1, const void *p2)
2232a77c 3253{
d62a17ae 3254 const zebra_mac_t *pmac1 = p1;
3255 const zebra_mac_t *pmac2 = p2;
2232a77c 3256
d62a17ae 3257 if (pmac1 == NULL && pmac2 == NULL)
74df8d6d 3258 return true;
2232a77c 3259
d62a17ae 3260 if (pmac1 == NULL || pmac2 == NULL)
74df8d6d 3261 return false;
2232a77c 3262
996c9314 3263 return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
d62a17ae 3264 == 0);
2232a77c 3265}
3266
3267/*
3268 * Callback to allocate MAC hash entry.
3269 */
d62a17ae 3270static void *zvni_mac_alloc(void *p)
2232a77c 3271{
d62a17ae 3272 const zebra_mac_t *tmp_mac = p;
3273 zebra_mac_t *mac;
2232a77c 3274
d62a17ae 3275 mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
3276 *mac = *tmp_mac;
2232a77c 3277
d62a17ae 3278 return ((void *)mac);
2232a77c 3279}
3280
3281/*
3282 * Add MAC entry.
3283 */
d62a17ae 3284static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
2232a77c 3285{
d62a17ae 3286 zebra_mac_t tmp_mac;
3287 zebra_mac_t *mac = NULL;
2232a77c 3288
d62a17ae 3289 memset(&tmp_mac, 0, sizeof(zebra_mac_t));
ff8b7eb8 3290 memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
d62a17ae 3291 mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
3292 assert(mac);
2232a77c 3293
b6938a74 3294 mac->neigh_list = list_new();
27fa3398 3295 mac->neigh_list->cmp = neigh_list_cmp;
b6938a74 3296
d62a17ae 3297 return mac;
2232a77c 3298}
3299
3300/*
3301 * Delete MAC entry.
3302 */
d62a17ae 3303static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 3304{
d62a17ae 3305 zebra_mac_t *tmp_mac;
2232a77c 3306
6a154c88 3307 list_delete(&mac->neigh_list);
b6938a74 3308
d62a17ae 3309 /* Free the VNI hash entry and allocated memory. */
3310 tmp_mac = hash_release(zvni->mac_table, mac);
0a22ddfb 3311 XFREE(MTYPE_MAC, tmp_mac);
2232a77c 3312
d62a17ae 3313 return 0;
2232a77c 3314}
3315
3316/*
3317 * Free MAC hash entry (callback)
3318 */
e3b78da8 3319static void zvni_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
2232a77c 3320{
d62a17ae 3321 struct mac_walk_ctx *wctx = arg;
e3b78da8 3322 zebra_mac_t *mac = bucket->data;
2232a77c 3323
d62a17ae 3324 if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
3325 || ((wctx->flags & DEL_REMOTE_MAC)
3326 && (mac->flags & ZEBRA_MAC_REMOTE))
3327 || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
3328 && (mac->flags & ZEBRA_MAC_REMOTE)
3329 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
3330 &wctx->r_vtep_ip))) {
3331 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
996c9314 3332 zvni_mac_send_del_to_client(wctx->zvni->vni,
e98e4b88 3333 &mac->macaddr);
d62a17ae 3334 }
2232a77c 3335
d62a17ae 3336 if (wctx->uninstall)
d63c1b18 3337 zvni_mac_uninstall(wctx->zvni, mac);
2232a77c 3338
b1599bb6 3339 zvni_mac_del(wctx->zvni, mac);
d62a17ae 3340 }
2232a77c 3341
b1599bb6 3342 return;
2232a77c 3343}
3344
3345/*
3346 * Delete all MAC entries from specific VTEP for a particular VNI.
3347 */
d62a17ae 3348static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
3349 struct in_addr *r_vtep_ip)
2232a77c 3350{
d62a17ae 3351 struct mac_walk_ctx wctx;
2232a77c 3352
d62a17ae 3353 if (!zvni->mac_table)
3354 return;
2232a77c 3355
d62a17ae 3356 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
3357 wctx.zvni = zvni;
3358 wctx.uninstall = uninstall;
3359 wctx.flags = DEL_REMOTE_MAC_FROM_VTEP;
3360 wctx.r_vtep_ip = *r_vtep_ip;
2232a77c 3361
b1599bb6 3362 hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx);
2232a77c 3363}
3364
3365/*
3366 * Delete all MAC entries for this VNI.
3367 */
996c9314 3368static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
d7c0a89a 3369 uint32_t flags)
2232a77c 3370{
d62a17ae 3371 struct mac_walk_ctx wctx;
2232a77c 3372
d62a17ae 3373 if (!zvni->mac_table)
3374 return;
2232a77c 3375
d62a17ae 3376 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
3377 wctx.zvni = zvni;
d62a17ae 3378 wctx.uninstall = uninstall;
3379 wctx.upd_client = upd_client;
3380 wctx.flags = flags;
2232a77c 3381
b1599bb6 3382 hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx);
2232a77c 3383}
3384
3385/*
3386 * Look up MAC hash entry.
3387 */
d62a17ae 3388static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
2232a77c 3389{
d62a17ae 3390 zebra_mac_t tmp;
3391 zebra_mac_t *pmac;
2232a77c 3392
d62a17ae 3393 memset(&tmp, 0, sizeof(tmp));
ff8b7eb8 3394 memcpy(&tmp.macaddr, mac, ETH_ALEN);
d62a17ae 3395 pmac = hash_lookup(zvni->mac_table, &tmp);
2232a77c 3396
d62a17ae 3397 return pmac;
2232a77c 3398}
3399
3400/*
3401 * Inform BGP about local MAC addition.
3402 */
996c9314 3403static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
f07e1c99 3404 uint8_t mac_flags, uint32_t seq)
2232a77c 3405{
d7c0a89a 3406 uint8_t flags = 0;
ead40654
MK
3407
3408 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
3409 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
3410 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
3411 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
3412
2853fed6 3413 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
2c476b72 3414 seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
2232a77c 3415}
3416
3417/*
3418 * Inform BGP about local MAC deletion.
3419 */
e98e4b88 3420static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
2232a77c 3421{
e98e4b88 3422 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
2c476b72 3423 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
2232a77c 3424}
3425
3426/*
3427 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2853fed6 3428 * notifications, to see if they are of interest.
2232a77c 3429 */
d62a17ae 3430static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
3431 struct interface *br_if, vlanid_t vid)
2232a77c 3432{
2853fed6 3433 struct zebra_ns *zns;
3434 struct route_node *rn;
3435 struct interface *tmp_if = NULL;
d62a17ae 3436 struct zebra_if *zif;
3437 struct zebra_l2info_bridge *br;
2853fed6 3438 struct zebra_l2info_vxlan *vxl = NULL;
d7c0a89a 3439 uint8_t bridge_vlan_aware;
d62a17ae 3440 zebra_vni_t *zvni;
2853fed6 3441 int found = 0;
2232a77c 3442
d62a17ae 3443 /* Determine if bridge is VLAN-aware or not */
3444 zif = br_if->info;
3445 assert(zif);
3446 br = &zif->l2info.br;
3447 bridge_vlan_aware = br->vlan_aware;
2232a77c 3448
d62a17ae 3449 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3450 /* TODO: Optimize with a hash. */
2853fed6 3451 zns = zebra_ns_lookup(NS_DEFAULT);
3452 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3453 tmp_if = (struct interface *)rn->info;
3454 if (!tmp_if)
3455 continue;
d62a17ae 3456 zif = tmp_if->info;
3457 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3458 continue;
3459 if (!if_is_operative(tmp_if))
3460 continue;
3461 vxl = &zif->l2info.vxl;
2232a77c 3462
d62a17ae 3463 if (zif->brslave_info.br_if != br_if)
3464 continue;
2232a77c 3465
2853fed6 3466 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3467 found = 1;
d62a17ae 3468 break;
2853fed6 3469 }
d62a17ae 3470 }
2232a77c 3471
2853fed6 3472 if (!found)
d62a17ae 3473 return NULL;
2232a77c 3474
2853fed6 3475 zvni = zvni_lookup(vxl->vni);
d62a17ae 3476 return zvni;
2232a77c 3477}
3478
3479/*
3480 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3481 * neighbor notifications, to see if they are of interest.
2232a77c 3482 */
b7cfce93
MK
3483static zebra_vni_t *zvni_from_svi(struct interface *ifp,
3484 struct interface *br_if)
d62a17ae 3485{
2853fed6 3486 struct zebra_ns *zns;
3487 struct route_node *rn;
3488 struct interface *tmp_if = NULL;
d62a17ae 3489 struct zebra_if *zif;
3490 struct zebra_l2info_bridge *br;
2853fed6 3491 struct zebra_l2info_vxlan *vxl = NULL;
d7c0a89a 3492 uint8_t bridge_vlan_aware;
d62a17ae 3493 vlanid_t vid = 0;
3494 zebra_vni_t *zvni;
2853fed6 3495 int found = 0;
d62a17ae 3496
71349e03
MK
3497 if (!br_if)
3498 return NULL;
3499
d62a17ae 3500 /* Make sure the linked interface is a bridge. */
3501 if (!IS_ZEBRA_IF_BRIDGE(br_if))
3502 return NULL;
3503
d62a17ae 3504 /* Determine if bridge is VLAN-aware or not */
3505 zif = br_if->info;
3506 assert(zif);
3507 br = &zif->l2info.br;
3508 bridge_vlan_aware = br->vlan_aware;
3509 if (bridge_vlan_aware) {
3510 struct zebra_l2info_vlan *vl;
3511
3512 if (!IS_ZEBRA_IF_VLAN(ifp))
3513 return NULL;
3514
3515 zif = ifp->info;
3516 assert(zif);
3517 vl = &zif->l2info.vl;
3518 vid = vl->vid;
3519 }
3520
3521 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3522 /* TODO: Optimize with a hash. */
2853fed6 3523 zns = zebra_ns_lookup(NS_DEFAULT);
3524 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3525 tmp_if = (struct interface *)rn->info;
3526 if (!tmp_if)
3527 continue;
d62a17ae 3528 zif = tmp_if->info;
3529 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3530 continue;
3531 if (!if_is_operative(tmp_if))
3532 continue;
3533 vxl = &zif->l2info.vxl;
3534
3535 if (zif->brslave_info.br_if != br_if)
3536 continue;
3537
2853fed6 3538 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3539 found = 1;
d62a17ae 3540 break;
2853fed6 3541 }
d62a17ae 3542 }
3543
2853fed6 3544 if (!found)
d62a17ae 3545 return NULL;
3546
2853fed6 3547 zvni = zvni_lookup(vxl->vni);
d62a17ae 3548 return zvni;
2232a77c 3549}
3550
3551/* Map to SVI on bridge corresponding to specified VLAN. This can be one
3552 * of two cases:
3553 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3554 * linked to the bridge
3555 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3556 * itself
3557 */
2853fed6 3558static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
d62a17ae 3559{
2853fed6 3560 struct zebra_ns *zns;
3561 struct route_node *rn;
3562 struct interface *tmp_if = NULL;
d62a17ae 3563 struct zebra_if *zif;
3564 struct zebra_l2info_bridge *br;
3565 struct zebra_l2info_vlan *vl;
d7c0a89a 3566 uint8_t bridge_vlan_aware;
2853fed6 3567 int found = 0;
d62a17ae 3568
b5ebdc9b 3569 /* Defensive check, caller expected to invoke only with valid bridge. */
3570 if (!br_if)
3571 return NULL;
3572
d62a17ae 3573 /* Determine if bridge is VLAN-aware or not */
3574 zif = br_if->info;
3575 assert(zif);
3576 br = &zif->l2info.br;
3577 bridge_vlan_aware = br->vlan_aware;
3578
3579 /* Check oper status of the SVI. */
3580 if (!bridge_vlan_aware)
3581 return if_is_operative(br_if) ? br_if : NULL;
3582
3583 /* Identify corresponding VLAN interface. */
3584 /* TODO: Optimize with a hash. */
2853fed6 3585 zns = zebra_ns_lookup(NS_DEFAULT);
3586 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3587 tmp_if = (struct interface *)rn->info;
d62a17ae 3588 /* Check oper status of the SVI. */
2853fed6 3589 if (!tmp_if || !if_is_operative(tmp_if))
d62a17ae 3590 continue;
3591 zif = tmp_if->info;
3592 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
3593 || zif->link != br_if)
3594 continue;
3595 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
3596
2853fed6 3597 if (vl->vid == vid) {
3598 found = 1;
d62a17ae 3599 break;
2853fed6 3600 }
d62a17ae 3601 }
3602
2853fed6 3603 return found ? tmp_if : NULL;
2232a77c 3604}
3605
3606/*
3607 * Install remote MAC into the kernel.
3608 */
d62a17ae 3609static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 3610{
d62a17ae 3611 struct zebra_if *zif;
3612 struct zebra_l2info_vxlan *vxl;
a37f4598 3613 bool sticky;
2232a77c 3614
d62a17ae 3615 if (!(mac->flags & ZEBRA_MAC_REMOTE))
3616 return 0;
2232a77c 3617
d62a17ae 3618 zif = zvni->vxlan_if->info;
3619 if (!zif)
3620 return -1;
3621 vxl = &zif->l2info.vxl;
2232a77c 3622
a37f4598 3623 sticky = !!CHECK_FLAG(mac->flags,
3624 (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
c85c03c7 3625
d62a17ae 3626 return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
3627 mac->fwd_info.r_vtep_ip, sticky);
2232a77c 3628}
3629
3630/*
d63c1b18 3631 * Uninstall remote MAC from the kernel.
2232a77c 3632 */
d63c1b18 3633static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 3634{
d62a17ae 3635 struct zebra_if *zif;
3636 struct zebra_l2info_vxlan *vxl;
98efddf1 3637 struct in_addr vtep_ip;
d62a17ae 3638 struct interface *ifp;
2232a77c 3639
d63c1b18 3640 if (!(mac->flags & ZEBRA_MAC_REMOTE))
d62a17ae 3641 return 0;
2232a77c 3642
d62a17ae 3643 if (!zvni->vxlan_if) {
9df414fe
QY
3644 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3645 zvni->vni, zvni);
d62a17ae 3646 return -1;
3647 }
2232a77c 3648
d62a17ae 3649 zif = zvni->vxlan_if->info;
3650 if (!zif)
3651 return -1;
3652 vxl = &zif->l2info.vxl;
2232a77c 3653
d63c1b18 3654 ifp = zvni->vxlan_if;
3655 vtep_ip = mac->fwd_info.r_vtep_ip;
2232a77c 3656
d63c1b18 3657 return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
2232a77c 3658}
3659
3660/*
3661 * Install MAC hash entry - called upon access VLAN change.
3662 */
e3b78da8 3663static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt)
2232a77c 3664{
d62a17ae 3665 zebra_mac_t *mac;
3666 struct mac_walk_ctx *wctx = ctxt;
2232a77c 3667
e3b78da8 3668 mac = (zebra_mac_t *)bucket->data;
2232a77c 3669
d62a17ae 3670 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
3671 zvni_mac_install(wctx->zvni, mac);
2232a77c 3672}
3673
fe697c6b 3674/*
3675 * Count of remote neighbors referencing this MAC.
3676 */
3677static int remote_neigh_count(zebra_mac_t *zmac)
3678{
3679 zebra_neigh_t *n = NULL;
3680 struct listnode *node = NULL;
3681 int count = 0;
3682
3683 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
3684 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
3685 count++;
3686 }
3687
3688 return count;
3689}
3690
2232a77c 3691/*
3692 * Decrement neighbor refcount of MAC; uninstall and free it if
3693 * appropriate.
3694 */
fe697c6b 3695static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 3696{
fe697c6b 3697 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
d62a17ae 3698 return;
2232a77c 3699
fe697c6b 3700 /* If all remote neighbors referencing a remote MAC go away,
3701 * we need to uninstall the MAC.
3702 */
3703 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) &&
3704 remote_neigh_count(mac) == 0) {
d63c1b18 3705 zvni_mac_uninstall(zvni, mac);
fe697c6b 3706 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
3707 }
2232a77c 3708
fe697c6b 3709 /* If no neighbors, delete the MAC. */
3710 if (list_isempty(mac->neigh_list))
3711 zvni_mac_del(zvni, mac);
2232a77c 3712}
3713
3714/*
3715 * Read and populate local MACs and neighbors corresponding to this VNI.
3716 */
996c9314 3717static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
2232a77c 3718{
2853fed6 3719 struct zebra_ns *zns;
d62a17ae 3720 struct zebra_if *zif;
3721 struct interface *vlan_if;
3722 struct zebra_l2info_vxlan *vxl;
1a98c087 3723 struct interface *vrr_if;
2232a77c 3724
d62a17ae 3725 zif = ifp->info;
3726 vxl = &zif->l2info.vxl;
2853fed6 3727 zns = zebra_ns_lookup(NS_DEFAULT);
2232a77c 3728
d62a17ae 3729 if (IS_ZEBRA_DEBUG_VXLAN)
3730 zlog_debug(
2853fed6 3731 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3732 ifp->name, ifp->ifindex, zvni->vni,
d62a17ae 3733 zif->brslave_info.bridge_ifindex);
2232a77c 3734
2853fed6 3735 macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if);
3736 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
1a98c087
MK
3737 if (vlan_if) {
3738
ead40654
MK
3739 /* Add SVI MAC-IP */
3740 zvni_add_macip_for_intf(vlan_if, zvni);
1a98c087 3741
ead40654
MK
3742 /* Add VRR MAC-IP - if any*/
3743 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
3744 if (vrr_if)
3745 zvni_add_macip_for_intf(vrr_if, zvni);
1a98c087 3746
2853fed6 3747 neigh_read_for_vlan(zns, vlan_if);
1a98c087 3748 }
2232a77c 3749}
3750
3751/*
3752 * Hash function for VNI.
3753 */
d62a17ae 3754static unsigned int vni_hash_keymake(void *p)
2232a77c 3755{
d62a17ae 3756 const zebra_vni_t *zvni = p;
2232a77c 3757
d62a17ae 3758 return (jhash_1word(zvni->vni, 0));
2232a77c 3759}
3760
3761/*
3762 * Compare 2 VNI hash entries.
3763 */
74df8d6d 3764static bool vni_hash_cmp(const void *p1, const void *p2)
2232a77c 3765{
d62a17ae 3766 const zebra_vni_t *zvni1 = p1;
3767 const zebra_vni_t *zvni2 = p2;
2232a77c 3768
d62a17ae 3769 return (zvni1->vni == zvni2->vni);
2232a77c 3770}
3771
27fa3398
DS
3772static int vni_list_cmp(void *p1, void *p2)
3773{
3774 const zebra_vni_t *zvni1 = p1;
3775 const zebra_vni_t *zvni2 = p2;
3776
3777 if (zvni1->vni == zvni2->vni)
3778 return 0;
3779 return (zvni1->vni < zvni2->vni) ? -1 : 1;
3780}
3781
2232a77c 3782/*
3783 * Callback to allocate VNI hash entry.
3784 */
d62a17ae 3785static void *zvni_alloc(void *p)
2232a77c 3786{
d62a17ae 3787 const zebra_vni_t *tmp_vni = p;
3788 zebra_vni_t *zvni;
2232a77c 3789
d62a17ae 3790 zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t));
3791 zvni->vni = tmp_vni->vni;
3792 return ((void *)zvni);
2232a77c 3793}
3794
3795/*
3796 * Look up VNI hash entry.
3797 */
2853fed6 3798static zebra_vni_t *zvni_lookup(vni_t vni)
2232a77c 3799{
2853fed6 3800 struct zebra_vrf *zvrf;
d62a17ae 3801 zebra_vni_t tmp_vni;
3802 zebra_vni_t *zvni = NULL;
2232a77c 3803
2853fed6 3804 zvrf = vrf_info_lookup(VRF_DEFAULT);
3805 assert(zvrf);
d62a17ae 3806 memset(&tmp_vni, 0, sizeof(zebra_vni_t));
3807 tmp_vni.vni = vni;
3808 zvni = hash_lookup(zvrf->vni_table, &tmp_vni);
2232a77c 3809
d62a17ae 3810 return zvni;
2232a77c 3811}
3812
3813/*
3814 * Add VNI hash entry.
3815 */
2853fed6 3816static zebra_vni_t *zvni_add(vni_t vni)
2232a77c 3817{
2853fed6 3818 struct zebra_vrf *zvrf;
d62a17ae 3819 zebra_vni_t tmp_zvni;
3820 zebra_vni_t *zvni = NULL;
2232a77c 3821
2853fed6 3822 zvrf = vrf_info_lookup(VRF_DEFAULT);
3823 assert(zvrf);
d62a17ae 3824 memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
3825 tmp_zvni.vni = vni;
3826 zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc);
3827 assert(zvni);
2232a77c 3828
d62a17ae 3829 /* Create hash table for MAC */
3830 zvni->mac_table =
3831 hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table");
2232a77c 3832
d62a17ae 3833 /* Create hash table for neighbors */
3834 zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp,
3835 "Zebra VNI Neighbor Table");
2232a77c 3836
d62a17ae 3837 return zvni;
2232a77c 3838}
3839
3840/*
3841 * Delete VNI hash entry.
3842 */
2853fed6 3843static int zvni_del(zebra_vni_t *zvni)
2232a77c 3844{
2853fed6 3845 struct zebra_vrf *zvrf;
d62a17ae 3846 zebra_vni_t *tmp_zvni;
2232a77c 3847
2853fed6 3848 zvrf = vrf_info_lookup(VRF_DEFAULT);
3849 assert(zvrf);
3850
d62a17ae 3851 zvni->vxlan_if = NULL;
2232a77c 3852
d62a17ae 3853 /* Free the neighbor hash table. */
3854 hash_free(zvni->neigh_table);
3855 zvni->neigh_table = NULL;
2232a77c 3856
d62a17ae 3857 /* Free the MAC hash table. */
3858 hash_free(zvni->mac_table);
3859 zvni->mac_table = NULL;
2232a77c 3860
d62a17ae 3861 /* Free the VNI hash entry and allocated memory. */
3862 tmp_zvni = hash_release(zvrf->vni_table, zvni);
0a22ddfb 3863 XFREE(MTYPE_ZVNI, tmp_zvni);
2232a77c 3864
d62a17ae 3865 return 0;
2232a77c 3866}
3867
3868/*
3869 * Inform BGP about local VNI addition.
3870 */
2853fed6 3871static int zvni_send_add_to_client(zebra_vni_t *zvni)
2232a77c 3872{
d62a17ae 3873 struct zserv *client;
3874 struct stream *s;
2232a77c 3875
21ccc0cf 3876 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
d62a17ae 3877 /* BGP may not be running. */
3878 if (!client)
3879 return 0;
2232a77c 3880
1002497a 3881 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2232a77c 3882
7cf15b25 3883 zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
d62a17ae 3884 stream_putl(s, zvni->vni);
3885 stream_put_in_addr(s, &zvni->local_vtep_ip);
b7cfce93 3886 stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
2232a77c 3887
d62a17ae 3888 /* Write packet size. */
3889 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 3890
d62a17ae 3891 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
3892 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni->vni,
3893 inet_ntoa(zvni->local_vtep_ip),
b7cfce93 3894 vrf_id_to_name(zvni->vrf_id),
d62a17ae 3895 zebra_route_string(client->proto));
2232a77c 3896
d62a17ae 3897 client->vniadd_cnt++;
21ccc0cf 3898 return zserv_send_message(client, s);
2232a77c 3899}
3900
3901/*
3902 * Inform BGP about local VNI deletion.
3903 */
2853fed6 3904static int zvni_send_del_to_client(vni_t vni)
2232a77c 3905{
d62a17ae 3906 struct zserv *client;
3907 struct stream *s;
2232a77c 3908
21ccc0cf 3909 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
d62a17ae 3910 /* BGP may not be running. */
3911 if (!client)
3912 return 0;
2232a77c 3913
1002497a 3914 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
d62a17ae 3915 stream_reset(s);
2232a77c 3916
7cf15b25 3917 zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
d62a17ae 3918 stream_putl(s, vni);
2232a77c 3919
d62a17ae 3920 /* Write packet size. */
3921 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 3922
d62a17ae 3923 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 3924 zlog_debug("Send VNI_DEL %u to %s", vni,
d62a17ae 3925 zebra_route_string(client->proto));
2232a77c 3926
d62a17ae 3927 client->vnidel_cnt++;
21ccc0cf 3928 return zserv_send_message(client, s);
2232a77c 3929}
3930
3931/*
3932 * Build the VNI hash table by going over the VxLAN interfaces. This
3933 * is called when EVPN (advertise-all-vni) is enabled.
3934 */
4d762f26 3935static void zvni_build_hash_table(void)
2232a77c 3936{
2853fed6 3937 struct zebra_ns *zns;
3938 struct route_node *rn;
d62a17ae 3939 struct interface *ifp;
2232a77c 3940
d62a17ae 3941 /* Walk VxLAN interfaces and create VNI hash. */
2853fed6 3942 zns = zebra_ns_lookup(NS_DEFAULT);
3943 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
b7cfce93 3944 vni_t vni;
643215ce 3945 zebra_vni_t *zvni = NULL;
3946 zebra_l3vni_t *zl3vni = NULL;
d62a17ae 3947 struct zebra_if *zif;
3948 struct zebra_l2info_vxlan *vxl;
2232a77c 3949
2853fed6 3950 ifp = (struct interface *)rn->info;
3951 if (!ifp)
3952 continue;
d62a17ae 3953 zif = ifp->info;
3954 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3955 continue;
2232a77c 3956
b7cfce93 3957 vxl = &zif->l2info.vxl;
d62a17ae 3958 vni = vxl->vni;
2232a77c 3959
643215ce 3960 /* L3-VNI and L2-VNI are handled seperately */
3961 zl3vni = zl3vni_lookup(vni);
3962 if (zl3vni) {
2232a77c 3963
b7cfce93 3964 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
3965 zlog_debug(
3966 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3967 ifp->name, ifp->ifindex, vni);
2232a77c 3968
b7cfce93 3969 /* associate with vxlan_if */
b67a60d2 3970 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 3971 zl3vni->vxlan_if = ifp;
2232a77c 3972
523cafc4 3973 /*
3974 * we need to associate with SVI.
b7cfce93 3975 * we can associate with svi-if only after association
523cafc4 3976 * with vxlan-intf is complete
3977 */
b7cfce93
MK
3978 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
3979
3980 if (is_l3vni_oper_up(zl3vni))
3981 zebra_vxlan_process_l3vni_oper_up(zl3vni);
3982
3983 } else {
b7cfce93
MK
3984 struct interface *vlan_if = NULL;
3985
3986 if (IS_ZEBRA_DEBUG_VXLAN)
3987 zlog_debug(
3988 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3989 ifp->name, ifp->ifindex, vni,
3990 inet_ntoa(vxl->vtep_ip));
3991
3992 /* VNI hash entry is not expected to exist. */
3993 zvni = zvni_lookup(vni);
3994 if (zvni) {
9df414fe 3995 zlog_debug(
b7cfce93
MK
3996 "VNI hash already present for IF %s(%u) L2-VNI %u",
3997 ifp->name, ifp->ifindex, vni);
3998 continue;
3999 }
4000
4001 zvni = zvni_add(vni);
4002 if (!zvni) {
9df414fe 4003 zlog_debug(
b7cfce93
MK
4004 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4005 ifp->name, ifp->ifindex, vni);
4006 return;
4007 }
4008
4009 zvni->local_vtep_ip = vxl->vtep_ip;
4010 zvni->vxlan_if = ifp;
4011 vlan_if = zvni_map_to_svi(vxl->access_vlan,
4012 zif->brslave_info.br_if);
4013 if (vlan_if) {
4014 zvni->vrf_id = vlan_if->vrf_id;
4015 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
4016 if (zl3vni)
4017 listnode_add_sort(zl3vni->l2vnis, zvni);
4018 }
4019
4020
4021 /* Inform BGP if intf is up and mapped to bridge. */
4022 if (if_is_operative(ifp) && zif->brslave_info.br_if)
4023 zvni_send_add_to_client(zvni);
4024 }
d62a17ae 4025 }
2232a77c 4026}
4027
4028/*
4029 * See if remote VTEP matches with prefix.
4030 */
d62a17ae 4031static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
2232a77c 4032{
d62a17ae 4033 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
2232a77c 4034}
4035
4036/*
4037 * Locate remote VTEP in VNI hash table.
4038 */
d62a17ae 4039static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 4040{
d62a17ae 4041 zebra_vtep_t *zvtep;
2232a77c 4042
d62a17ae 4043 if (!zvni)
4044 return NULL;
2232a77c 4045
d62a17ae 4046 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
4047 if (zvni_vtep_match(vtep_ip, zvtep))
4048 break;
4049 }
2232a77c 4050
d62a17ae 4051 return zvtep;
2232a77c 4052}
4053
4054/*
4055 * Add remote VTEP to VNI hash table.
4056 */
d62a17ae 4057static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 4058{
d62a17ae 4059 zebra_vtep_t *zvtep;
2232a77c 4060
d62a17ae 4061 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
2232a77c 4062
d62a17ae 4063 zvtep->vtep_ip = *vtep_ip;
2232a77c 4064
d62a17ae 4065 if (zvni->vteps)
4066 zvni->vteps->prev = zvtep;
4067 zvtep->next = zvni->vteps;
4068 zvni->vteps = zvtep;
2232a77c 4069
d62a17ae 4070 return zvtep;
2232a77c 4071}
4072
4073/*
4074 * Remove remote VTEP from VNI hash table.
4075 */
d62a17ae 4076static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
2232a77c 4077{
d62a17ae 4078 if (zvtep->next)
4079 zvtep->next->prev = zvtep->prev;
4080 if (zvtep->prev)
4081 zvtep->prev->next = zvtep->next;
4082 else
4083 zvni->vteps = zvtep->next;
2232a77c 4084
d62a17ae 4085 zvtep->prev = zvtep->next = NULL;
4086 XFREE(MTYPE_ZVNI_VTEP, zvtep);
2232a77c 4087
d62a17ae 4088 return 0;
2232a77c 4089}
4090
4091/*
4092 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4093 * uninstall from kernel if asked to.
4094 */
d62a17ae 4095static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
2232a77c 4096{
d62a17ae 4097 zebra_vtep_t *zvtep, *zvtep_next;
2232a77c 4098
d62a17ae 4099 if (!zvni)
4100 return -1;
2232a77c 4101
d62a17ae 4102 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
4103 zvtep_next = zvtep->next;
4104 if (uninstall)
4105 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
4106 zvni_vtep_del(zvni, zvtep);
4107 }
2232a77c 4108
d62a17ae 4109 return 0;
2232a77c 4110}
4111
4112/*
4113 * Install remote VTEP into the kernel.
4114 */
d62a17ae 4115static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 4116{
fbac9605
DS
4117 if (is_vxlan_flooding_head_end())
4118 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
4119 return 0;
2232a77c 4120}
4121
4122/*
4123 * Uninstall remote VTEP from the kernel.
4124 */
d62a17ae 4125static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 4126{
d62a17ae 4127 if (!zvni->vxlan_if) {
9df414fe
QY
4128 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4129 zvni->vni, zvni);
d62a17ae 4130 return -1;
4131 }
2232a77c 4132
d62a17ae 4133 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 4134}
4135
fbac9605
DS
4136/*
4137 * Install or uninstall flood entries in the kernel corresponding to
4138 * remote VTEPs. This is invoked upon change to BUM handling.
4139 */
e3b78da8 4140static void zvni_handle_flooding_remote_vteps(struct hash_bucket *bucket,
fbac9605
DS
4141 void *zvrf)
4142{
4143 zebra_vni_t *zvni;
4144 zebra_vtep_t *zvtep;
4145
e3b78da8 4146 zvni = (zebra_vni_t *)bucket->data;
fbac9605
DS
4147 if (!zvni)
4148 return;
4149
4150 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
4151 if (is_vxlan_flooding_head_end())
4152 zvni_vtep_install(zvni, &zvtep->vtep_ip);
4153 else
4154 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
4155 }
4156}
4157
2232a77c 4158/*
4159 * Cleanup VNI/VTEP and update kernel
4160 */
e3b78da8 4161static void zvni_cleanup_all(struct hash_bucket *bucket, void *arg)
2232a77c 4162{
b7cfce93
MK
4163 zebra_vni_t *zvni = NULL;
4164 zebra_l3vni_t *zl3vni = NULL;
84915b0a 4165 struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;
2232a77c 4166
e3b78da8 4167 zvni = (zebra_vni_t *)bucket->data;
2232a77c 4168
b7cfce93 4169 /* remove from l3-vni list */
84915b0a 4170 if (zvrf->l3vni)
4171 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93
MK
4172 if (zl3vni)
4173 listnode_delete(zl3vni->l2vnis, zvni);
4174
d62a17ae 4175 /* Free up all neighbors and MACs, if any. */
2853fed6 4176 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
4177 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
2232a77c 4178
d62a17ae 4179 /* Free up all remote VTEPs, if any. */
4180 zvni_vtep_del_all(zvni, 1);
2232a77c 4181
d62a17ae 4182 /* Delete the hash entry. */
2853fed6 4183 zvni_del(zvni);
2232a77c 4184}
4185
655b04d1 4186/* cleanup L3VNI */
e3b78da8 4187static void zl3vni_cleanup_all(struct hash_bucket *bucket, void *args)
655b04d1
MK
4188{
4189 zebra_l3vni_t *zl3vni = NULL;
4190
e3b78da8 4191 zl3vni = (zebra_l3vni_t *)bucket->data;
655b04d1
MK
4192
4193 zebra_vxlan_process_l3vni_oper_down(zl3vni);
4194}
4195
85442b09 4196static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe,
41db76c2 4197 struct prefix *host)
5e1b0650
DS
4198{
4199 struct host_rb_entry lookup;
4200 struct host_rb_entry *hle;
4201
4202 memset(&lookup, 0, sizeof(lookup));
4203 memcpy(&lookup.p, host, sizeof(*host));
4204
85442b09 4205 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
5e1b0650
DS
4206 if (hle)
4207 return;
4208
4209 hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry));
4210 memcpy(hle, &lookup, sizeof(lookup));
4211
85442b09 4212 RB_INSERT(host_rb_tree_entry, hrbe, hle);
5e1b0650
DS
4213}
4214
85442b09 4215static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host)
5e1b0650
DS
4216{
4217 struct host_rb_entry lookup;
4218 struct host_rb_entry *hle;
4219
4220 memset(&lookup, 0, sizeof(lookup));
4221 memcpy(&lookup.p, host, sizeof(*host));
4222
85442b09 4223 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
10ac2516 4224 if (hle) {
85442b09 4225 RB_REMOVE(host_rb_tree_entry, hrbe, hle);
10ac2516
DS
4226 XFREE(MTYPE_HOST_PREFIX, hle);
4227 }
5e1b0650
DS
4228
4229 return;
4230}
4231
b7cfce93
MK
4232/*
4233 * Look up MAC hash entry.
4234 */
2dbad57f 4235static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
b7cfce93
MK
4236 struct ethaddr *rmac)
4237{
4238 zebra_mac_t tmp;
4239 zebra_mac_t *pmac;
4240
4241 memset(&tmp, 0, sizeof(tmp));
4242 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
4243 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
2232a77c 4244
b7cfce93 4245 return pmac;
2dbad57f 4246}
2232a77c 4247
cec2e17d 4248/*
b7cfce93 4249 * Callback to allocate RMAC hash entry.
cec2e17d 4250 */
2dbad57f 4251static void *zl3vni_rmac_alloc(void *p)
d62a17ae 4252{
b7cfce93
MK
4253 const zebra_mac_t *tmp_rmac = p;
4254 zebra_mac_t *zrmac;
d62a17ae 4255
b7cfce93
MK
4256 zrmac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
4257 *zrmac = *tmp_rmac;
d62a17ae 4258
b7cfce93 4259 return ((void *)zrmac);
2dbad57f 4260}
cd233079 4261
b7cfce93
MK
4262/*
4263 * Add RMAC entry to l3-vni
4264 */
996c9314 4265static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac)
b7cfce93
MK
4266{
4267 zebra_mac_t tmp_rmac;
4268 zebra_mac_t *zrmac = NULL;
d62a17ae 4269
b7cfce93
MK
4270 memset(&tmp_rmac, 0, sizeof(zebra_mac_t));
4271 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
4272 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
4273 assert(zrmac);
d62a17ae 4274
85442b09 4275 RB_INIT(host_rb_tree_entry, &zrmac->host_rb);
b7cfce93 4276
2dbad57f 4277 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
4278 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
4279
b7cfce93 4280 return zrmac;
2dbad57f 4281}
cec2e17d 4282
4283/*
b7cfce93 4284 * Delete MAC entry.
cec2e17d 4285 */
996c9314 4286static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
cec2e17d 4287{
b7cfce93 4288 zebra_mac_t *tmp_rmac;
5e1b0650 4289 struct host_rb_entry *hle;
cd233079 4290
85442b09
DS
4291 while (!RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
4292 hle = RB_ROOT(host_rb_tree_entry, &zrmac->host_rb);
5e1b0650 4293
85442b09 4294 RB_REMOVE(host_rb_tree_entry, &zrmac->host_rb, hle);
5e1b0650
DS
4295 XFREE(MTYPE_HOST_PREFIX, hle);
4296 }
cd233079 4297
b7cfce93 4298 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
0a22ddfb 4299 XFREE(MTYPE_MAC, tmp_rmac);
cd233079 4300
b7cfce93 4301 return 0;
2dbad57f 4302}
cec2e17d 4303
4304/*
b7cfce93 4305 * Install remote RMAC into the kernel.
cec2e17d 4306 */
996c9314 4307static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
cec2e17d 4308{
b7cfce93
MK
4309 struct zebra_if *zif = NULL;
4310 struct zebra_l2info_vxlan *vxl = NULL;
cec2e17d 4311
996c9314
LB
4312 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
4313 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
4314 return 0;
4315
4316 zif = zl3vni->vxlan_if->info;
4317 if (!zif)
4318 return -1;
4319
4320 vxl = &zif->l2info.vxl;
4321
4322 return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
996c9314 4323 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
2dbad57f 4324}
b7cfce93
MK
4325
4326/*
4327 * Uninstall remote RMAC from the kernel.
4328 */
996c9314 4329static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
b7cfce93
MK
4330{
4331 char buf[ETHER_ADDR_STRLEN];
4332 struct zebra_if *zif = NULL;
4333 struct zebra_l2info_vxlan *vxl = NULL;
4334
996c9314
LB
4335 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
4336 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
4337 return 0;
4338
4339 if (!zl3vni->vxlan_if) {
9df414fe 4340 zlog_debug(
996c9314
LB
4341 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4342 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
4343 zl3vni->vni, zl3vni);
b7cfce93
MK
4344 return -1;
4345 }
4346
4347 zif = zl3vni->vxlan_if->info;
4348 if (!zif)
4349 return -1;
4350
4351 vxl = &zif->l2info.vxl;
4352
4353 return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
d63c1b18 4354 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
2dbad57f 4355}
4356
4357/* handle rmac add */
996c9314 4358static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
6134fd82 4359 struct ipaddr *vtep_ip,
4360 struct prefix *host_prefix)
2dbad57f 4361{
4362 char buf[ETHER_ADDR_STRLEN];
4363 char buf1[INET6_ADDRSTRLEN];
4364 zebra_mac_t *zrmac = NULL;
4365
4366 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
4367 if (!zrmac) {
4368
4369 zrmac = zl3vni_rmac_add(zl3vni, rmac);
4370 if (!zrmac) {
9df414fe 4371 zlog_debug(
2dbad57f 4372 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
996c9314
LB
4373 prefix_mac2str(rmac, buf, sizeof(buf)),
4374 zl3vni->vni,
4375 ipaddr2str(vtep_ip, buf1, sizeof(buf1)));
2dbad57f 4376 return -1;
4377 }
4378 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
4379 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
4380
4381 /* install rmac in kernel */
4382 zl3vni_rmac_install(zl3vni, zrmac);
4383 }
6134fd82 4384
41db76c2 4385 rb_find_or_add_host(&zrmac->host_rb, host_prefix);
5e1b0650 4386
2dbad57f 4387 return 0;
4388}
4389
4390
4391/* handle rmac delete */
22e63104 4392static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac,
6134fd82 4393 struct prefix *host_prefix)
2dbad57f 4394{
41db76c2 4395 rb_delete_host(&zrmac->host_rb, host_prefix);
2dbad57f 4396
85442b09 4397 if (RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
2dbad57f 4398 /* uninstall from kernel */
4399 zl3vni_rmac_uninstall(zl3vni, zrmac);
4400
4401 /* del the rmac entry */
4402 zl3vni_rmac_del(zl3vni, zrmac);
4403 }
2dbad57f 4404}
b7cfce93
MK
4405
4406/*
4407 * Look up nh hash entry on a l3-vni.
4408 */
996c9314 4409static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
b7cfce93
MK
4410{
4411 zebra_neigh_t tmp;
4412 zebra_neigh_t *n;
4413
4414 memset(&tmp, 0, sizeof(tmp));
4415 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
4416 n = hash_lookup(zl3vni->nh_table, &tmp);
4417
4418 return n;
2dbad57f 4419}
b7cfce93
MK
4420
4421
4422/*
4423 * Callback to allocate NH hash entry on L3-VNI.
4424 */
2dbad57f 4425static void *zl3vni_nh_alloc(void *p)
b7cfce93
MK
4426{
4427 const zebra_neigh_t *tmp_n = p;
4428 zebra_neigh_t *n;
4429
4430 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
4431 *n = *tmp_n;
4432
4433 return ((void *)n);
2dbad57f 4434}
b7cfce93
MK
4435
4436/*
4437 * Add neighbor entry.
4438 */
996c9314 4439static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
b7cfce93
MK
4440 struct ethaddr *mac)
4441{
4442 zebra_neigh_t tmp_n;
4443 zebra_neigh_t *n = NULL;
4444
4445 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
4446 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
4447 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
4448 assert(n);
4449
85442b09 4450 RB_INIT(host_rb_tree_entry, &n->host_rb);
6134fd82 4451
b7cfce93 4452 memcpy(&n->emac, mac, ETH_ALEN);
2dbad57f 4453 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
4454 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
b7cfce93
MK
4455
4456 return n;
2dbad57f 4457}
b7cfce93
MK
4458
4459/*
4460 * Delete neighbor entry.
4461 */
996c9314 4462static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
b7cfce93
MK
4463{
4464 zebra_neigh_t *tmp_n;
f2a503f0 4465 struct host_rb_entry *hle;
b7cfce93 4466
85442b09
DS
4467 while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) {
4468 hle = RB_ROOT(host_rb_tree_entry, &n->host_rb);
f2a503f0 4469
85442b09 4470 RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle);
f2a503f0
DS
4471 XFREE(MTYPE_HOST_PREFIX, hle);
4472 }
55aabf6f 4473
b7cfce93 4474 tmp_n = hash_release(zl3vni->nh_table, n);
0a22ddfb 4475 XFREE(MTYPE_NEIGH, tmp_n);
b7cfce93
MK
4476
4477 return 0;
2dbad57f 4478}
b7cfce93
MK
4479
4480/*
4481 * Install remote nh as neigh into the kernel.
4482 */
996c9314 4483static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
b7cfce93 4484{
f7dae312 4485#ifdef GNU_LINUX
68e33151 4486 uint8_t flags;
f7dae312 4487#endif
68e33151
CS
4488 int ret = 0;
4489
b7cfce93
MK
4490 if (!is_l3vni_oper_up(zl3vni))
4491 return -1;
4492
996c9314
LB
4493 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
4494 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93 4495 return 0;
68e33151
CS
4496#ifdef GNU_LINUX
4497 flags = NTF_EXT_LEARNED;
4498 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
4499 flags |= NTF_ROUTER;
4500 ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags);
4501#endif
4502 return ret;
2dbad57f 4503}
b7cfce93
MK
4504
4505/*
4506 * Uninstall remote nh from the kernel.
4507 */
996c9314 4508static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
b7cfce93 4509{
996c9314
LB
4510 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
4511 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93
MK
4512 return 0;
4513
fa409e1e 4514 if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
4515 return 0;
4516
b7cfce93 4517 return kernel_del_neigh(zl3vni->svi_if, &n->ip);
2dbad57f 4518}
4519
4520/* add remote vtep as a neigh entry */
996c9314 4521static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
6134fd82 4522 struct ethaddr *rmac,
4523 struct prefix *host_prefix)
2dbad57f 4524{
4525 char buf[ETHER_ADDR_STRLEN];
4526 char buf1[INET6_ADDRSTRLEN];
4527 zebra_neigh_t *nh = NULL;
4528
4529 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
4530 if (!nh) {
4531 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
4532 if (!nh) {
4533
9df414fe 4534 zlog_debug(
2dbad57f 4535 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
996c9314
LB
4536 ipaddr2str(vtep_ip, buf1, sizeof(buf1)),
4537 prefix_mac2str(rmac, buf, sizeof(buf)),
2dbad57f 4538 zl3vni->vni);
4539 return -1;
4540 }
4541
4542 /* install the nh neigh in kernel */
4543 zl3vni_nh_install(zl3vni, nh);
4544 }
6134fd82 4545
f2a503f0 4546 rb_find_or_add_host(&nh->host_rb, host_prefix);
6134fd82 4547
2dbad57f 4548 return 0;
4549}
4550
4551/* handle nh neigh delete */
22e63104 4552static void zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *nh,
4553 struct prefix *host_prefix)
2dbad57f 4554{
f2a503f0 4555 rb_delete_host(&nh->host_rb, host_prefix);
2dbad57f 4556
85442b09 4557 if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) {
2dbad57f 4558 /* uninstall from kernel */
4559 zl3vni_nh_uninstall(zl3vni, nh);
4560
4561 /* delete the nh entry */
4562 zl3vni_nh_del(zl3vni, nh);
4563 }
2dbad57f 4564}
b7cfce93 4565
3bcbba10 4566/* handle neigh update from kernel - the only thing of interest is to
4567 * readd stale entries.
4568 */
996c9314 4569static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
d7c0a89a 4570 uint16_t state)
3bcbba10 4571{
c05a738b 4572#ifdef GNU_LINUX
3bcbba10 4573 zebra_neigh_t *n = NULL;
4574
4575 n = zl3vni_nh_lookup(zl3vni, ip);
4576 if (!n)
4577 return 0;
4578
4579 /* all next hop neigh are remote and installed by frr.
4580 * If the kernel has aged this entry, re-install.
4581 */
4582 if (state & NUD_STALE)
4583 zl3vni_nh_install(zl3vni, n);
c05a738b 4584#endif
3bcbba10 4585 return 0;
4586}
4587
8c9b80b9 4588/* handle neigh delete from kernel */
996c9314 4589static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
8c9b80b9
MK
4590{
4591 zebra_neigh_t *n = NULL;
4592
4593 n = zl3vni_nh_lookup(zl3vni, ip);
4594 if (!n)
4595 return 0;
4596
4597 /* all next hop neigh are remote and installed by frr.
4598 * If we get an age out notification for these neigh entries, we have to
523cafc4 4599 * install it back
4600 */
8c9b80b9
MK
4601 zl3vni_nh_install(zl3vni, n);
4602
4603 return 0;
4604}
4605
b7cfce93
MK
4606/*
4607 * Hash function for L3 VNI.
4608 */
4609static unsigned int l3vni_hash_keymake(void *p)
4610{
4611 const zebra_l3vni_t *zl3vni = p;
4612
4613 return jhash_1word(zl3vni->vni, 0);
4614}
4615
4616/*
4617 * Compare 2 L3 VNI hash entries.
4618 */
74df8d6d 4619static bool l3vni_hash_cmp(const void *p1, const void *p2)
b7cfce93
MK
4620{
4621 const zebra_l3vni_t *zl3vni1 = p1;
4622 const zebra_l3vni_t *zl3vni2 = p2;
4623
4624 return (zl3vni1->vni == zl3vni2->vni);
4625}
4626
4627/*
4628 * Callback to allocate L3 VNI hash entry.
4629 */
4630static void *zl3vni_alloc(void *p)
4631{
4632 zebra_l3vni_t *zl3vni = NULL;
4633 const zebra_l3vni_t *tmp_l3vni = p;
4634
4635 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(zebra_l3vni_t));
4636 zl3vni->vni = tmp_l3vni->vni;
4637 return ((void *)zl3vni);
4638}
4639
4640/*
4641 * Look up L3 VNI hash entry.
4642 */
4643static zebra_l3vni_t *zl3vni_lookup(vni_t vni)
4644{
b7cfce93
MK
4645 zebra_l3vni_t tmp_l3vni;
4646 zebra_l3vni_t *zl3vni = NULL;
4647
b7cfce93
MK
4648 memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t));
4649 tmp_l3vni.vni = vni;
89272910 4650 zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni);
b7cfce93
MK
4651
4652 return zl3vni;
4653}
4654
4655/*
4656 * Add L3 VNI hash entry.
4657 */
4658static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
4659{
4660 zebra_l3vni_t tmp_zl3vni;
b7cfce93
MK
4661 zebra_l3vni_t *zl3vni = NULL;
4662
b7cfce93
MK
4663 memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t));
4664 tmp_zl3vni.vni = vni;
4665
89272910 4666 zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc);
b7cfce93
MK
4667 assert(zl3vni);
4668
4669 zl3vni->vrf_id = vrf_id;
4670 zl3vni->svi_if = NULL;
4671 zl3vni->vxlan_if = NULL;
4672 zl3vni->l2vnis = list_new();
27fa3398 4673 zl3vni->l2vnis->cmp = vni_list_cmp;
b7cfce93
MK
4674
4675 /* Create hash table for remote RMAC */
996c9314
LB
4676 zl3vni->rmac_table = hash_create(mac_hash_keymake, mac_cmp,
4677 "Zebra L3-VNI RMAC-Table");
b7cfce93
MK
4678
4679 /* Create hash table for neighbors */
4680 zl3vni->nh_table = hash_create(neigh_hash_keymake, neigh_cmp,
996c9314 4681 "Zebra L3-VNI next-hop table");
b7cfce93
MK
4682
4683 return zl3vni;
4684}
4685
4686/*
4687 * Delete L3 VNI hash entry.
4688 */
4689static int zl3vni_del(zebra_l3vni_t *zl3vni)
4690{
b7cfce93
MK
4691 zebra_l3vni_t *tmp_zl3vni;
4692
b7cfce93 4693 /* free the list of l2vnis */
6a154c88 4694 list_delete(&zl3vni->l2vnis);
b7cfce93
MK
4695 zl3vni->l2vnis = NULL;
4696
4697 /* Free the rmac table */
4698 hash_free(zl3vni->rmac_table);
4699 zl3vni->rmac_table = NULL;
4700
4701 /* Free the nh table */
4702 hash_free(zl3vni->nh_table);
4703 zl3vni->nh_table = NULL;
4704
4705 /* Free the VNI hash entry and allocated memory. */
89272910 4706 tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
0a22ddfb 4707 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
b7cfce93
MK
4708
4709 return 0;
4710}
4711
b7cfce93
MK
4712static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
4713{
4714 struct zebra_ns *zns = NULL;
4715 struct route_node *rn = NULL;
4716 struct interface *ifp = NULL;
4717
4718 /* loop through all vxlan-interface */
4719 zns = zebra_ns_lookup(NS_DEFAULT);
4720 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
4721
4722 struct zebra_if *zif = NULL;
4723 struct zebra_l2info_vxlan *vxl = NULL;
4724
4725 ifp = (struct interface *)rn->info;
4726 if (!ifp)
4727 continue;
4728
4729 zif = ifp->info;
4730 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
4731 continue;
4732
4733 vxl = &zif->l2info.vxl;
b67a60d2 4734 if (vxl->vni == zl3vni->vni) {
4735 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 4736 return ifp;
b67a60d2 4737 }
b7cfce93
MK
4738 }
4739
4740 return NULL;
4741}
4742
4743static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
4744{
996c9314 4745 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
b7cfce93
MK
4746 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
4747
2aeb403d 4748 if (!zl3vni)
4749 return NULL;
4750
b7cfce93
MK
4751 if (!zl3vni->vxlan_if)
4752 return NULL;
4753
4754 zif = zl3vni->vxlan_if->info;
4755 if (!zif)
4756 return NULL;
4757
4758 vxl = &zif->l2info.vxl;
4759
4760 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
4761}
4762
4763static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
4764{
4765 struct zebra_vrf *zvrf = NULL;
4766
4767 zvrf = zebra_vrf_lookup_by_id(vrf_id);
4768 if (!zvrf)
4769 return NULL;
4770
4771 return zl3vni_lookup(zvrf->l3vni);
4772}
4773
4774/*
4775 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4776 * neighbor notifications, to see if they are of interest.
4777 */
4778static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp,
4779 struct interface *br_if)
4780{
4781 int found = 0;
4782 vlanid_t vid = 0;
d7c0a89a 4783 uint8_t bridge_vlan_aware = 0;
b7cfce93
MK
4784 zebra_l3vni_t *zl3vni = NULL;
4785 struct zebra_ns *zns = NULL;
4786 struct route_node *rn = NULL;
4787 struct zebra_if *zif = NULL;
4788 struct interface *tmp_if = NULL;
4789 struct zebra_l2info_bridge *br = NULL;
4790 struct zebra_l2info_vxlan *vxl = NULL;
4791
4792 if (!br_if)
4793 return NULL;
4794
4795 /* Make sure the linked interface is a bridge. */
4796 if (!IS_ZEBRA_IF_BRIDGE(br_if))
4797 return NULL;
4798
4799 /* Determine if bridge is VLAN-aware or not */
4800 zif = br_if->info;
4801 assert(zif);
4802 br = &zif->l2info.br;
4803 bridge_vlan_aware = br->vlan_aware;
4804 if (bridge_vlan_aware) {
4805 struct zebra_l2info_vlan *vl;
4806
4807 if (!IS_ZEBRA_IF_VLAN(ifp))
4808 return NULL;
4809
4810 zif = ifp->info;
4811 assert(zif);
4812 vl = &zif->l2info.vl;
4813 vid = vl->vid;
4814 }
4815
4816 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4817 /* TODO: Optimize with a hash. */
4818 zns = zebra_ns_lookup(NS_DEFAULT);
4819 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
4820 tmp_if = (struct interface *)rn->info;
4821 if (!tmp_if)
4822 continue;
4823 zif = tmp_if->info;
4824 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
4825 continue;
4826 if (!if_is_operative(tmp_if))
4827 continue;
4828 vxl = &zif->l2info.vxl;
4829
4830 if (zif->brslave_info.br_if != br_if)
4831 continue;
4832
4833 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
4834 found = 1;
4835 break;
4836 }
4837 }
4838
4839 if (!found)
4840 return NULL;
4841
4842 zl3vni = zl3vni_lookup(vxl->vni);
4843 return zl3vni;
4844}
4845
4846/*
4847 * Inform BGP about l3-vni.
4848 */
4849static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
4850{
4851 struct stream *s = NULL;
4852 struct zserv *client = NULL;
4853 struct ethaddr rmac;
4854 char buf[ETHER_ADDR_STRLEN];
4855
21ccc0cf 4856 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
4857 /* BGP may not be running. */
4858 if (!client)
4859 return 0;
4860
4861 /* get the rmac */
4862 memset(&rmac, 0, sizeof(struct ethaddr));
4863 zl3vni_get_rmac(zl3vni, &rmac);
4864
1002497a 4865 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 4866
996c9314 4867 zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
b7cfce93
MK
4868 stream_putl(s, zl3vni->vni);
4869 stream_put(s, &rmac, sizeof(struct ethaddr));
b67a60d2 4870 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
c48d9f5f 4871 stream_put(s, &zl3vni->filter, sizeof(int));
0483af6e 4872 stream_putl(s, zl3vni->svi_if->ifindex);
b7cfce93
MK
4873
4874 /* Write packet size. */
4875 stream_putw_at(s, 0, stream_get_endp(s));
4876
4877 if (IS_ZEBRA_DEBUG_VXLAN)
c48d9f5f 4878 zlog_debug(
996c9314
LB
4879 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4880 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
4881 prefix_mac2str(&rmac, buf, sizeof(buf)),
4882 inet_ntoa(zl3vni->local_vtep_ip),
4883 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
4884 ? "prefix-routes-only"
4885 : "none",
4886 zebra_route_string(client->proto));
b7cfce93
MK
4887
4888 client->l3vniadd_cnt++;
21ccc0cf 4889 return zserv_send_message(client, s);
b7cfce93
MK
4890}
4891
4892/*
4893 * Inform BGP about local l3-VNI deletion.
4894 */
4895static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
4896{
4897 struct stream *s = NULL;
4898 struct zserv *client = NULL;
4899
21ccc0cf 4900 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
4901 /* BGP may not be running. */
4902 if (!client)
4903 return 0;
4904
1002497a 4905 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 4906
996c9314 4907 zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
b7cfce93
MK
4908 stream_putl(s, zl3vni->vni);
4909
4910 /* Write packet size. */
4911 stream_putw_at(s, 0, stream_get_endp(s));
4912
4913 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 4914 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
b7cfce93
MK
4915 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
4916 zebra_route_string(client->proto));
4917
4918 client->l3vnidel_cnt++;
21ccc0cf 4919 return zserv_send_message(client, s);
b7cfce93
MK
4920}
4921
4922static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
4923{
2aeb403d 4924 if (!zl3vni)
4925 return;
4926
b7cfce93
MK
4927 /* send l3vni add to BGP */
4928 zl3vni_send_add_to_client(zl3vni);
4929}
4930
4931static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni)
4932{
2aeb403d 4933 if (!zl3vni)
4934 return;
4935
b7cfce93
MK
4936 /* send l3-vni del to BGP*/
4937 zl3vni_send_del_to_client(zl3vni);
4938}
4939
e3b78da8 4940static void zvni_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt)
b7cfce93 4941{
e3b78da8 4942 zebra_vni_t *zvni = (zebra_vni_t *)bucket->data;
996c9314 4943 zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)ctxt;
b7cfce93
MK
4944
4945 if (zvni->vrf_id == zl3vni_vrf_id(zl3vni))
4946 listnode_add_sort(zl3vni->l2vnis, zvni);
4947}
4948
b7cfce93
MK
4949/*
4950 * handle transition of vni from l2 to l3 and vice versa
4951 */
996c9314
LB
4952static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
4953 int add)
b7cfce93
MK
4954{
4955 zebra_vni_t *zvni = NULL;
4956
4957 /* There is a possibility that VNI notification was already received
4958 * from kernel and we programmed it as L2-VNI
4959 * In such a case we need to delete this L2-VNI first, so
4960 * that it can be reprogrammed as L3-VNI in the system. It is also
4961 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4962 * interface is still present in kernel. In this case to keep it
523cafc4 4963 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4964 */
b7cfce93
MK
4965 if (add) {
4966 /* Locate hash entry */
4967 zvni = zvni_lookup(vni);
4968 if (!zvni)
4969 return 0;
4970
4971 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 4972 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
b7cfce93
MK
4973
4974 /* Delete VNI from BGP. */
4975 zvni_send_del_to_client(zvni->vni);
4976
4977 /* Free up all neighbors and MAC, if any. */
4978 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
4979 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
4980
4981 /* Free up all remote VTEPs, if any. */
4982 zvni_vtep_del_all(zvni, 0);
4983
4984 /* Delete the hash entry. */
4985 if (zvni_del(zvni)) {
e914ccbe 4986 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
1c50c1c0
QY
4987 "Failed to del VNI hash %p, VNI %u", zvni,
4988 zvni->vni);
b7cfce93
MK
4989 return -1;
4990 }
4991 } else {
4992 /* TODO_MITESH: This needs to be thought through. We don't have
4993 * enough information at this point to reprogram the vni as
4994 * l2-vni. One way is to store the required info in l3-vni and
523cafc4 4995 * used it solely for this purpose
4996 */
b7cfce93
MK
4997 }
4998
4999 return 0;
5000}
5001
5e06422c 5002/* delete and uninstall rmac hash entry */
e3b78da8 5003static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx)
5e06422c
MK
5004{
5005 zebra_mac_t *zrmac = NULL;
5006 zebra_l3vni_t *zl3vni = NULL;
5007
e3b78da8 5008 zrmac = (zebra_mac_t *)bucket->data;
5e06422c
MK
5009 zl3vni = (zebra_l3vni_t *)ctx;
5010 zl3vni_rmac_uninstall(zl3vni, zrmac);
5011 zl3vni_rmac_del(zl3vni, zrmac);
5012}
5013
5014/* delete and uninstall nh hash entry */
e3b78da8 5015static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)
5e06422c
MK
5016{
5017 zebra_neigh_t *n = NULL;
5018 zebra_l3vni_t *zl3vni = NULL;
5019
e3b78da8 5020 n = (zebra_neigh_t *)bucket->data;
5e06422c
MK
5021 zl3vni = (zebra_l3vni_t *)ctx;
5022 zl3vni_nh_uninstall(zl3vni, n);
5023 zl3vni_nh_del(zl3vni, n);
5024}
5025
996c9314
LB
5026static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
5027 uint16_t cmd)
31310b25
MK
5028{
5029 struct zserv *client = NULL;
5030 struct stream *s = NULL;
5031 char buf[PREFIX_STRLEN];
5032
21ccc0cf 5033 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
31310b25
MK
5034 /* BGP may not be running. */
5035 if (!client)
5036 return 0;
5037
1002497a 5038 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
31310b25 5039
22bd3e94 5040 zclient_create_header(s, cmd, vrf_id);
31310b25
MK
5041 stream_put(s, p, sizeof(struct prefix));
5042
5043 /* Write packet size. */
5044 stream_putw_at(s, 0, stream_get_endp(s));
5045
5046 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 5047 zlog_debug("Send ip prefix %s %s on vrf %s",
31310b25
MK
5048 prefix2str(p, buf, sizeof(buf)),
5049 (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL",
5050 vrf_id_to_name(vrf_id));
5051
5052 if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD)
5053 client->prefixadd_cnt++;
5054 else
5055 client->prefixdel_cnt++;
5056
21ccc0cf 5057 return zserv_send_message(client, s);
31310b25
MK
5058}
5059
a9a76262
MK
5060/* re-add remote rmac if needed */
5061static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
996c9314 5062 struct ethaddr *rmac)
a9a76262
MK
5063{
5064 char buf[ETHER_ADDR_STRLEN];
5065 zebra_mac_t *zrmac = NULL;
5066
5067 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
5068 if (!zrmac)
5069 return 0;
5070
5071 if (IS_ZEBRA_DEBUG_VXLAN)
5072 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
996c9314 5073 prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni);
a9a76262
MK
5074
5075 zl3vni_rmac_install(zl3vni, zrmac);
5076 return 0;
5077}
5078
f07e1c99 5079/* Process a remote MACIP add from BGP. */
5080static void process_remote_macip_add(vni_t vni,
5081 struct ethaddr *macaddr,
9df2b997 5082 uint16_t ipa_len,
f07e1c99 5083 struct ipaddr *ipaddr,
9df2b997 5084 uint8_t flags,
f07e1c99 5085 uint32_t seq,
5086 struct in_addr vtep_ip)
c48d9f5f 5087{
f07e1c99 5088 zebra_vni_t *zvni;
5089 zebra_vtep_t *zvtep;
e22a946a 5090 zebra_mac_t *mac = NULL, *old_mac = NULL;
f07e1c99 5091 zebra_neigh_t *n = NULL;
5092 int update_mac = 0, update_neigh = 0;
5093 char buf[ETHER_ADDR_STRLEN];
5094 char buf1[INET6_ADDRSTRLEN];
5095 struct interface *ifp = NULL;
5096 struct zebra_if *zif = NULL;
e22a946a 5097 struct zebra_vrf *zvrf;
f07e1c99 5098 uint32_t tmp_seq;
a37f4598 5099 bool sticky;
5100 bool remote_gw;
5101 bool is_router;
e22a946a
CS
5102 bool do_dad = false;
5103 bool is_dup_detect = false;
c48d9f5f 5104
f07e1c99 5105 /* Locate VNI hash entry - expected to exist. */
5106 zvni = zvni_lookup(vni);
5107 if (!zvni) {
5108 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni);
5109 return;
5110 }
2dbad57f 5111
f07e1c99 5112 ifp = zvni->vxlan_if;
5113 if (ifp)
5114 zif = ifp->info;
5115 if (!ifp ||
5116 !if_is_operative(ifp) ||
5117 !zif ||
5118 !zif->brslave_info.br_if) {
5119 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5120 vni);
2dbad57f 5121 return;
f07e1c99 5122 }
2dbad57f 5123
f07e1c99 5124 /* The remote VTEP specified should normally exist, but it is
5125 * possible that when peering comes up, peer may advertise MACIP
5126 * routes before advertising type-3 routes.
f50dc5e6 5127 */
f07e1c99 5128 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5129 if (!zvtep) {
5130 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5131 flog_err(
e914ccbe 5132 EC_ZEBRA_VTEP_ADD_FAILED,
f07e1c99 5133 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5134 vni, zvni);
5135 return;
5136 }
2dbad57f 5137
f07e1c99 5138 zvni_vtep_install(zvni, &vtep_ip);
5139 }
f50dc5e6 5140
a37f4598 5141 sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
5142 remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
5143 is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
2dbad57f 5144
f07e1c99 5145 mac = zvni_mac_lookup(zvni, macaddr);
2dbad57f 5146
f07e1c99 5147 /* Ignore if the mac is already present as a gateway mac */
5148 if (mac &&
5149 CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) &&
5150 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
5151 if (IS_ZEBRA_DEBUG_VXLAN)
5152 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5153 vni,
5154 prefix_mac2str(macaddr, buf, sizeof(buf)),
5155 ipa_len ? " IP " : "",
5156 ipa_len ?
5157 ipaddr2str(ipaddr, buf1, sizeof(buf1)) : "");
2dbad57f 5158 return;
f07e1c99 5159 }
2dbad57f 5160
e22a946a
CS
5161 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
5162 if (!zvrf)
5163 return;
5164
f07e1c99 5165 /* check if the remote MAC is unknown or has a change.
5166 * If so, that needs to be updated first. Note that client could
5167 * install MAC and MACIP separately or just install the latter.
5168 */
5169 if (!mac
5170 || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
a37f4598 5171 || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
5172 || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
f07e1c99 5173 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
5174 || seq != mac->rem_seq)
5175 update_mac = 1;
5176
5177 if (update_mac) {
5178 if (!mac) {
5179 mac = zvni_mac_add(zvni, macaddr);
5180 if (!mac) {
5181 zlog_warn(
5182 "Failed to add MAC %s VNI %u Remote VTEP %s",
5183 prefix_mac2str(macaddr, buf,
5184 sizeof(buf)),
5185 vni, inet_ntoa(vtep_ip));
5186 return;
5187 }
5188
5189 /* Is this MAC created for a MACIP? */
5190 if (ipa_len)
5191 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5192 } else {
5193 const char *mac_type;
5194
5195 /* When host moves but changes its (MAC,IP)
5196 * binding, BGP may install a MACIP entry that
5197 * corresponds to "older" location of the host
5198 * in transient situations (because {IP1,M1}
5199 * is a different route from {IP1,M2}). Check
5200 * the sequence number and ignore this update
5201 * if appropriate.
5202 */
5203 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
5204 tmp_seq = mac->loc_seq;
5205 mac_type = "local";
5206 } else {
5207 tmp_seq = mac->rem_seq;
5208 mac_type = "remote";
5209 }
5210 if (seq < tmp_seq) {
5211 if (IS_ZEBRA_DEBUG_VXLAN)
5212 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5213 vni,
5214 prefix_mac2str(macaddr,
5215 buf, sizeof(buf)),
5216 ipa_len ? " IP " : "",
5217 ipa_len ?
5218 ipaddr2str(ipaddr,
5219 buf1, sizeof(buf1)) : "",
5220 mac_type,
5221 tmp_seq);
5222 return;
5223 }
5224 }
5225
e22a946a
CS
5226 /* Check MAC's curent state is local (this is the case
5227 * where MAC has moved from L->R) and check previous
5228 * detection started via local learning.
5229 * RFC-7432: A PE/VTEP that detects a MAC mobility
5230 * event via local learning starts an M-second timer.
5231 *
753ad4fe 5232 * VTEP-IP or seq. change alone is not considered
e22a946a 5233 * for dup. detection.
753ad4fe
CS
5234 *
5235 * MAC is already marked duplicate set dad, then
5236 * is_dup_detect will be set to not install the entry.
e22a946a 5237 */
753ad4fe
CS
5238 if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) &&
5239 mac->dad_count) ||
5240 CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
e22a946a
CS
5241 do_dad = true;
5242
e98e4b88
AK
5243 /* Remove local MAC from BGP. */
5244 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5245 zvni_mac_send_del_to_client(zvni->vni, macaddr);
5246
f07e1c99 5247 /* Set "auto" and "remote" forwarding info. */
5248 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5249 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
5250 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5251 mac->fwd_info.r_vtep_ip = vtep_ip;
5252
5253 if (sticky)
5254 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5255 else
5256 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5257
5258 if (remote_gw)
5259 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
5260 else
5261 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
5262
bdca1974
CS
5263 zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac,
5264 mac->fwd_info.r_vtep_ip,
5265 do_dad, &is_dup_detect,
5266 false);
e22a946a 5267
a4445ece
CS
5268 if (!is_dup_detect) {
5269 zvni_process_neigh_on_remote_mac_add(zvni, mac);
5270 /* Install the entry. */
e22a946a 5271 zvni_mac_install(zvni, mac);
a4445ece 5272 }
f07e1c99 5273 }
5274
5275 /* Update seq number. */
5276 mac->rem_seq = seq;
5277
5278 /* If there is no IP, return after clearing AUTO flag of MAC. */
5279 if (!ipa_len) {
5280 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5281 return;
5282 }
5283
e22a946a
CS
5284 /* Reset flag */
5285 do_dad = false;
5286
f07e1c99 5287 /* Check if the remote neighbor itself is unknown or has a
5288 * change. If so, create or update and then install the entry.
5289 */
5290 n = zvni_neigh_lookup(zvni, ipaddr);
5291 if (!n
5292 || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
a37f4598 5293 || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)
f07e1c99 5294 || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0)
5295 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)
5296 || seq != n->rem_seq)
5297 update_neigh = 1;
5298
5299 if (update_neigh) {
5300 if (!n) {
5301 n = zvni_neigh_add(zvni, ipaddr, macaddr);
5302 if (!n) {
5303 zlog_warn(
5304 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5305 ipaddr2str(ipaddr, buf1,
5306 sizeof(buf1)),
5307 prefix_mac2str(macaddr, buf,
5308 sizeof(buf)),
5309 vni, inet_ntoa(vtep_ip));
5310 return;
5311 }
5312
5313 } else {
5314 const char *n_type;
5315
5316 /* When host moves but changes its (MAC,IP)
5317 * binding, BGP may install a MACIP entry that
5318 * corresponds to "older" location of the host
5319 * in transient situations (because {IP1,M1}
5320 * is a different route from {IP1,M2}). Check
5321 * the sequence number and ignore this update
5322 * if appropriate.
5323 */
5324 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
5325 tmp_seq = n->loc_seq;
5326 n_type = "local";
5327 } else {
5328 tmp_seq = n->rem_seq;
5329 n_type = "remote";
5330 }
5331 if (seq < tmp_seq) {
5332 if (IS_ZEBRA_DEBUG_VXLAN)
5333 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5334 vni,
5335 prefix_mac2str(macaddr,
5336 buf, sizeof(buf)),
4848ef74
A
5337 " IP ",
5338 ipaddr2str(ipaddr, buf1, sizeof(buf1)),
f07e1c99 5339 n_type,
5340 tmp_seq);
5341 return;
5342 }
5343 if (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) {
5344 /* MAC change, send a delete for old
5345 * neigh if learnt locally.
5346 */
5347 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) &&
5348 IS_ZEBRA_NEIGH_ACTIVE(n))
5349 zvni_neigh_send_del_to_client(
5350 zvni->vni, &n->ip,
2c476b72 5351 &n->emac, 0, n->state);
f07e1c99 5352
5353 /* update neigh list for macs */
5354 old_mac = zvni_mac_lookup(zvni, &n->emac);
5355 if (old_mac) {
5356 listnode_delete(old_mac->neigh_list, n);
fe697c6b 5357 zvni_deref_ip2mac(zvni, old_mac);
f07e1c99 5358 }
5359 listnode_add_sort(mac->neigh_list, n);
5360 memcpy(&n->emac, macaddr, ETH_ALEN);
e22a946a
CS
5361
5362 /* Check Neigh's curent state is local
5363 * (this is the case where neigh/host has moved
5364 * from L->R) and check previous detction
5365 * started via local learning.
5366 *
5367 * RFC-7432: A PE/VTEP that detects a MAC
5368 * mobilit event via local learning starts
5369 * an M-second timer.
5370 * VTEP-IP or seq. change along is not
5371 * considered for dup. detection.
5372 *
5373 * Mobilty event scenario-B IP-MAC binding
5374 * changed.
5375 */
5376 if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
5377 && n->dad_count)
5378 do_dad = true;
5379
f07e1c99 5380 }
5381 }
5382
5383 /* Set "remote" forwarding info. */
5384 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
5385 n->r_vtep_ip = vtep_ip;
5386 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
5387
5388 /* Set router flag (R-bit) to this Neighbor entry */
5389 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
5390 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
f190902f 5391 else
5392 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
f07e1c99 5393
e22a946a
CS
5394 /* Check old or new MAC detected as duplicate,
5395 * inherit duplicate flag to this neigh.
5396 */
5397 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf, old_mac,
5398 mac, n)) {
5399 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
5400 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5401 zvni->vni,
5402 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
5403 ipaddr2str(&n->ip, buf1, sizeof(buf1)));
5404 }
5405
7510e459
CS
5406 /* Check duplicate address detection for IP */
5407 zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n,
5408 n->r_vtep_ip,
5409 do_dad,
5410 &is_dup_detect,
5411 false);
f07e1c99 5412 /* Install the entry. */
e22a946a
CS
5413 if (!is_dup_detect)
5414 zvni_neigh_install(zvni, n);
f07e1c99 5415 }
5416
44bc8ae5
CS
5417 zvni_probe_neigh_on_mac_add(zvni, mac);
5418
f07e1c99 5419 /* Update seq number. */
5420 n->rem_seq = seq;
5421}
5422
5423/* Process a remote MACIP delete from BGP. */
5424static void process_remote_macip_del(vni_t vni,
5425 struct ethaddr *macaddr,
9df2b997 5426 uint16_t ipa_len,
f07e1c99 5427 struct ipaddr *ipaddr,
5428 struct in_addr vtep_ip)
5429{
5430 zebra_vni_t *zvni;
5431 zebra_mac_t *mac = NULL;
5432 zebra_neigh_t *n = NULL;
5433 struct interface *ifp = NULL;
5434 struct zebra_if *zif = NULL;
67fb9374
CS
5435 struct zebra_ns *zns;
5436 struct zebra_l2info_vxlan *vxl;
5437 struct zebra_vrf *zvrf;
f07e1c99 5438 char buf[ETHER_ADDR_STRLEN];
5439 char buf1[INET6_ADDRSTRLEN];
5440
5441 /* Locate VNI hash entry - expected to exist. */
5442 zvni = zvni_lookup(vni);
5443 if (!zvni) {
5444 if (IS_ZEBRA_DEBUG_VXLAN)
5445 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni);
5446 return;
5447 }
5448
5449 ifp = zvni->vxlan_if;
5450 if (ifp)
5451 zif = ifp->info;
5452 if (!ifp ||
5453 !if_is_operative(ifp) ||
5454 !zif ||
5455 !zif->brslave_info.br_if) {
5456 if (IS_ZEBRA_DEBUG_VXLAN)
5457 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5458 vni);
5459 return;
5460 }
67fb9374
CS
5461 zns = zebra_ns_lookup(NS_DEFAULT);
5462 vxl = &zif->l2info.vxl;
f07e1c99 5463
5464 /* The remote VTEP specified is normally expected to exist, but
5465 * it is possible that the peer may delete the VTEP before deleting
5466 * any MACs referring to the VTEP, in which case the handler (see
5467 * remote_vtep_del) would have already deleted the MACs.
5468 */
5469 if (!zvni_vtep_find(zvni, &vtep_ip))
5470 return;
5471
5472 mac = zvni_mac_lookup(zvni, macaddr);
5473 if (ipa_len)
5474 n = zvni_neigh_lookup(zvni, ipaddr);
5475
5476 if (n && !mac) {
5477 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5478 prefix_mac2str(macaddr, buf, sizeof(buf)),
5479 ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni);
5480 return;
5481 }
5482
5483 /* If the remote mac or neighbor doesn't exist there is nothing
5484 * more to do. Otherwise, uninstall the entry and then remove it.
5485 */
5486 if (!mac && !n)
5487 return;
5488
67fb9374
CS
5489 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
5490
f07e1c99 5491 /* Ignore the delete if this mac is a gateway mac-ip */
67fb9374 5492 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
f07e1c99 5493 && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
5494 zlog_warn(
5495 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5496 vni,
5497 prefix_mac2str(macaddr, buf, sizeof(buf)),
5498 ipa_len ? " IP " : "",
5499 ipa_len ?
5500 ipaddr2str(ipaddr, buf1, sizeof(buf1)) : "");
5501 return;
5502 }
5503
5504 /* Uninstall remote neighbor or MAC. */
5505 if (n) {
67fb9374
CS
5506 if (zvrf->dad_freeze &&
5507 CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) &&
5508 CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) &&
5509 (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
5510 struct interface *vlan_if;
5511
5512 vlan_if = zvni_map_to_svi(vxl->access_vlan,
5513 zif->brslave_info.br_if);
5514 if (IS_ZEBRA_DEBUG_VXLAN)
5515 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5516 __PRETTY_FUNCTION__,
5517 ipaddr2str(ipaddr, buf1,
5518 sizeof(buf1)), n->flags,
5519 vlan_if->name);
5520 neigh_read_specific_ip(ipaddr, vlan_if);
5521 }
5522
f07e1c99 5523 /* When the MAC changes for an IP, it is possible the
5524 * client may update the new MAC before trying to delete the
5525 * "old" neighbor (as these are two different MACIP routes).
5526 * Do the delete only if the MAC matches.
5527 */
5528 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5529 && (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
5530 zvni_neigh_uninstall(zvni, n);
5531 zvni_neigh_del(zvni, n);
fe697c6b 5532 zvni_deref_ip2mac(zvni, mac);
f07e1c99 5533 }
5534 } else {
67fb9374
CS
5535 /* DAD: when MAC is freeze state as remote learn event,
5536 * remote mac-ip delete event is received will result in freeze
5537 * entry removal, first fetch kernel for the same entry present
5538 * as LOCAL and reachable, avoid deleting this entry instead
5539 * use kerenel local entry to update during unfreeze time.
5540 */
5541 if (zvrf->dad_freeze &&
5542 CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) &&
5543 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5544 if (IS_ZEBRA_DEBUG_VXLAN)
5545 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5546 __PRETTY_FUNCTION__,
5547 prefix_mac2str(macaddr, buf,
5548 sizeof(buf)),
5549 mac->flags);
5550 macfdb_read_specific_mac(zns, zif->brslave_info.br_if,
5551 macaddr, vxl->access_vlan);
5552 }
5553
f07e1c99 5554 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5555 zvni_process_neigh_on_remote_mac_del(zvni, mac);
f3a930da
AK
5556 /*
5557 * the remote sequence number in the auto mac entry
5558 * needs to be reset to 0 as the mac entry may have
5559 * been removed on all VTEPs (including
5560 * the originating one)
5561 */
5562 mac->rem_seq = 0;
f07e1c99 5563
fe697c6b 5564 /* If all remote neighbors referencing a remote MAC
5565 * go away, we need to uninstall the MAC.
5566 */
5567 if (remote_neigh_count(mac) == 0) {
d63c1b18 5568 zvni_mac_uninstall(zvni, mac);
fe697c6b 5569 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5570 }
5571 if (list_isempty(mac->neigh_list))
f07e1c99 5572 zvni_mac_del(zvni, mac);
fe697c6b 5573 else
f07e1c99 5574 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5575 }
5576 }
5577}
5578
5579
b7cfce93
MK
5580/* Public functions */
5581
c48d9f5f
MK
5582int is_l3vni_for_prefix_routes_only(vni_t vni)
5583{
5584 zebra_l3vni_t *zl3vni = NULL;
5585
5586 zl3vni = zl3vni_lookup(vni);
5587 if (!zl3vni)
5588 return 0;
5589
5590 return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
5591}
5592
2dbad57f 5593/* handle evpn route in vrf table */
996c9314
LB
5594void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac,
5595 struct ipaddr *vtep_ip,
5596 struct prefix *host_prefix)
2dbad57f 5597{
5598 zebra_l3vni_t *zl3vni = NULL;
f50dc5e6 5599 struct ipaddr ipv4_vtep;
2dbad57f 5600
5601 zl3vni = zl3vni_from_vrf(vrf_id);
5602 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
5603 return;
5604
3518f352 5605 /*
f50dc5e6
MK
5606 * add the next hop neighbor -
5607 * neigh to be installed is the ipv6 nexthop neigh
5608 */
3518f352 5609 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
2dbad57f 5610
f50dc5e6
MK
5611 /*
5612 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5613 * address. Rmac is programmed against the ipv4 vtep because we only
5614 * support ipv4 tunnels in the h/w right now
5615 */
5616 memset(&ipv4_vtep, 0, sizeof(struct ipaddr));
5617 ipv4_vtep.ipa_type = IPADDR_V4;
5618 if (vtep_ip->ipa_type == IPADDR_V6)
5619 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
5620 &(ipv4_vtep.ipaddr_v4));
5621 else
5622 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
5623 sizeof(struct in_addr));
5624
3518f352
DS
5625 /*
5626 * add the rmac - remote rmac to be installed is against the ipv4
f50dc5e6
MK
5627 * nexthop address
5628 */
3518f352 5629 zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix);
2dbad57f 5630}
5631
5632/* handle evpn vrf route delete */
22e63104 5633void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
996c9314
LB
5634 struct ipaddr *vtep_ip,
5635 struct prefix *host_prefix)
2dbad57f 5636{
5637 zebra_l3vni_t *zl3vni = NULL;
22e63104 5638 zebra_neigh_t *nh = NULL;
5639 zebra_mac_t *zrmac = NULL;
2dbad57f 5640
5641 zl3vni = zl3vni_from_vrf(vrf_id);
5e06422c 5642 if (!zl3vni)
2dbad57f 5643 return;
5644
22e63104 5645 /* find the next hop entry and rmac entry */
5646 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
5647 if (!nh)
5648 return;
5649 zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
5650
2dbad57f 5651 /* delete the next hop entry */
22e63104 5652 zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
2dbad57f 5653
5654 /* delete the rmac entry */
22e63104 5655 if (zrmac)
5656 zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
5657
2dbad57f 5658}
5659
996c9314 5660void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
9f049418 5661 struct ethaddr *rmac, bool use_json)
9aa741ea
MK
5662{
5663 zebra_l3vni_t *zl3vni = NULL;
5664 zebra_mac_t *zrmac = NULL;
316f4ca4 5665 json_object *json = NULL;
9aa741ea 5666
316f4ca4
MK
5667 if (!is_evpn_enabled()) {
5668 if (use_json)
5669 vty_out(vty, "{}\n");
9aa741ea 5670 return;
316f4ca4
MK
5671 }
5672
5673 if (use_json)
5674 json = json_object_new_object();
9aa741ea
MK
5675
5676 zl3vni = zl3vni_lookup(l3vni);
5677 if (!zl3vni) {
316f4ca4
MK
5678 if (use_json)
5679 vty_out(vty, "{}\n");
5680 else
0437e105 5681 vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
9aa741ea
MK
5682 return;
5683 }
5684
5685 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
5686 if (!zrmac) {
316f4ca4
MK
5687 if (use_json)
5688 vty_out(vty, "{}\n");
5689 else
5690 vty_out(vty,
0437e105 5691 "%% Requested RMAC doesn't exist in L3-VNI %u",
316f4ca4 5692 l3vni);
9aa741ea
MK
5693 return;
5694 }
5695
316f4ca4
MK
5696 zl3vni_print_rmac(zrmac, vty, json);
5697
5698 if (use_json) {
5699 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5700 json, JSON_C_TO_STRING_PRETTY));
5701 json_object_free(json);
5702 }
9aa741ea 5703}
2dbad57f 5704
9f049418 5705void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
b7cfce93
MK
5706{
5707 zebra_l3vni_t *zl3vni;
d7c0a89a 5708 uint32_t num_rmacs;
b7cfce93
MK
5709 struct rmac_walk_ctx wctx;
5710 json_object *json = NULL;
b7cfce93
MK
5711
5712 if (!is_evpn_enabled())
5713 return;
5714
5715 zl3vni = zl3vni_lookup(l3vni);
5716 if (!zl3vni) {
5717 if (use_json)
5718 vty_out(vty, "{}\n");
5719 else
5720 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
5721 return;
5722 }
5723 num_rmacs = hashcount(zl3vni->rmac_table);
5724 if (!num_rmacs)
5725 return;
5726
75223c9e 5727 if (use_json)
b7cfce93 5728 json = json_object_new_object();
b7cfce93
MK
5729
5730 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
5731 wctx.vty = vty;
75223c9e 5732 wctx.json = json;
b7cfce93 5733 if (!use_json) {
996c9314 5734 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
b7cfce93 5735 num_rmacs);
4cce389e 5736 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
b7cfce93
MK
5737 } else
5738 json_object_int_add(json, "numRmacs", num_rmacs);
5739
5740 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
5741
5742 if (use_json) {
b7cfce93
MK
5743 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5744 json, JSON_C_TO_STRING_PRETTY));
5745 json_object_free(json);
5746 }
5747}
5748
9f049418 5749void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
b7cfce93 5750{
b7cfce93 5751 json_object *json = NULL;
c0b4eaa4 5752 void *args[2];
b7cfce93
MK
5753
5754 if (!is_evpn_enabled()) {
5755 if (use_json)
5756 vty_out(vty, "{}\n");
5757 return;
5758 }
5759
b7cfce93
MK
5760 if (use_json)
5761 json = json_object_new_object();
5762
c0b4eaa4
MK
5763 args[0] = vty;
5764 args[1] = json;
89272910 5765 hash_iterate(zrouter.l3vni_table,
e3b78da8 5766 (void (*)(struct hash_bucket *,
c0b4eaa4
MK
5767 void *))zl3vni_print_rmac_hash_all_vni,
5768 args);
b7cfce93
MK
5769
5770 if (use_json) {
5771 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5772 json, JSON_C_TO_STRING_PRETTY));
5773 json_object_free(json);
5774 }
5775}
5776
996c9314 5777void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
9f049418 5778 struct ipaddr *ip, bool use_json)
9aa741ea
MK
5779{
5780 zebra_l3vni_t *zl3vni = NULL;
5781 zebra_neigh_t *n = NULL;
c0e519d3 5782 json_object *json = NULL;
9aa741ea 5783
c0e519d3
MK
5784 if (!is_evpn_enabled()) {
5785 if (use_json)
5786 vty_out(vty, "{}\n");
9aa741ea 5787 return;
c0e519d3
MK
5788 }
5789
5790 if (use_json)
5791 json = json_object_new_object();
9aa741ea
MK
5792
5793 zl3vni = zl3vni_lookup(l3vni);
5794 if (!zl3vni) {
c0e519d3
MK
5795 if (use_json)
5796 vty_out(vty, "{}\n");
5797 else
5798 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
9aa741ea
MK
5799 return;
5800 }
5801
5802 n = zl3vni_nh_lookup(zl3vni, ip);
5803 if (!n) {
c0e519d3
MK
5804 if (use_json)
5805 vty_out(vty, "{}\n");
5806 else
5807 vty_out(vty,
5808 "%% Requested next-hop not present for L3-VNI %u",
5809 l3vni);
9aa741ea
MK
5810 return;
5811 }
5812
c0e519d3
MK
5813 zl3vni_print_nh(n, vty, json);
5814
5815 if (use_json) {
5816 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5817 json, JSON_C_TO_STRING_PRETTY));
5818 json_object_free(json);
5819 }
9aa741ea
MK
5820}
5821
9f049418 5822void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
b7cfce93 5823{
d7c0a89a 5824 uint32_t num_nh;
2dbad57f 5825 struct nh_walk_ctx wctx;
b7cfce93 5826 json_object *json = NULL;
b7cfce93
MK
5827 zebra_l3vni_t *zl3vni = NULL;
5828
5829 if (!is_evpn_enabled())
5830 return;
5831
5832 zl3vni = zl3vni_lookup(l3vni);
5833 if (!zl3vni) {
5834 if (use_json)
5835 vty_out(vty, "{}\n");
5836 else
5837 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
5838 return;
5839 }
5840
5841 num_nh = hashcount(zl3vni->nh_table);
5842 if (!num_nh)
5843 return;
5844
9187f600 5845 if (use_json)
b7cfce93 5846 json = json_object_new_object();
b7cfce93 5847
2dbad57f 5848 wctx.vty = vty;
9187f600 5849 wctx.json = json;
b7cfce93 5850 if (!use_json) {
996c9314 5851 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
b7cfce93 5852 num_nh);
4cce389e 5853 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
b7cfce93 5854 } else
4cce389e 5855 json_object_int_add(json, "numNextHops", num_nh);
b7cfce93
MK
5856
5857 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
5858
5859 if (use_json) {
b7cfce93
MK
5860 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5861 json, JSON_C_TO_STRING_PRETTY));
5862 json_object_free(json);
5863 }
5864}
5865
9f049418 5866void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
b7cfce93 5867{
2dbad57f 5868 json_object *json = NULL;
32798965 5869 void *args[2];
2dbad57f 5870
5871 if (!is_evpn_enabled()) {
5872 if (use_json)
5873 vty_out(vty, "{}\n");
5874 return;
5875 }
5876
2dbad57f 5877 if (use_json)
5878 json = json_object_new_object();
5879
32798965
MK
5880 args[0] = vty;
5881 args[1] = json;
89272910 5882 hash_iterate(zrouter.l3vni_table,
e3b78da8 5883 (void (*)(struct hash_bucket *,
32798965
MK
5884 void *))zl3vni_print_nh_hash_all_vni,
5885 args);
2dbad57f 5886
5887 if (use_json) {
5888 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5889 json, JSON_C_TO_STRING_PRETTY));
5890 json_object_free(json);
5891 }
b7cfce93
MK
5892}
5893
5894/*
5895 * Display L3 VNI information (VTY command handler).
5896 */
9f049418 5897void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
b7cfce93
MK
5898{
5899 void *args[2];
5900 json_object *json = NULL;
5901 zebra_l3vni_t *zl3vni = NULL;
5902
b2ee5a13
MK
5903 if (!is_evpn_enabled()) {
5904 if (use_json)
5905 vty_out(vty, "{}\n");
b7cfce93 5906 return;
b2ee5a13 5907 }
b7cfce93
MK
5908
5909 zl3vni = zl3vni_lookup(vni);
5910 if (!zl3vni) {
5911 if (use_json)
5912 vty_out(vty, "{}\n");
5913 else
5914 vty_out(vty, "%% VNI %u does not exist\n", vni);
5915 return;
5916 }
5917
5918 if (use_json)
5919 json = json_object_new_object();
5920
b2ee5a13
MK
5921 args[0] = vty;
5922 args[1] = json;
b7cfce93
MK
5923 zl3vni_print(zl3vni, (void *)args);
5924
5925 if (use_json) {
5926 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5927 json, JSON_C_TO_STRING_PRETTY));
5928 json_object_free(json);
5929 }
5930}
5931
4cce389e
MK
5932void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
5933 json_object *json_vrfs)
b7cfce93 5934{
4cce389e
MK
5935 char buf[ETHER_ADDR_STRLEN];
5936 zebra_l3vni_t *zl3vni = NULL;
b7cfce93 5937
4cce389e
MK
5938 zl3vni = zl3vni_lookup(zvrf->l3vni);
5939 if (!zl3vni)
b7cfce93 5940 return;
b7cfce93 5941
4cce389e
MK
5942 if (!json_vrfs) {
5943 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
996c9314 5944 zvrf_name(zvrf), zl3vni->vni,
4cce389e 5945 zl3vni_vxlan_if_name(zl3vni),
996c9314 5946 zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
4cce389e 5947 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
b7cfce93 5948 } else {
4cce389e 5949 json_object *json_vrf = NULL;
9df2b997 5950
4cce389e 5951 json_vrf = json_object_new_object();
996c9314 5952 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
4cce389e
MK
5953 json_object_int_add(json_vrf, "vni", zl3vni->vni);
5954 json_object_string_add(json_vrf, "vxlanIntf",
5955 zl3vni_vxlan_if_name(zl3vni));
5956 json_object_string_add(json_vrf, "sviIntf",
5957 zl3vni_svi_if_name(zl3vni));
5958 json_object_string_add(json_vrf, "state",
5959 zl3vni_state2str(zl3vni));
996c9314
LB
5960 json_object_string_add(
5961 json_vrf, "routerMac",
5962 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 5963 json_object_array_add(json_vrfs, json_vrf);
b7cfce93
MK
5964 }
5965}
5966
5967/*
5968 * Display Neighbors for a VNI (VTY command handler).
5969 */
5970void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 5971 vni_t vni, bool use_json)
b7cfce93
MK
5972{
5973 zebra_vni_t *zvni;
d7c0a89a 5974 uint32_t num_neigh;
b7cfce93
MK
5975 struct neigh_walk_ctx wctx;
5976 json_object *json = NULL;
5977
5978 if (!is_evpn_enabled())
5979 return;
5980 zvni = zvni_lookup(vni);
5981 if (!zvni) {
5982 if (use_json)
5983 vty_out(vty, "{}\n");
5984 else
5985 vty_out(vty, "%% VNI %u does not exist\n", vni);
5986 return;
5987 }
5988 num_neigh = hashcount(zvni->neigh_table);
5989 if (!num_neigh)
5990 return;
5991
5992 if (use_json)
5993 json = json_object_new_object();
5994
5995 /* Since we have IPv6 addresses to deal with which can vary widely in
5996 * size, we try to be a bit more elegant in display by first computing
5997 * the maximum width.
5998 */
5999 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
6000 wctx.zvni = zvni;
6001 wctx.vty = vty;
6002 wctx.addr_width = 15;
6003 wctx.json = json;
6004 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
6005
6006 if (!use_json) {
6007 vty_out(vty,
6008 "Number of ARPs (local and remote) known for this VNI: %u\n",
6009 num_neigh);
1a8c5c38 6010 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
6011 -wctx.addr_width, "IP", "Type",
6012 "State", "MAC", "Remote VTEP");
b7cfce93
MK
6013 } else
6014 json_object_int_add(json, "numArpNd", num_neigh);
6015
6016 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
6017 if (use_json) {
6018 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6019 json, JSON_C_TO_STRING_PRETTY));
6020 json_object_free(json);
6021 }
6022}
6023
6024/*
6025 * Display neighbors across all VNIs (VTY command handler).
6026 */
6027void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
1374d4db 6028 bool print_dup, bool use_json)
b7cfce93
MK
6029{
6030 json_object *json = NULL;
1374d4db 6031 void *args[3];
b7cfce93
MK
6032
6033 if (!is_evpn_enabled())
6034 return;
6035
6036 if (use_json)
6037 json = json_object_new_object();
6038
6039 args[0] = vty;
6040 args[1] = json;
1374d4db
CS
6041 args[2] = (void *)(ptrdiff_t)print_dup;
6042
b7cfce93 6043 hash_iterate(zvrf->vni_table,
e3b78da8 6044 (void (*)(struct hash_bucket *,
b7cfce93
MK
6045 void *))zvni_print_neigh_hash_all_vni,
6046 args);
6047 if (use_json) {
6048 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6049 json, JSON_C_TO_STRING_PRETTY));
6050 json_object_free(json);
6051 }
6052}
6053
e3fac919
NS
6054/*
6055 * Display neighbors across all VNIs in detail(VTY command handler).
6056 */
6057void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
6058 struct zebra_vrf *zvrf,
6059 bool print_dup, bool use_json)
6060{
6061 json_object *json = NULL;
6062 void *args[3];
6063
6064 if (!is_evpn_enabled())
6065 return;
6066
6067 if (use_json)
6068 json = json_object_new_object();
6069
6070 args[0] = vty;
6071 args[1] = json;
6072 args[2] = (void *)(ptrdiff_t)print_dup;
6073
6074 hash_iterate(zvrf->vni_table,
e3b78da8 6075 (void (*)(struct hash_bucket *,
e3fac919
NS
6076 void *))zvni_print_neigh_hash_all_vni_detail,
6077 args);
6078 if (use_json) {
6079 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6080 json, JSON_C_TO_STRING_PRETTY));
6081 json_object_free(json);
6082 }
6083}
6084
b7cfce93
MK
6085/*
6086 * Display specific neighbor for a VNI, if present (VTY command handler).
6087 */
6088void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
6089 struct zebra_vrf *zvrf, vni_t vni,
9f049418 6090 struct ipaddr *ip, bool use_json)
b7cfce93
MK
6091{
6092 zebra_vni_t *zvni;
6093 zebra_neigh_t *n;
6094 json_object *json = NULL;
6095
6096 if (!is_evpn_enabled())
6097 return;
6098 zvni = zvni_lookup(vni);
6099 if (!zvni) {
6100 if (use_json)
cd233079
CS
6101 vty_out(vty, "{}\n");
6102 else
6103 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 6104 return;
6105 }
6106 n = zvni_neigh_lookup(zvni, ip);
6107 if (!n) {
cd233079
CS
6108 if (!use_json)
6109 vty_out(vty,
6110 "%% Requested neighbor does not exist in VNI %u\n",
6111 vni);
d62a17ae 6112 return;
6113 }
cd233079
CS
6114 if (use_json)
6115 json = json_object_new_object();
6116
6117 zvni_print_neigh(n, vty, json);
cec2e17d 6118
cd233079
CS
6119 if (use_json) {
6120 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6121 json, JSON_C_TO_STRING_PRETTY));
6122 json_object_free(json);
6123 }
cec2e17d 6124}
6125
6126/*
6127 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6128 * By definition, these are remote neighbors.
6129 */
d62a17ae 6130void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 6131 vni_t vni, struct in_addr vtep_ip,
9f049418 6132 bool use_json)
cec2e17d 6133{
d62a17ae 6134 zebra_vni_t *zvni;
d7c0a89a 6135 uint32_t num_neigh;
d62a17ae 6136 struct neigh_walk_ctx wctx;
cd233079 6137 json_object *json = NULL;
cec2e17d 6138
2853fed6 6139 if (!is_evpn_enabled())
d62a17ae 6140 return;
2853fed6 6141 zvni = zvni_lookup(vni);
d62a17ae 6142 if (!zvni) {
cd233079
CS
6143 if (use_json)
6144 vty_out(vty, "{}\n");
6145 else
6146 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 6147 return;
6148 }
6149 num_neigh = hashcount(zvni->neigh_table);
6150 if (!num_neigh)
6151 return;
cec2e17d 6152
d62a17ae 6153 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
6154 wctx.zvni = zvni;
6155 wctx.vty = vty;
68e33151 6156 wctx.addr_width = 15;
d62a17ae 6157 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
6158 wctx.r_vtep_ip = vtep_ip;
cd233079 6159 wctx.json = json;
68e33151 6160 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
d62a17ae 6161 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
6162
6163 if (use_json) {
6164 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6165 json, JSON_C_TO_STRING_PRETTY));
6166 json_object_free(json);
6167 }
cec2e17d 6168}
6169
1374d4db
CS
6170/*
6171 * Display Duplicate detected Neighbors for a VNI
6172 * (VTY command handler).
6173 */
6174void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
6175 struct zebra_vrf *zvrf,
6176 vni_t vni,
6177 bool use_json)
6178{
6179 zebra_vni_t *zvni;
6180 uint32_t num_neigh;
6181 struct neigh_walk_ctx wctx;
6182 json_object *json = NULL;
6183
6184 if (!is_evpn_enabled())
6185 return;
6186
6187 zvni = zvni_lookup(vni);
6188 if (!zvni) {
6189 vty_out(vty, "%% VNI %u does not exist\n", vni);
6190 return;
6191 }
6192
6193 num_neigh = hashcount(zvni->neigh_table);
6194 if (!num_neigh)
6195 return;
6196
6197 num_neigh = num_dup_detected_neighs(zvni);
6198 if (!num_neigh)
6199 return;
6200
6201 if (use_json)
6202 json = json_object_new_object();
6203
6204 /* Since we have IPv6 addresses to deal with which can vary widely in
6205 * size, we try to be a bit more elegant in display by first computing
6206 * the maximum width.
6207 */
6208 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
6209 wctx.zvni = zvni;
6210 wctx.vty = vty;
6211 wctx.addr_width = 15;
6212 wctx.json = json;
6213 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
6214
6215 if (!use_json) {
6216 vty_out(vty,
6217 "Number of ARPs (local and remote) known for this VNI: %u\n",
6218 num_neigh);
6219 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
6220 -wctx.addr_width, "IP", "Type",
6221 "State", "MAC", "Remote VTEP");
6222 } else
6223 json_object_int_add(json, "numArpNd", num_neigh);
6224
6225 hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash, &wctx);
6226
6227 if (use_json) {
6228 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6229 json, JSON_C_TO_STRING_PRETTY));
6230 json_object_free(json);
6231 }
6232}
6233
cec2e17d 6234/*
6235 * Display MACs for a VNI (VTY command handler).
6236 */
d62a17ae 6237void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 6238 vni_t vni, bool use_json)
cec2e17d 6239{
d62a17ae 6240 zebra_vni_t *zvni;
d7c0a89a 6241 uint32_t num_macs;
d62a17ae 6242 struct mac_walk_ctx wctx;
cd233079
CS
6243 json_object *json = NULL;
6244 json_object *json_mac = NULL;
cec2e17d 6245
2853fed6 6246 if (!is_evpn_enabled())
d62a17ae 6247 return;
2853fed6 6248 zvni = zvni_lookup(vni);
d62a17ae 6249 if (!zvni) {
cd233079
CS
6250 if (use_json)
6251 vty_out(vty, "{}\n");
6252 else
6253 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 6254 return;
6255 }
790f8dc5 6256 num_macs = num_valid_macs(zvni);
d62a17ae 6257 if (!num_macs)
6258 return;
cec2e17d 6259
cd233079
CS
6260 if (use_json) {
6261 json = json_object_new_object();
6262 json_mac = json_object_new_object();
6263 }
6264
d62a17ae 6265 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6266 wctx.zvni = zvni;
6267 wctx.vty = vty;
cd233079 6268 wctx.json = json_mac;
cec2e17d 6269
cd233079
CS
6270 if (!use_json) {
6271 vty_out(vty,
6272 "Number of MACs (local and remote) known for this VNI: %u\n",
6273 num_macs);
6274 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6275 "Intf/Remote VTEP", "VLAN");
6276 } else
6277 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 6278
d62a17ae 6279 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
6280
6281 if (use_json) {
6282 json_object_object_add(json, "macs", json_mac);
6283 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6284 json, JSON_C_TO_STRING_PRETTY));
6285 json_object_free(json);
6286 }
cec2e17d 6287}
6288
6289/*
6290 * Display MACs for all VNIs (VTY command handler).
6291 */
cd233079 6292void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
1374d4db 6293 bool print_dup, bool use_json)
cec2e17d 6294{
d62a17ae 6295 struct mac_walk_ctx wctx;
cd233079 6296 json_object *json = NULL;
cec2e17d 6297
2853fed6 6298 if (!is_evpn_enabled()) {
cd233079
CS
6299 if (use_json)
6300 vty_out(vty, "{}\n");
d62a17ae 6301 return;
cd233079
CS
6302 }
6303 if (use_json)
6304 json = json_object_new_object();
6305
d62a17ae 6306 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6307 wctx.vty = vty;
cd233079 6308 wctx.json = json;
1374d4db 6309 wctx.print_dup = print_dup;
d62a17ae 6310 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
6311
6312 if (use_json) {
6313 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6314 json, JSON_C_TO_STRING_PRETTY));
6315 json_object_free(json);
6316 }
cec2e17d 6317}
6318
cffe7580
NS
6319/*
6320 * Display MACs in detail for all VNIs (VTY command handler).
6321 */
6322void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
6323 struct zebra_vrf *zvrf,
6324 bool print_dup, bool use_json)
6325{
6326 struct mac_walk_ctx wctx;
6327 json_object *json = NULL;
6328
6329 if (!is_evpn_enabled()) {
6330 if (use_json)
6331 vty_out(vty, "{}\n");
6332 return;
6333 }
6334 if (use_json)
6335 json = json_object_new_object();
6336
6337 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6338 wctx.vty = vty;
6339 wctx.json = json;
6340 wctx.print_dup = print_dup;
6341 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni_detail,
6342 &wctx);
6343
6344 if (use_json) {
6345 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6346 json, JSON_C_TO_STRING_PRETTY));
6347 json_object_free(json);
6348 }
6349}
6350
cec2e17d 6351/*
6352 * Display MACs for all VNIs (VTY command handler).
6353 */
d62a17ae 6354void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
6355 struct zebra_vrf *zvrf,
9f049418 6356 struct in_addr vtep_ip, bool use_json)
cec2e17d 6357{
d62a17ae 6358 struct mac_walk_ctx wctx;
cd233079 6359 json_object *json = NULL;
cec2e17d 6360
2853fed6 6361 if (!is_evpn_enabled())
d62a17ae 6362 return;
cd233079
CS
6363
6364 if (use_json)
6365 json = json_object_new_object();
6366
d62a17ae 6367 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6368 wctx.vty = vty;
6369 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
6370 wctx.r_vtep_ip = vtep_ip;
cd233079 6371 wctx.json = json;
d62a17ae 6372 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
6373
6374 if (use_json) {
6375 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6376 json, JSON_C_TO_STRING_PRETTY));
6377 json_object_free(json);
6378 }
cec2e17d 6379}
6380
6381/*
6382 * Display specific MAC for a VNI, if present (VTY command handler).
6383 */
d62a17ae 6384void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
24cdbd0d
DS
6385 vni_t vni, struct ethaddr *macaddr,
6386 bool use_json)
cec2e17d 6387{
d62a17ae 6388 zebra_vni_t *zvni;
6389 zebra_mac_t *mac;
24cdbd0d 6390 json_object *json = NULL;
cec2e17d 6391
2853fed6 6392 if (!is_evpn_enabled())
d62a17ae 6393 return;
24cdbd0d 6394
2853fed6 6395 zvni = zvni_lookup(vni);
d62a17ae 6396 if (!zvni) {
24cdbd0d
DS
6397 if (use_json)
6398 vty_out(vty, "{}\n");
6399 else
6400 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 6401 return;
6402 }
6403 mac = zvni_mac_lookup(zvni, macaddr);
6404 if (!mac) {
24cdbd0d
DS
6405 if (use_json)
6406 vty_out(vty, "{}\n");
6407 else
6408 vty_out(vty,
6409 "%% Requested MAC does not exist in VNI %u\n",
6410 vni);
d62a17ae 6411 return;
6412 }
cec2e17d 6413
24cdbd0d
DS
6414 if (use_json)
6415 json = json_object_new_object();
6416
6417 zvni_print_mac(mac, vty, json);
cffe7580
NS
6418 if (use_json) {
6419 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6420 json, JSON_C_TO_STRING_PRETTY));
6421 json_object_free(json);
6422 }
cec2e17d 6423}
6424
1374d4db
CS
6425/* Print Duplicate MACs per VNI */
6426void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
6427 struct zebra_vrf *zvrf,
6428 vni_t vni, bool use_json)
6429{
6430 zebra_vni_t *zvni;
6431 struct mac_walk_ctx wctx;
6432 uint32_t num_macs;
6433 json_object *json = NULL;
6434 json_object *json_mac = NULL;
6435
6436 if (!is_evpn_enabled())
6437 return;
6438
6439 zvni = zvni_lookup(vni);
6440 if (!zvni) {
6441 vty_out(vty, "%% VNI %u does not exist\n", vni);
6442 return;
6443 }
6444
6445 num_macs = num_valid_macs(zvni);
6446 if (!num_macs)
6447 return;
6448
6449 num_macs = num_dup_detected_macs(zvni);
6450 if (!num_macs)
6451 return;
6452
6453 if (use_json) {
6454 json = json_object_new_object();
6455 json_mac = json_object_new_object();
6456 }
6457
6458 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6459 wctx.zvni = zvni;
6460 wctx.vty = vty;
6461 wctx.json = json_mac;
6462
6463 if (!use_json) {
6464 vty_out(vty,
6465 "Number of MACs (local and remote) known for this VNI: %u\n",
6466 num_macs);
6467 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6468 "Intf/Remote VTEP", "VLAN");
6469 } else
6470 json_object_int_add(json, "numMacs", num_macs);
6471
6472 hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, &wctx);
6473
6474 if (use_json) {
6475 json_object_object_add(json, "macs", json_mac);
6476 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6477 json, JSON_C_TO_STRING_PRETTY));
6478 json_object_free(json);
6479 }
6480
6481}
6482
1883de66
CS
6483int zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
6484 struct zebra_vrf *zvrf,
6485 vni_t vni, struct ethaddr *macaddr)
09de9258
CS
6486{
6487 zebra_vni_t *zvni;
6488 zebra_mac_t *mac;
6489 struct listnode *node = NULL;
6490 zebra_neigh_t *nbr = NULL;
6491
6492 if (!is_evpn_enabled())
1883de66
CS
6493 return CMD_SUCCESS;
6494
09de9258
CS
6495 zvni = zvni_lookup(vni);
6496 if (!zvni) {
6497 vty_out(vty, "%% VNI %u does not exist\n", vni);
1883de66 6498 return CMD_WARNING;
09de9258
CS
6499 }
6500
6501 mac = zvni_mac_lookup(zvni, macaddr);
6502 if (!mac) {
6503 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
6504 vni);
1883de66 6505 return CMD_WARNING;
09de9258
CS
6506 }
6507
6508 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
6509 vty_out(vty, "%% Requested MAC is not duplicate detected\n");
1883de66 6510 return CMD_WARNING;
09de9258
CS
6511 }
6512
6513 /* Remove all IPs as duplicate associcated with this MAC */
6514 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
6515 /* For local neigh mark inactive so MACIP update is generated
6516 * to BGP. This is a scenario where MAC update received
6517 * and detected as duplicate which marked neigh as duplicate.
6518 * Later local neigh update did not get a chance to relay
6519 * to BGP. Similarly remote macip update, neigh needs to be
6520 * installed locally.
6521 */
d4199657
CS
6522 if (zvrf->dad_freeze &&
6523 CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
09de9258
CS
6524 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
6525 ZEBRA_NEIGH_SET_INACTIVE(nbr);
6526 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
6527 zvni_neigh_install(zvni, nbr);
6528 }
6529
6530 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6531 nbr->dad_count = 0;
6532 nbr->detect_start_time.tv_sec = 0;
6533 nbr->dad_dup_detect_time = 0;
6534 }
6535
6536 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
6537 mac->dad_count = 0;
6538 mac->detect_start_time.tv_sec = 0;
6539 mac->detect_start_time.tv_usec = 0;
6540 mac->dad_dup_detect_time = 0;
6541 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
6542
d4199657
CS
6543 /* warn-only action return */
6544 if (!zvrf->dad_freeze)
6545 return CMD_SUCCESS;
6546
09de9258
CS
6547 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6548 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
6549 /* Inform to BGP */
6550 if (zvni_mac_send_add_to_client(zvni->vni,
6551 &mac->macaddr,
6552 mac->flags,
6553 mac->loc_seq))
1883de66 6554 return CMD_SUCCESS;
09de9258
CS
6555
6556 /* Process all neighbors associated with this MAC. */
6557 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
6558
6559 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
6560 zvni_process_neigh_on_remote_mac_add(zvni, mac);
6561
6562 /* Install the entry. */
6563 zvni_mac_install(zvni, mac);
6564 }
6565
1883de66 6566 return CMD_SUCCESS;
09de9258
CS
6567}
6568
1883de66
CS
6569int zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
6570 struct zebra_vrf *zvrf,
6571 vni_t vni, struct ipaddr *ip)
09de9258
CS
6572{
6573 zebra_vni_t *zvni;
6574 zebra_neigh_t *nbr;
6575 zebra_mac_t *mac;
6576 char buf[INET6_ADDRSTRLEN];
6577 char buf2[ETHER_ADDR_STRLEN];
6578
6579 if (!is_evpn_enabled())
1883de66 6580 return CMD_SUCCESS;
09de9258
CS
6581
6582 zvni = zvni_lookup(vni);
6583 if (!zvni) {
6584 vty_out(vty, "%% VNI %u does not exist\n", vni);
1883de66 6585 return CMD_WARNING;
09de9258
CS
6586 }
6587
6588 nbr = zvni_neigh_lookup(zvni, ip);
6589 if (!nbr) {
6590 vty_out(vty,
6591 "%% Requested host IP does not exist in VNI %u\n",
6592 vni);
1883de66 6593 return CMD_WARNING;
09de9258
CS
6594 }
6595
6596 ipaddr2str(&nbr->ip, buf, sizeof(buf));
6597
6598 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
6599 vty_out(vty,
6600 "%% Requsted host IP %s is not duplicate detected\n",
6601 buf);
1883de66 6602 return CMD_WARNING;
09de9258
CS
6603 }
6604
6605 mac = zvni_mac_lookup(zvni, &nbr->emac);
6606
6607 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
6608 vty_out(vty,
6609 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6610 prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
1883de66 6611 return CMD_WARNING_CONFIG_FAILED;
09de9258
CS
6612 }
6613
6614 if (IS_ZEBRA_DEBUG_VXLAN)
6615 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6616 __PRETTY_FUNCTION__, buf, nbr->flags,
6617 nbr->loc_seq);
6618
6619 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6620 nbr->dad_count = 0;
6621 nbr->detect_start_time.tv_sec = 0;
6622 nbr->detect_start_time.tv_usec = 0;
6623 nbr->dad_dup_detect_time = 0;
6624 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
6625
6626 if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
6627 zvni_neigh_send_add_to_client(zvni->vni, ip,
6628 &nbr->emac,
6629 nbr->flags, nbr->loc_seq);
6630 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
6631 zvni_neigh_install(zvni, nbr);
6632 }
6633
1883de66 6634 return CMD_SUCCESS;
09de9258
CS
6635}
6636
e3b78da8 6637static void zvni_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt)
09de9258
CS
6638{
6639 struct mac_walk_ctx *wctx = ctxt;
6640 zebra_mac_t *mac;
6641 zebra_vni_t *zvni;
6642 struct listnode *node = NULL;
6643 zebra_neigh_t *nbr = NULL;
6644
e3b78da8 6645 mac = (zebra_mac_t *)bucket->data;
09de9258
CS
6646 if (!mac)
6647 return;
6648
6649 zvni = wctx->zvni;
6650
6651 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
6652 return;
6653
6654 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
6655 mac->dad_count = 0;
6656 mac->detect_start_time.tv_sec = 0;
6657 mac->detect_start_time.tv_usec = 0;
6658 mac->dad_dup_detect_time = 0;
6659 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
6660
6661 /* Remove all IPs as duplicate associcated with this MAC */
6662 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
6663 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)
6664 && nbr->dad_count)
6665 ZEBRA_NEIGH_SET_INACTIVE(nbr);
6666
6667 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6668 nbr->dad_count = 0;
6669 nbr->detect_start_time.tv_sec = 0;
6670 nbr->dad_dup_detect_time = 0;
6671 }
6672
6673 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6674 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
6675 /* Inform to BGP */
6676 if (zvni_mac_send_add_to_client(zvni->vni,
6677 &mac->macaddr,
6678 mac->flags, mac->loc_seq))
6679 return;
6680
6681 /* Process all neighbors associated with this MAC. */
6682 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
6683
6684 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
6685 zvni_process_neigh_on_remote_mac_add(zvni, mac);
6686
6687 /* Install the entry. */
6688 zvni_mac_install(zvni, mac);
6689 }
6690}
6691
e3b78da8 6692static void zvni_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt)
09de9258
CS
6693{
6694 struct neigh_walk_ctx *wctx = ctxt;
6695 zebra_neigh_t *nbr;
6696 zebra_vni_t *zvni;
6697 char buf[INET6_ADDRSTRLEN];
6698
e3b78da8 6699 nbr = (zebra_neigh_t *)bucket->data;
09de9258
CS
6700 if (!nbr)
6701 return;
6702
6703 zvni = wctx->zvni;
6704
6705 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
6706 return;
6707
6708 if (IS_ZEBRA_DEBUG_VXLAN) {
6709 ipaddr2str(&nbr->ip, buf, sizeof(buf));
6710 zlog_debug(
6711 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6712 __PRETTY_FUNCTION__, buf,
6713 nbr->flags, nbr->loc_seq);
6714 }
6715
6716 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6717 nbr->dad_count = 0;
6718 nbr->detect_start_time.tv_sec = 0;
6719 nbr->detect_start_time.tv_usec = 0;
6720 nbr->dad_dup_detect_time = 0;
6721 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
6722
6723 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
6724 zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip,
6725 &nbr->emac,
6726 nbr->flags, nbr->loc_seq);
6727 } else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
6728 zvni_neigh_install(zvni, nbr);
6729 }
6730}
6731
e3b78da8 6732static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket,
09de9258
CS
6733 void **args)
6734{
6735 struct vty *vty;
6736 zebra_vni_t *zvni;
6737 struct zebra_vrf *zvrf;
6738 struct mac_walk_ctx m_wctx;
6739 struct neigh_walk_ctx n_wctx;
6740
e3b78da8 6741 zvni = (zebra_vni_t *)bucket->data;
09de9258
CS
6742 if (!zvni)
6743 return;
6744
6745 vty = (struct vty *)args[0];
6746 zvrf = (struct zebra_vrf *)args[1];
6747
6748 if (hashcount(zvni->neigh_table)) {
6749 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6750 n_wctx.vty = vty;
6751 n_wctx.zvni = zvni;
6752 n_wctx.zvrf = zvrf;
6753 hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash,
6754 &n_wctx);
6755 }
6756
6757 if (num_valid_macs(zvni)) {
6758 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6759 m_wctx.zvni = zvni;
6760 m_wctx.vty = vty;
6761 m_wctx.zvrf = zvrf;
6762 hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
6763 }
6764
6765}
6766
1883de66 6767int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
09de9258
CS
6768 struct zebra_vrf *zvrf)
6769{
6770 void *args[2];
6771
6772 if (!is_evpn_enabled())
1883de66 6773 return CMD_SUCCESS;
09de9258
CS
6774
6775 args[0] = vty;
6776 args[1] = zvrf;
6777
6778 hash_iterate(zvrf->vni_table,
e3b78da8 6779 (void (*)(struct hash_bucket *, void *))
09de9258
CS
6780 zvni_clear_dup_detect_hash_vni_all, args);
6781
1883de66 6782 return CMD_SUCCESS;
09de9258
CS
6783}
6784
1883de66 6785int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
09de9258
CS
6786 struct zebra_vrf *zvrf,
6787 vni_t vni)
6788{
6789 zebra_vni_t *zvni;
6790 struct mac_walk_ctx m_wctx;
6791 struct neigh_walk_ctx n_wctx;
6792
6793 if (!is_evpn_enabled())
1883de66 6794 return CMD_SUCCESS;
09de9258
CS
6795
6796 zvni = zvni_lookup(vni);
6797 if (!zvni) {
6798 vty_out(vty, "%% VNI %u does not exist\n", vni);
1883de66 6799 return CMD_WARNING;
09de9258
CS
6800 }
6801
6802 if (hashcount(zvni->neigh_table)) {
6803 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6804 n_wctx.vty = vty;
6805 n_wctx.zvni = zvni;
6806 n_wctx.zvrf = zvrf;
6807 hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash,
6808 &n_wctx);
6809 }
6810
6811 if (num_valid_macs(zvni)) {
6812 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6813 m_wctx.zvni = zvni;
6814 m_wctx.vty = vty;
6815 m_wctx.zvrf = zvrf;
6816 hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
6817 }
6818
1883de66 6819 return CMD_SUCCESS;
09de9258
CS
6820}
6821
cec2e17d 6822/*
6823 * Display MACs for a VNI from specific VTEP (VTY command handler).
6824 */
d62a17ae 6825void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 6826 vni_t vni, struct in_addr vtep_ip,
9f049418 6827 bool use_json)
cec2e17d 6828{
d62a17ae 6829 zebra_vni_t *zvni;
d7c0a89a 6830 uint32_t num_macs;
d62a17ae 6831 struct mac_walk_ctx wctx;
cd233079
CS
6832 json_object *json = NULL;
6833 json_object *json_mac = NULL;
cec2e17d 6834
2853fed6 6835 if (!is_evpn_enabled())
d62a17ae 6836 return;
2853fed6 6837 zvni = zvni_lookup(vni);
d62a17ae 6838 if (!zvni) {
cd233079
CS
6839 if (use_json)
6840 vty_out(vty, "{}\n");
6841 else
6842 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 6843 return;
6844 }
790f8dc5 6845 num_macs = num_valid_macs(zvni);
d62a17ae 6846 if (!num_macs)
6847 return;
cd233079
CS
6848
6849 if (use_json) {
6850 json = json_object_new_object();
6851 json_mac = json_object_new_object();
6852 }
6853
d62a17ae 6854 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6855 wctx.zvni = zvni;
6856 wctx.vty = vty;
6857 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
6858 wctx.r_vtep_ip = vtep_ip;
cd233079 6859 wctx.json = json_mac;
d62a17ae 6860 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
6861
6862 if (use_json) {
6863 json_object_int_add(json, "numMacs", wctx.count);
6864 if (wctx.count)
6865 json_object_object_add(json, "macs", json_mac);
6866 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6867 json, JSON_C_TO_STRING_PRETTY));
6868 json_object_free(json);
6869 }
cec2e17d 6870}
6871
6872
6873/*
6874 * Display VNI information (VTY command handler).
6875 */
cd233079 6876void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
9f049418 6877 bool use_json)
cec2e17d 6878{
cd233079
CS
6879 json_object *json = NULL;
6880 void *args[2];
1f2129ec 6881 zebra_l3vni_t *zl3vni = NULL;
6882 zebra_vni_t *zvni = NULL;
cec2e17d 6883
2853fed6 6884 if (!is_evpn_enabled())
d62a17ae 6885 return;
4cce389e 6886
cd233079
CS
6887 if (use_json)
6888 json = json_object_new_object();
6889 args[0] = vty;
6890 args[1] = json;
4cce389e 6891
1f2129ec 6892 zl3vni = zl3vni_lookup(vni);
6893 if (zl3vni) {
4cce389e
MK
6894 zl3vni_print(zl3vni, (void *)args);
6895 } else {
4cce389e
MK
6896 zvni = zvni_lookup(vni);
6897 if (!zvni) {
6898 if (use_json)
6899 vty_out(vty, "{}\n");
6900 else
6901 vty_out(vty, "%% VNI %u does not exist\n", vni);
6902 return;
6903 }
6904
6905 zvni_print(zvni, (void *)args);
6906 }
6907
cd233079
CS
6908 if (use_json) {
6909 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6910 json, JSON_C_TO_STRING_PRETTY));
6911 json_object_free(json);
6912 }
cec2e17d 6913}
6914
4cce389e 6915/* Display all global details for EVPN */
088f1098 6916void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
cec2e17d 6917{
4cce389e
MK
6918 int num_l2vnis = 0;
6919 int num_l3vnis = 0;
d4454626 6920 int num_vnis = 0;
cd233079 6921 json_object *json = NULL;
4cce389e 6922 struct zebra_vrf *zvrf = NULL;
cec2e17d 6923
2853fed6 6924 if (!is_evpn_enabled())
d62a17ae 6925 return;
4cce389e 6926
4cce389e
MK
6927 zvrf = vrf_info_lookup(VRF_DEFAULT);
6928 if (!zvrf)
6929 return;
6930
89272910 6931 num_l3vnis = hashcount(zrouter.l3vni_table);
4cce389e 6932 num_l2vnis = hashcount(zvrf->vni_table);
d4454626 6933 num_vnis = num_l2vnis + num_l3vnis;
4cce389e
MK
6934
6935 if (uj) {
cd233079 6936 json = json_object_new_object();
ddd16ed5
MK
6937 json_object_string_add(json, "advertiseGatewayMacip",
6938 zvrf->advertise_gw_macip ? "Yes" : "No");
d4454626 6939 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
6940 json_object_int_add(json, "numL2Vnis", num_l2vnis);
6941 json_object_int_add(json, "numL3Vnis", num_l3vnis);
61d46eda
CS
6942 if (zvrf->dup_addr_detect)
6943 json_object_boolean_true_add(json,
6944 "isDuplicateAddrDetection");
6945 else
6946 json_object_boolean_false_add(json,
6947 "isDuplicateAddrDetection");
6948 json_object_int_add(json, "maxMoves", zvrf->dad_max_moves);
6949 json_object_int_add(json, "detectionTime", zvrf->dad_time);
6950 json_object_int_add(json, "detectionFreezeTime",
6951 zvrf->dad_freeze_time);
6952
cd233079 6953 } else {
4cce389e
MK
6954 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
6955 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
ddd16ed5
MK
6956 vty_out(vty, "Advertise gateway mac-ip: %s\n",
6957 zvrf->advertise_gw_macip ? "Yes" : "No");
278e26de
CS
6958 vty_out(vty, "Advertise svi mac-ip: %s\n",
6959 zvrf->advertise_svi_macip ? "Yes" : "No");
61d46eda
CS
6960 vty_out(vty, "Duplicate address detection: %s\n",
6961 zvrf->dup_addr_detect ? "Enable" : "Disable");
6962 vty_out(vty, " Detection max-moves %u, time %d\n",
6963 zvrf->dad_max_moves, zvrf->dad_time);
6964 if (zvrf->dad_freeze) {
6965 if (zvrf->dad_freeze_time)
6966 vty_out(vty, " Detection freeze %u\n",
6967 zvrf->dad_freeze_time);
6968 else
6969 vty_out(vty, " Detection freeze %s\n",
6970 "permanent");
6971 }
cd233079 6972 }
4cce389e
MK
6973
6974 if (uj) {
6975 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6976 json, JSON_C_TO_STRING_PRETTY));
6977 json_object_free(json);
6978 }
6979}
6980
6981/*
6982 * Display VNI hash table (VTY command handler).
6983 */
6984void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 6985 bool use_json)
4cce389e
MK
6986{
6987 json_object *json = NULL;
4cce389e
MK
6988 void *args[2];
6989
6990 if (!is_evpn_enabled())
6991 return;
6992
4cce389e
MK
6993 if (use_json)
6994 json = json_object_new_object();
6995 else
996c9314
LB
6996 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6997 "Type", "VxLAN IF", "# MACs", "# ARPs",
6998 "# Remote VTEPs", "Tenant VRF");
4cce389e 6999
cd233079
CS
7000 args[0] = vty;
7001 args[1] = json;
7002
4cce389e 7003 /* Display all L2-VNIs */
cd233079 7004 hash_iterate(zvrf->vni_table,
e3b78da8 7005 (void (*)(struct hash_bucket *, void *))zvni_print_hash,
cd233079
CS
7006 args);
7007
4cce389e 7008 /* Display all L3-VNIs */
89272910 7009 hash_iterate(zrouter.l3vni_table,
e3b78da8 7010 (void (*)(struct hash_bucket *, void *))zl3vni_print_hash,
4cce389e
MK
7011 args);
7012
cd233079
CS
7013 if (use_json) {
7014 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7015 json, JSON_C_TO_STRING_PRETTY));
7016 json_object_free(json);
7017 }
cec2e17d 7018}
7019
3950b52c
CS
7020void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
7021{
7022 struct stream *s;
7023 int time = 0;
7024 uint32_t max_moves = 0;
7025 uint32_t freeze_time = 0;
7026 bool dup_addr_detect = false;
7027 bool freeze = false;
7028
7029 s = msg;
7030 STREAM_GETL(s, dup_addr_detect);
7031 STREAM_GETL(s, time);
7032 STREAM_GETL(s, max_moves);
7033 STREAM_GETL(s, freeze);
7034 STREAM_GETL(s, freeze_time);
7035
09de9258
CS
7036 /* DAD previous state was enabled, and new state is disable,
7037 * clear all duplicate detected addresses.
7038 */
7039 if (zvrf->dup_addr_detect && !dup_addr_detect)
7040 zebra_vxlan_clear_dup_detect_vni_all(NULL, zvrf);
7041
3950b52c
CS
7042 zvrf->dup_addr_detect = dup_addr_detect;
7043 zvrf->dad_time = time;
7044 zvrf->dad_max_moves = max_moves;
7045 zvrf->dad_freeze = freeze;
7046 zvrf->dad_freeze_time = freeze_time;
7047
7048 if (IS_ZEBRA_DEBUG_VXLAN)
7049 zlog_debug(
6005fe55
CS
7050 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7051 vrf_id_to_name(zvrf->vrf->vrf_id),
3950b52c
CS
7052 zvrf->dup_addr_detect ? "enable" : "disable",
7053 zvrf->dad_max_moves,
7054 zvrf->dad_time,
7055 zvrf->dad_freeze ? "enable" : "disable",
7056 zvrf->dad_freeze_time);
7057
7058stream_failure:
7059 return;
7060}
7061
09af6961
NS
7062/*
7063 * Display VNI hash table in detail(VTY command handler).
7064 */
7065void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
7066 bool use_json)
7067{
7068 json_object *json = NULL;
7069 struct zebra_ns *zns = NULL;
7070 struct zvni_evpn_show zes;
7071
7072 if (!is_evpn_enabled())
7073 return;
7074
7075 zns = zebra_ns_lookup(NS_DEFAULT);
7076 if (!zns)
7077 return;
7078
7079
7080 if (use_json)
7081 json = json_object_new_object();
7082
7083 zes.vty = vty;
7084 zes.json = json;
7085 zes.zvrf = zvrf;
7086
7087 /* Display all L2-VNIs */
2bcb1a7f
QY
7088 hash_iterate(
7089 zvrf->vni_table,
7090 (void (*)(struct hash_bucket *, void *))zvni_print_hash_detail,
7091 &zes);
09af6961
NS
7092
7093 /* Display all L3-VNIs */
7094 hash_iterate(zrouter.l3vni_table,
e3b78da8 7095 (void (*)(struct hash_bucket *,
09af6961
NS
7096 void *))zl3vni_print_hash_detail,
7097 &zes);
7098
7099 if (use_json) {
2bcb1a7f
QY
7100 vty_out(vty, "%s\n",
7101 json_object_to_json_string_ext(
7102 json, JSON_C_TO_STRING_PRETTY));
09af6961
NS
7103 json_object_free(json);
7104 }
7105}
7106
2232a77c 7107/*
ee69da27
MK
7108 * Handle neighbor delete notification from the kernel (on a VLAN device
7109 * / L3 interface). This may result in either the neighbor getting deleted
7110 * from our database or being re-added to the kernel (if it is a valid
2232a77c 7111 * remote neighbor).
7112 */
ee69da27
MK
7113int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
7114 struct interface *link_if,
7115 struct ipaddr *ip)
d62a17ae 7116{
d62a17ae 7117 char buf[INET6_ADDRSTRLEN];
b6938a74 7118 char buf2[ETHER_ADDR_STRLEN];
b7cfce93
MK
7119 zebra_neigh_t *n = NULL;
7120 zebra_vni_t *zvni = NULL;
7121 zebra_mac_t *zmac = NULL;
8c9b80b9 7122 zebra_l3vni_t *zl3vni = NULL;
280c70ea 7123 struct zebra_vrf *zvrf;
b7cfce93 7124
8c9b80b9 7125 /* check if this is a remote neigh entry corresponding to remote
523cafc4 7126 * next-hop
7127 */
8c9b80b9
MK
7128 zl3vni = zl3vni_from_svi(ifp, link_if);
7129 if (zl3vni)
7130 return zl3vni_local_nh_del(zl3vni, ip);
d62a17ae 7131
7132 /* We are only interested in neighbors on an SVI that resides on top
7133 * of a VxLAN bridge.
7134 */
b7cfce93 7135 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 7136 if (!zvni)
7137 return 0;
8c9b80b9 7138
d62a17ae 7139 if (!zvni->vxlan_if) {
9df414fe 7140 zlog_debug(
d62a17ae 7141 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7142 zvni->vni, zvni);
7143 return -1;
7144 }
7145
7146 if (IS_ZEBRA_DEBUG_VXLAN)
8c9b80b9 7147 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
996c9314
LB
7148 ipaddr2str(ip, buf, sizeof(buf)), ifp->name,
7149 ifp->ifindex, zvni->vni);
d62a17ae 7150
7151 /* If entry doesn't exist, nothing to do. */
7152 n = zvni_neigh_lookup(zvni, ip);
7153 if (!n)
7154 return 0;
7155
b6938a74
MK
7156 zmac = zvni_mac_lookup(zvni, &n->emac);
7157 if (!zmac) {
7158 if (IS_ZEBRA_DEBUG_VXLAN)
9df414fe 7159 zlog_debug(
2853fed6 7160 "Trying to del a neigh %s without a mac %s on VNI %u",
7161 ipaddr2str(ip, buf, sizeof(buf)),
b6938a74
MK
7162 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
7163 zvni->vni);
7164
7165 return 0;
7166 }
7167
d62a17ae 7168 /* If it is a remote entry, the kernel has aged this out or someone has
7169 * deleted it, it needs to be re-installed as Quagga is the owner.
7170 */
7171 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
7172 zvni_neigh_install(zvni, n);
7173 return 0;
7174 }
7175
280c70ea
CS
7176 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
7177 if (!zvrf) {
7178 zlog_debug("%s: VNI %u vrf lookup failed.",
7179 __PRETTY_FUNCTION__, zvni->vni);
7180 return -1;
7181 }
7182
7183 /* In case of feeze action, if local neigh is in duplicate state,
7184 * Mark the Neigh as inactive before sending delete request to BGPd,
7185 * If BGPd has remote entry, it will re-install
7186 */
7187 if (zvrf->dad_freeze &&
7188 CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
7189 ZEBRA_NEIGH_SET_INACTIVE(n);
7190
d62a17ae 7191 /* Remove neighbor from BGP. */
280c70ea 7192 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0, n->state);
d62a17ae 7193
7194 /* Delete this neighbor entry. */
7195 zvni_neigh_del(zvni, n);
7196
b6938a74
MK
7197 /* see if the AUTO mac needs to be deleted */
7198 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
f51d8a27 7199 && !listcount(zmac->neigh_list))
b6938a74
MK
7200 zvni_mac_del(zvni, zmac);
7201
d62a17ae 7202 return 0;
2232a77c 7203}
7204
7205/*
ee69da27
MK
7206 * Handle neighbor add or update notification from the kernel (on a VLAN
7207 * device / L3 interface). This is typically for a local neighbor but can
7208 * also be for a remote neighbor (e.g., ageout notification). It could
7209 * also be a "move" scenario.
2232a77c 7210 */
ee69da27
MK
7211int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
7212 struct interface *link_if,
7213 struct ipaddr *ip,
7214 struct ethaddr *macaddr,
7215 uint16_t state,
a37f4598 7216 bool is_ext,
7217 bool is_router)
d62a17ae 7218{
d62a17ae 7219 char buf[ETHER_ADDR_STRLEN];
7220 char buf2[INET6_ADDRSTRLEN];
b7cfce93 7221 zebra_vni_t *zvni = NULL;
3bcbba10 7222 zebra_l3vni_t *zl3vni = NULL;
7223
7224 /* check if this is a remote neigh entry corresponding to remote
7225 * next-hop
7226 */
7227 zl3vni = zl3vni_from_svi(ifp, link_if);
7228 if (zl3vni)
7229 return zl3vni_local_nh_add_update(zl3vni, ip, state);
b7cfce93 7230
d62a17ae 7231 /* We are only interested in neighbors on an SVI that resides on top
7232 * of a VxLAN bridge.
7233 */
b7cfce93 7234 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 7235 if (!zvni)
7236 return 0;
7237
d62a17ae 7238 if (IS_ZEBRA_DEBUG_VXLAN)
7239 zlog_debug(
54c17425 7240 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
2853fed6 7241 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 7242 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
a37f4598 7243 ifp->ifindex, state, is_ext ? "ext-learned " : "",
7244 is_router ? "router " : "",
8c9b80b9 7245 zvni->vni);
d62a17ae 7246
ee69da27 7247 /* Is this about a local neighbor or a remote one? */
a37f4598 7248 if (!is_ext)
68e33151 7249 return zvni_local_neigh_update(zvni, ifp, ip, macaddr,
a37f4598 7250 is_router);
b7cfce93 7251
ee69da27 7252 return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
2232a77c 7253}
7254
b682f6de 7255
2232a77c 7256/*
7257 * Handle message from client to delete a remote MACIP for a VNI.
7258 */
89f4e507 7259void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
d62a17ae 7260{
7261 struct stream *s;
7262 vni_t vni;
7263 struct ethaddr macaddr;
7264 struct ipaddr ip;
7265 struct in_addr vtep_ip;
9df2b997 7266 uint16_t l = 0, ipa_len;
d62a17ae 7267 char buf[ETHER_ADDR_STRLEN];
7268 char buf1[INET6_ADDRSTRLEN];
7269
b7cfce93 7270 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
7271 memset(&ip, 0, sizeof(struct ipaddr));
7272 memset(&vtep_ip, 0, sizeof(struct in_addr));
7273
1002497a 7274 s = msg;
d62a17ae 7275
89f4e507 7276 while (l < hdr->length) {
d62a17ae 7277 /* Obtain each remote MACIP and process. */
7278 /* Message contains VNI, followed by MAC followed by IP (if any)
7279 * followed by remote VTEP IP.
7280 */
d62a17ae 7281 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
7282 STREAM_GETL(s, vni);
7283 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
7284 STREAM_GETL(s, ipa_len);
d62a17ae 7285 if (ipa_len) {
7286 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
7287 : IPADDR_V6;
ec93aa12 7288 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 7289 }
ff8b7eb8 7290 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 7291 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 7292 l += IPV4_MAX_BYTELEN;
7293
7294 if (IS_ZEBRA_DEBUG_VXLAN)
7295 zlog_debug(
f07e1c99 7296 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7297 vni,
d62a17ae 7298 prefix_mac2str(&macaddr, buf, sizeof(buf)),
f07e1c99 7299 ipa_len ? " IP " : "",
7300 ipa_len ?
7301 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
d62a17ae 7302 inet_ntoa(vtep_ip),
7303 zebra_route_string(client->proto));
7304
f07e1c99 7305 process_remote_macip_del(vni, &macaddr, ipa_len, &ip, vtep_ip);
d62a17ae 7306 }
7307
ec93aa12 7308stream_failure:
8068a649 7309 return;
2232a77c 7310}
7311
7312/*
7313 * Handle message from client to add a remote MACIP for a VNI. This
7314 * could be just the add of a MAC address or the add of a neighbor
7315 * (IP+MAC).
7316 */
89f4e507 7317void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
d62a17ae 7318{
7319 struct stream *s;
7320 vni_t vni;
7321 struct ethaddr macaddr;
7322 struct ipaddr ip;
7323 struct in_addr vtep_ip;
9df2b997 7324 uint16_t l = 0, ipa_len;
f07e1c99 7325 uint8_t flags = 0;
7326 uint32_t seq;
d62a17ae 7327 char buf[ETHER_ADDR_STRLEN];
7328 char buf1[INET6_ADDRSTRLEN];
d62a17ae 7329
b7cfce93 7330 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
7331 memset(&ip, 0, sizeof(struct ipaddr));
7332 memset(&vtep_ip, 0, sizeof(struct in_addr));
7333
ec93aa12 7334 if (!EVPN_ENABLED(zvrf)) {
9df414fe 7335 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
8068a649 7336 return;
ec93aa12 7337 }
d62a17ae 7338
1002497a 7339 s = msg;
d62a17ae 7340
89f4e507 7341 while (l < hdr->length) {
d62a17ae 7342 /* Obtain each remote MACIP and process. */
7343 /* Message contains VNI, followed by MAC followed by IP (if any)
7344 * followed by remote VTEP IP.
7345 */
d62a17ae 7346 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
7347 STREAM_GETL(s, vni);
7348 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
7349 STREAM_GETL(s, ipa_len);
d62a17ae 7350 if (ipa_len) {
7351 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
7352 : IPADDR_V6;
ec93aa12 7353 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 7354 }
ff8b7eb8 7355 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 7356 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 7357 l += IPV4_MAX_BYTELEN;
7358
ead40654 7359 /* Get flags - sticky mac and/or gateway mac */
2017b3ea 7360 STREAM_GETC(s, flags);
d62a17ae 7361 l++;
f07e1c99 7362 STREAM_GETL(s, seq);
7363 l += 4;
d62a17ae 7364
7365 if (IS_ZEBRA_DEBUG_VXLAN)
7366 zlog_debug(
f07e1c99 7367 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7368 vni,
d62a17ae 7369 prefix_mac2str(&macaddr, buf, sizeof(buf)),
f07e1c99 7370 ipa_len ? " IP " : "",
7371 ipa_len ?
7372 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
7373 flags, seq, inet_ntoa(vtep_ip),
d62a17ae 7374 zebra_route_string(client->proto));
7375
f07e1c99 7376 process_remote_macip_add(vni, &macaddr, ipa_len, &ip,
7377 flags, seq, vtep_ip);
d62a17ae 7378 }
7379
ec93aa12 7380stream_failure:
8068a649 7381 return;
13d60d35 7382}
7383
7384/*
2232a77c 7385 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7386 * us, this must involve a multihoming scenario. Treat this as implicit delete
7387 * of any prior local MAC.
13d60d35 7388 */
d62a17ae 7389int zebra_vxlan_check_del_local_mac(struct interface *ifp,
7390 struct interface *br_if,
7391 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 7392{
d62a17ae 7393 struct zebra_if *zif;
d62a17ae 7394 struct zebra_l2info_vxlan *vxl;
7395 vni_t vni;
7396 zebra_vni_t *zvni;
7397 zebra_mac_t *mac;
7398 char buf[ETHER_ADDR_STRLEN];
13d60d35 7399
d62a17ae 7400 zif = ifp->info;
7401 assert(zif);
7402 vxl = &zif->l2info.vxl;
7403 vni = vxl->vni;
13d60d35 7404
2853fed6 7405 /* Check if EVPN is enabled. */
7406 if (!is_evpn_enabled())
d62a17ae 7407 return 0;
13d60d35 7408
d62a17ae 7409 /* Locate hash entry; it is expected to exist. */
2853fed6 7410 zvni = zvni_lookup(vni);
d62a17ae 7411 if (!zvni)
7412 return 0;
13d60d35 7413
d62a17ae 7414 /* If entry doesn't exist, nothing to do. */
7415 mac = zvni_mac_lookup(zvni, macaddr);
7416 if (!mac)
7417 return 0;
13d60d35 7418
d62a17ae 7419 /* Is it a local entry? */
7420 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
7421 return 0;
13d60d35 7422
d62a17ae 7423 if (IS_ZEBRA_DEBUG_VXLAN)
7424 zlog_debug(
2853fed6 7425 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
996c9314
LB
7426 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7427 ifp->ifindex, vni);
13d60d35 7428
d62a17ae 7429 /* Remove MAC from BGP. */
e98e4b88 7430 zvni_mac_send_del_to_client(zvni->vni, macaddr);
13d60d35 7431
b6938a74
MK
7432 /*
7433 * If there are no neigh associated with the mac delete the mac
7434 * else mark it as AUTO for forward reference
7435 */
7436 if (!listcount(mac->neigh_list)) {
7437 zvni_mac_del(zvni, mac);
7438 } else {
7439 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7440 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
7441 }
13d60d35 7442
d62a17ae 7443 return 0;
13d60d35 7444}
7445
7446/*
2232a77c 7447 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7448 * This can happen because the remote MAC entries are also added as "dynamic",
7449 * so the kernel can ageout the entry.
13d60d35 7450 */
d62a17ae 7451int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
7452 struct interface *br_if,
7453 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 7454{
a9a76262
MK
7455 struct zebra_if *zif = NULL;
7456 struct zebra_l2info_vxlan *vxl = NULL;
d62a17ae 7457 vni_t vni;
a9a76262
MK
7458 zebra_vni_t *zvni = NULL;
7459 zebra_l3vni_t *zl3vni = NULL;
7460 zebra_mac_t *mac = NULL;
d62a17ae 7461 char buf[ETHER_ADDR_STRLEN];
2232a77c 7462
d62a17ae 7463 zif = ifp->info;
7464 assert(zif);
7465 vxl = &zif->l2info.vxl;
7466 vni = vxl->vni;
2232a77c 7467
2853fed6 7468 /* Check if EVPN is enabled. */
7469 if (!is_evpn_enabled())
d62a17ae 7470 return 0;
2232a77c 7471
a9a76262
MK
7472 /* check if this is a remote RMAC and readd simillar to remote macs */
7473 zl3vni = zl3vni_lookup(vni);
7474 if (zl3vni)
7475 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
7476
d62a17ae 7477 /* Locate hash entry; it is expected to exist. */
2853fed6 7478 zvni = zvni_lookup(vni);
d62a17ae 7479 if (!zvni)
7480 return 0;
13d60d35 7481
d62a17ae 7482 /* If entry doesn't exist, nothing to do. */
7483 mac = zvni_mac_lookup(zvni, macaddr);
7484 if (!mac)
7485 return 0;
2232a77c 7486
d62a17ae 7487 /* Is it a remote entry? */
7488 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
7489 return 0;
2232a77c 7490
d62a17ae 7491 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 7492 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
d62a17ae 7493 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7494 ifp->ifindex, vni);
13d60d35 7495
d62a17ae 7496 zvni_mac_install(zvni, mac);
7497 return 0;
13d60d35 7498}
7499
7500/*
2232a77c 7501 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 7502 */
d62a17ae 7503int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
7504 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 7505{
d62a17ae 7506 zebra_vni_t *zvni;
7507 zebra_mac_t *mac;
d62a17ae 7508 char buf[ETHER_ADDR_STRLEN];
13d60d35 7509
d62a17ae 7510 /* We are interested in MACs only on ports or (port, VLAN) that
7511 * map to a VNI.
7512 */
7513 zvni = zvni_map_vlan(ifp, br_if, vid);
7514 if (!zvni)
7515 return 0;
7516 if (!zvni->vxlan_if) {
9df414fe
QY
7517 zlog_debug(
7518 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7519 zvni->vni, zvni);
d62a17ae 7520 return -1;
7521 }
13d60d35 7522
d62a17ae 7523 if (IS_ZEBRA_DEBUG_VXLAN)
f07e1c99 7524 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
d62a17ae 7525 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7526 ifp->ifindex, vid, zvni->vni);
2232a77c 7527
d62a17ae 7528 /* If entry doesn't exist, nothing to do. */
7529 mac = zvni_mac_lookup(zvni, macaddr);
7530 if (!mac)
7531 return 0;
2232a77c 7532
d62a17ae 7533 /* Is it a local entry? */
7534 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
7535 return 0;
2232a77c 7536
b6938a74 7537 /* Update all the neigh entries associated with this mac */
2853fed6 7538 zvni_process_neigh_on_local_mac_del(zvni, mac);
b6938a74 7539
f07e1c99 7540 /* Remove MAC from BGP. */
e98e4b88 7541 zvni_mac_send_del_to_client(zvni->vni, macaddr);
f07e1c99 7542
b6938a74
MK
7543 /*
7544 * If there are no neigh associated with the mac delete the mac
7545 * else mark it as AUTO for forward reference
7546 */
7547 if (!listcount(mac->neigh_list)) {
7548 zvni_mac_del(zvni, mac);
7549 } else {
7550 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7551 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
7552 }
2232a77c 7553
d62a17ae 7554 return 0;
13d60d35 7555}
7556
7557/*
2232a77c 7558 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 7559 */
d62a17ae 7560int zebra_vxlan_local_mac_add_update(struct interface *ifp,
7561 struct interface *br_if,
7562 struct ethaddr *macaddr, vlanid_t vid,
a37f4598 7563 bool sticky)
d62a17ae 7564{
7565 zebra_vni_t *zvni;
7566 zebra_mac_t *mac;
e22a946a 7567 struct zebra_vrf *zvrf;
d62a17ae 7568 char buf[ETHER_ADDR_STRLEN];
f07e1c99 7569 bool mac_sticky = false;
7570 bool inform_client = false;
7571 bool upd_neigh = false;
a4445ece 7572 bool is_dup_detect = false;
e22a946a 7573 struct in_addr vtep_ip = {.s_addr = 0};
d62a17ae 7574
7575 /* We are interested in MACs only on ports or (port, VLAN) that
7576 * map to a VNI.
7577 */
7578 zvni = zvni_map_vlan(ifp, br_if, vid);
7579 if (!zvni) {
7580 if (IS_ZEBRA_DEBUG_VXLAN)
7581 zlog_debug(
2853fed6 7582 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7583 sticky ? "sticky " : "",
d62a17ae 7584 prefix_mac2str(macaddr, buf, sizeof(buf)),
7585 ifp->name, ifp->ifindex, vid);
7586 return 0;
7587 }
7588
7589 if (!zvni->vxlan_if) {
9df414fe
QY
7590 zlog_debug(
7591 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7592 zvni->vni, zvni);
d62a17ae 7593 return -1;
7594 }
7595
e22a946a
CS
7596 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
7597 if (!zvrf)
7598 return -1;
7599
f07e1c99 7600 /* Check if we need to create or update or it is a NO-OP. */
d62a17ae 7601 mac = zvni_mac_lookup(zvni, macaddr);
f07e1c99 7602 if (!mac) {
7603 if (IS_ZEBRA_DEBUG_VXLAN)
7604 zlog_debug(
7605 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7606 sticky ? "sticky " : "",
7607 prefix_mac2str(macaddr, buf, sizeof(buf)),
7608 ifp->name, ifp->ifindex, vid, zvni->vni);
d62a17ae 7609
f07e1c99 7610 mac = zvni_mac_add(zvni, macaddr);
7611 if (!mac) {
7612 flog_err(
e914ccbe 7613 EC_ZEBRA_MAC_ADD_FAILED,
f07e1c99 7614 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7615 prefix_mac2str(macaddr, buf, sizeof(buf)),
7616 ifp->name, ifp->ifindex, vid, zvni->vni);
7617 return -1;
7618 }
7619 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7620 mac->fwd_info.local.ifindex = ifp->ifindex;
7621 mac->fwd_info.local.vid = vid;
7622 if (sticky)
7623 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
7624 inform_client = true;
7625
7626 } else {
7627 if (IS_ZEBRA_DEBUG_VXLAN)
7628 zlog_debug(
7629 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7630 sticky ? "sticky " : "",
7631 prefix_mac2str(macaddr, buf, sizeof(buf)),
7632 ifp->name, ifp->ifindex, vid, zvni->vni,
7633 mac->flags);
7634
7635 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
7636 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
7637 mac_sticky = true;
b6938a74 7638
b8ce75a5 7639 /*
f07e1c99 7640 * Update any changes and if changes are relevant to
7641 * BGP, note it.
b8ce75a5 7642 */
d62a17ae 7643 if (mac_sticky == sticky
7644 && mac->fwd_info.local.ifindex == ifp->ifindex
7645 && mac->fwd_info.local.vid == vid) {
7646 if (IS_ZEBRA_DEBUG_VXLAN)
7647 zlog_debug(
2853fed6 7648 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
d62a17ae 7649 "entry exists and has not changed ",
d62a17ae 7650 sticky ? "sticky " : "",
7651 prefix_mac2str(macaddr, buf,
7652 sizeof(buf)),
7653 ifp->name, ifp->ifindex, vid,
7654 zvni->vni);
7655 return 0;
b6938a74 7656 }
f07e1c99 7657 if (mac_sticky != sticky) {
7658 if (sticky)
7659 SET_FLAG(mac->flags,
7660 ZEBRA_MAC_STICKY);
7661 else
7662 UNSET_FLAG(mac->flags,
7663 ZEBRA_MAC_STICKY);
7664 inform_client = true;
7665 }
7666
7667 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
7668 mac->fwd_info.local.ifindex = ifp->ifindex;
7669 mac->fwd_info.local.vid = vid;
7670
7671 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ||
7672 CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
e22a946a 7673 bool do_dad = false;
f07e1c99 7674
421bb26a 7675 /*
f07e1c99 7676 * MAC has either moved or was "internally" created due
7677 * to a neighbor learn and is now actually learnt. If
7678 * it was learnt as a remote sticky MAC, this is an
7679 * operator error.
421bb26a 7680 */
8f4b98ee 7681 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
9df414fe 7682 flog_warn(
e914ccbe 7683 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
9df414fe 7684 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
421bb26a
MK
7685 prefix_mac2str(macaddr, buf,
7686 sizeof(buf)),
7687 inet_ntoa(mac->fwd_info.r_vtep_ip),
7688 zvni->vni);
8f4b98ee
MK
7689 return 0;
7690 }
d62a17ae 7691
f07e1c99 7692 /* If an actual move, compute MAC's seq number */
e22a946a 7693 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
f07e1c99 7694 mac->loc_seq = MAX(mac->rem_seq + 1,
7695 mac->loc_seq);
e22a946a
CS
7696 vtep_ip = mac->fwd_info.r_vtep_ip;
7697 /* Trigger DAD for remote MAC */
7698 do_dad = true;
7699 }
7700
f07e1c99 7701 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
7702 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
7703 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7704 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
7705 mac->fwd_info.local.ifindex = ifp->ifindex;
7706 mac->fwd_info.local.vid = vid;
7707 if (sticky)
7708 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
7709 else
7710 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
7711 /*
7712 * We have to inform BGP of this MAC as well as process
7713 * all neighbors.
7714 */
7715 inform_client = true;
7716 upd_neigh = true;
e22a946a 7717
bdca1974
CS
7718 zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, vtep_ip,
7719 do_dad,
a4445ece 7720 &is_dup_detect,
bdca1974 7721 true);
a4445ece
CS
7722 if (is_dup_detect) {
7723 inform_client = false;
7724 upd_neigh = false;
7725 }
d62a17ae 7726 }
7727 }
7728
d62a17ae 7729 /* Inform BGP if required. */
f07e1c99 7730 if (inform_client) {
7731 if (zvni_mac_send_add_to_client(zvni->vni, macaddr,
7732 mac->flags, mac->loc_seq))
7733 return -1;
b6938a74 7734 }
d62a17ae 7735
f07e1c99 7736 /* Process all neighbors associated with this MAC, if required. */
7737 if (upd_neigh)
7738 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
7739
d62a17ae 7740 return 0;
2232a77c 7741}
13d60d35 7742
7743/*
7744 * Handle message from client to delete a remote VTEP for a VNI.
7745 */
89f4e507 7746void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
d62a17ae 7747{
7748 struct stream *s;
d7c0a89a 7749 unsigned short l = 0;
d62a17ae 7750 vni_t vni;
7751 struct in_addr vtep_ip;
7752 zebra_vni_t *zvni;
7753 zebra_vtep_t *zvtep;
b5ebdc9b 7754 struct interface *ifp;
7755 struct zebra_if *zif;
d62a17ae 7756
ec93aa12 7757 if (!is_evpn_enabled()) {
9df414fe 7758 zlog_debug(
996c9314
LB
7759 "%s: EVPN is not enabled yet we have received a vtep del command",
7760 __PRETTY_FUNCTION__);
8068a649 7761 return;
ec93aa12
DS
7762 }
7763
2853fed6 7764 if (zvrf_id(zvrf) != VRF_DEFAULT) {
9df414fe
QY
7765 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7766 zvrf_id(zvrf));
8068a649 7767 return;
2853fed6 7768 }
7769
1002497a 7770 s = msg;
d62a17ae 7771
89f4e507 7772 while (l < hdr->length) {
d62a17ae 7773 /* Obtain each remote VTEP and process. */
ec93aa12 7774 STREAM_GETL(s, vni);
d62a17ae 7775 l += 4;
ec93aa12 7776 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 7777 l += IPV4_MAX_BYTELEN;
7778
7779 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 7780 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7781 inet_ntoa(vtep_ip), vni,
d62a17ae 7782 zebra_route_string(client->proto));
7783
7784 /* Locate VNI hash entry - expected to exist. */
2853fed6 7785 zvni = zvni_lookup(vni);
d62a17ae 7786 if (!zvni) {
7787 if (IS_ZEBRA_DEBUG_VXLAN)
7788 zlog_debug(
7789 "Failed to locate VNI hash upon remote VTEP DEL, "
2853fed6 7790 "VNI %u",
7791 vni);
d62a17ae 7792 continue;
7793 }
7794
b5ebdc9b 7795 ifp = zvni->vxlan_if;
7796 if (!ifp) {
9df414fe 7797 zlog_debug(
60466a63
QY
7798 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7799 zvni->vni, zvni);
b682f6de 7800 continue;
b5ebdc9b 7801 }
7802 zif = ifp->info;
7803
7804 /* If down or not mapped to a bridge, we're done. */
b682f6de 7805 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 7806 continue;
7807
d62a17ae 7808 /* If the remote VTEP does not exist, there's nothing more to
7809 * do.
7810 * Otherwise, uninstall any remote MACs pointing to this VTEP
7811 * and
7812 * then, the VTEP entry itself and remove it.
7813 */
7814 zvtep = zvni_vtep_find(zvni, &vtep_ip);
7815 if (!zvtep)
7816 continue;
7817
7818 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
7819 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
7820 zvni_vtep_uninstall(zvni, &vtep_ip);
7821 zvni_vtep_del(zvni, zvtep);
7822 }
7823
ec93aa12 7824stream_failure:
8068a649 7825 return;
13d60d35 7826}
7827
7828/*
7829 * Handle message from client to add a remote VTEP for a VNI.
7830 */
89f4e507 7831void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
d62a17ae 7832{
7833 struct stream *s;
d7c0a89a 7834 unsigned short l = 0;
d62a17ae 7835 vni_t vni;
7836 struct in_addr vtep_ip;
7837 zebra_vni_t *zvni;
b5ebdc9b 7838 struct interface *ifp;
7839 struct zebra_if *zif;
d62a17ae 7840
ec93aa12 7841 if (!is_evpn_enabled()) {
9df414fe 7842 zlog_debug(
996c9314
LB
7843 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7844 __PRETTY_FUNCTION__);
8068a649 7845 return;
ec93aa12
DS
7846 }
7847
2853fed6 7848 if (zvrf_id(zvrf) != VRF_DEFAULT) {
9df414fe
QY
7849 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7850 zvrf_id(zvrf));
8068a649 7851 return;
2853fed6 7852 }
d62a17ae 7853
1002497a 7854 s = msg;
d62a17ae 7855
89f4e507 7856 while (l < hdr->length) {
d62a17ae 7857 /* Obtain each remote VTEP and process. */
ec93aa12 7858 STREAM_GETL(s, vni);
d62a17ae 7859 l += 4;
ec93aa12 7860 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 7861 l += IPV4_MAX_BYTELEN;
7862
7863 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 7864 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7865 inet_ntoa(vtep_ip), vni,
d62a17ae 7866 zebra_route_string(client->proto));
7867
7868 /* Locate VNI hash entry - expected to exist. */
2853fed6 7869 zvni = zvni_lookup(vni);
d62a17ae 7870 if (!zvni) {
af4c2728 7871 flog_err(
e914ccbe 7872 EC_ZEBRA_VTEP_ADD_FAILED,
2853fed6 7873 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7874 vni);
d62a17ae 7875 continue;
7876 }
b5ebdc9b 7877
7878 ifp = zvni->vxlan_if;
7879 if (!ifp) {
af4c2728 7880 flog_err(
e914ccbe 7881 EC_ZEBRA_VTEP_ADD_FAILED,
d62a17ae 7882 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7883 zvni->vni, zvni);
7884 continue;
7885 }
7886
b5ebdc9b 7887 zif = ifp->info;
d62a17ae 7888
b5ebdc9b 7889 /* If down or not mapped to a bridge, we're done. */
b682f6de 7890 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 7891 continue;
7892
b682f6de 7893 /* If the remote VTEP already exists,
7894 there's nothing more to do. */
b5ebdc9b 7895 if (zvni_vtep_find(zvni, &vtep_ip))
d62a17ae 7896 continue;
7897
7898 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
e914ccbe 7899 flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
1c50c1c0
QY
7900 "Failed to add remote VTEP, VNI %u zvni %p",
7901 vni, zvni);
d62a17ae 7902 continue;
7903 }
7904
7905 zvni_vtep_install(zvni, &vtep_ip);
7906 }
7907
ec93aa12 7908stream_failure:
8068a649 7909 return;
13d60d35 7910}
7911
1a98c087
MK
7912/*
7913 * Add/Del gateway macip to evpn
7914 * g/w can be:
7915 * 1. SVI interface on a vlan aware bridge
7916 * 2. SVI interface on a vlan unaware bridge
7917 * 3. vrr interface (MACVLAN) associated to a SVI
7918 * We advertise macip routes for an interface if it is associated to VxLan vlan
7919 */
7920int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
7921 int add)
7922{
7923 struct ipaddr ip;
7924 struct ethaddr macaddr;
7925 zebra_vni_t *zvni = NULL;
1a98c087
MK
7926
7927 memset(&ip, 0, sizeof(struct ipaddr));
7928 memset(&macaddr, 0, sizeof(struct ethaddr));
7929
2853fed6 7930 /* Check if EVPN is enabled. */
7931 if (!is_evpn_enabled())
297a21b6
MK
7932 return 0;
7933
1a98c087
MK
7934 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
7935 struct interface *svi_if =
7936 NULL; /* SVI corresponding to the MACVLAN */
7937 struct zebra_if *ifp_zif =
7938 NULL; /* Zebra daemon specific info for MACVLAN */
7939 struct zebra_if *svi_if_zif =
7940 NULL; /* Zebra daemon specific info for SVI*/
7941
7942 ifp_zif = ifp->info;
7943 if (!ifp_zif)
7944 return -1;
7945
71349e03
MK
7946 /*
7947 * for a MACVLAN interface the link represents the svi_if
7948 */
7949 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
7950 ifp_zif->link_ifindex);
1a98c087 7951 if (!svi_if) {
9df414fe
QY
7952 zlog_debug("MACVLAN %s(%u) without link information",
7953 ifp->name, ifp->ifindex);
1a98c087
MK
7954 return -1;
7955 }
7956
7957 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
7958 /*
7959 * If it is a vlan aware bridge then the link gives the
7960 * bridge information
7961 */
7962 struct interface *svi_if_link = NULL;
7963
1a98c087 7964 svi_if_zif = svi_if->info;
71349e03
MK
7965 if (svi_if_zif) {
7966 svi_if_link = if_lookup_by_index_per_ns(
60466a63
QY
7967 zebra_ns_lookup(NS_DEFAULT),
7968 svi_if_zif->link_ifindex);
b7cfce93 7969 zvni = zvni_from_svi(svi_if, svi_if_link);
71349e03 7970 }
1a98c087 7971 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
7972 /*
7973 * If it is a vlan unaware bridge then svi is the bridge
7974 * itself
7975 */
b7cfce93 7976 zvni = zvni_from_svi(svi_if, svi_if);
1a98c087
MK
7977 }
7978 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
7979 struct zebra_if *svi_if_zif =
71349e03
MK
7980 NULL; /* Zebra daemon specific info for SVI */
7981 struct interface *svi_if_link =
7982 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
7983
7984 svi_if_zif = ifp->info;
e3bb770c
IS
7985 if (svi_if_zif) {
7986 svi_if_link = if_lookup_by_index_per_ns(
cef91a18
QY
7987 zebra_ns_lookup(NS_DEFAULT),
7988 svi_if_zif->link_ifindex);
e3bb770c
IS
7989 if (svi_if_link)
7990 zvni = zvni_from_svi(ifp, svi_if_link);
7991 }
1a98c087 7992 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
b7cfce93 7993 zvni = zvni_from_svi(ifp, ifp);
1a98c087
MK
7994 }
7995
7996 if (!zvni)
7997 return 0;
7998
7999 if (!zvni->vxlan_if) {
9df414fe
QY
8000 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8001 zvni->vni, zvni);
1a98c087
MK
8002 return -1;
8003 }
8004
1a98c087 8005
1a98c087
MK
8006 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
8007
8008 if (p->family == AF_INET) {
8009 ip.ipa_type = IPADDR_V4;
8010 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
8011 sizeof(struct in_addr));
8012 } else if (p->family == AF_INET6) {
8013 ip.ipa_type = IPADDR_V6;
8014 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
8015 sizeof(struct in6_addr));
8016 }
8017
8018
8019 if (add)
8020 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
8021 else
8022 zvni_gw_macip_del(ifp, zvni, &ip);
8023
8024 return 0;
8025}
8026
2232a77c 8027/*
b7cfce93
MK
8028 * Handle SVI interface going down.
8029 * SVI can be associated to either L3-VNI or L2-VNI.
8030 * For L2-VNI: At this point, this is a NOP since
8031 * the kernel deletes the neighbor entries on this SVI (if any).
8032 * We only need to update the vrf corresponding to zvni.
8033 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8034 * from bgp
2232a77c 8035 */
d62a17ae 8036int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 8037{
b7cfce93
MK
8038 zebra_l3vni_t *zl3vni = NULL;
8039
8040 zl3vni = zl3vni_from_svi(ifp, link_if);
8041 if (zl3vni) {
8042
8043 /* process l3-vni down */
8044 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8045
8046 /* remove association with svi-if */
8047 zl3vni->svi_if = NULL;
8048 } else {
8049 zebra_vni_t *zvni = NULL;
8050
8051 /* since we dont have svi corresponding to zvni, we associate it
8052 * to default vrf. Note: the corresponding neigh entries on the
8053 * SVI would have already been deleted */
8054 zvni = zvni_from_svi(ifp, link_if);
8055 if (zvni) {
8056 zvni->vrf_id = VRF_DEFAULT;
8057
8058 /* update the tenant vrf in BGP */
8059 zvni_send_add_to_client(zvni);
8060 }
8061 }
d62a17ae 8062 return 0;
2232a77c 8063}
8064
8065/*
b7cfce93
MK
8066 * Handle SVI interface coming up.
8067 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8068 * vxlan intf).
8069 * For L2-VNI: we need to install any remote neighbors entried (used for
8070 * apr-suppression)
8071 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
2232a77c 8072 */
d62a17ae 8073int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 8074{
b7cfce93
MK
8075 zebra_vni_t *zvni = NULL;
8076 zebra_l3vni_t *zl3vni = NULL;
2232a77c 8077
b7cfce93
MK
8078 zl3vni = zl3vni_from_svi(ifp, link_if);
8079 if (zl3vni) {
2232a77c 8080
b7cfce93
MK
8081 /* associate with svi */
8082 zl3vni->svi_if = ifp;
2232a77c 8083
b7cfce93
MK
8084 /* process oper-up */
8085 if (is_l3vni_oper_up(zl3vni))
8086 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8087 } else {
8088
8089 /* process SVI up for l2-vni */
8090 struct neigh_walk_ctx n_wctx;
8091
8092 zvni = zvni_from_svi(ifp, link_if);
8093 if (!zvni)
8094 return 0;
8095
8096 if (!zvni->vxlan_if) {
9df414fe 8097 zlog_debug(
43e52561
QY
8098 "VNI %u hash %p doesn't have intf upon SVI up",
8099 zvni->vni, zvni);
b7cfce93
MK
8100 return -1;
8101 }
8102
8103 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8104 zlog_debug(
8105 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8106 ifp->name, ifp->ifindex, zvni->vni,
8107 vrf_id_to_name(ifp->vrf_id));
2232a77c 8108
b7cfce93
MK
8109 /* update the vrf information for l2-vni and inform bgp */
8110 zvni->vrf_id = ifp->vrf_id;
8111 zvni_send_add_to_client(zvni);
8112
8113 /* Install any remote neighbors for this VNI. */
8114 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
8115 n_wctx.zvni = zvni;
996c9314 8116 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
b7cfce93
MK
8117 &n_wctx);
8118 }
2232a77c 8119
d62a17ae 8120 return 0;
2232a77c 8121}
8122
13d60d35 8123/*
b7cfce93 8124 * Handle VxLAN interface down
13d60d35 8125 */
d62a17ae 8126int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 8127{
d62a17ae 8128 vni_t vni;
b7cfce93
MK
8129 struct zebra_if *zif = NULL;
8130 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 8131 zebra_l3vni_t *zl3vni = NULL;
8132 zebra_vni_t *zvni;
13d60d35 8133
2853fed6 8134 /* Check if EVPN is enabled. */
8135 if (!is_evpn_enabled())
d62a17ae 8136 return 0;
13d60d35 8137
d62a17ae 8138 zif = ifp->info;
8139 assert(zif);
8140 vxl = &zif->l2info.vxl;
8141 vni = vxl->vni;
13d60d35 8142
643215ce 8143 zl3vni = zl3vni_lookup(vni);
8144 if (zl3vni) {
b7cfce93 8145 /* process-if-down for l3-vni */
b7cfce93 8146 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8147 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
8148 ifp->ifindex, vni);
b7cfce93 8149
b7cfce93 8150 zebra_vxlan_process_l3vni_oper_down(zl3vni);
b7cfce93
MK
8151 } else {
8152 /* process if-down for l2-vni */
b7cfce93 8153 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8154 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
8155 ifp->ifindex, vni);
13d60d35 8156
b7cfce93
MK
8157 /* Locate hash entry; it is expected to exist. */
8158 zvni = zvni_lookup(vni);
8159 if (!zvni) {
9df414fe 8160 zlog_debug(
b7cfce93
MK
8161 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8162 ifp->name, ifp->ifindex, vni);
8163 return -1;
8164 }
13d60d35 8165
b7cfce93 8166 assert(zvni->vxlan_if == ifp);
13d60d35 8167
b7cfce93
MK
8168 /* Delete this VNI from BGP. */
8169 zvni_send_del_to_client(zvni->vni);
2232a77c 8170
b7cfce93
MK
8171 /* Free up all neighbors and MACs, if any. */
8172 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
8173 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
13d60d35 8174
b7cfce93
MK
8175 /* Free up all remote VTEPs, if any. */
8176 zvni_vtep_del_all(zvni, 1);
8177 }
d62a17ae 8178 return 0;
13d60d35 8179}
8180
8181/*
8182 * Handle VxLAN interface up - update BGP if required.
8183 */
d62a17ae 8184int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 8185{
d62a17ae 8186 vni_t vni;
b7cfce93
MK
8187 struct zebra_if *zif = NULL;
8188 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 8189 zebra_vni_t *zvni = NULL;
8190 zebra_l3vni_t *zl3vni = NULL;
13d60d35 8191
2853fed6 8192 /* Check if EVPN is enabled. */
8193 if (!is_evpn_enabled())
d62a17ae 8194 return 0;
13d60d35 8195
d62a17ae 8196 zif = ifp->info;
8197 assert(zif);
8198 vxl = &zif->l2info.vxl;
8199 vni = vxl->vni;
13d60d35 8200
643215ce 8201 zl3vni = zl3vni_lookup(vni);
8202 if (zl3vni) {
13d60d35 8203
b7cfce93 8204 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8205 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp->name,
8206 ifp->ifindex, vni);
13d60d35 8207
b7cfce93 8208 /* we need to associate with SVI, if any, we can associate with
523cafc4 8209 * svi-if only after association with vxlan-intf is complete
8210 */
b7cfce93
MK
8211 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8212
8213 if (is_l3vni_oper_up(zl3vni))
8214 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8215 } else {
8216 /* Handle L2-VNI add */
b7cfce93
MK
8217 struct interface *vlan_if = NULL;
8218
8219 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8220 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
8221 ifp->ifindex, vni);
b7cfce93
MK
8222
8223 /* Locate hash entry; it is expected to exist. */
8224 zvni = zvni_lookup(vni);
8225 if (!zvni) {
9df414fe 8226 zlog_debug(
b7cfce93
MK
8227 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8228 ifp->name, ifp->ifindex, vni);
8229 return -1;
8230 }
8231
8232 assert(zvni->vxlan_if == ifp);
8233 vlan_if = zvni_map_to_svi(vxl->access_vlan,
8234 zif->brslave_info.br_if);
8235 if (vlan_if) {
8236 zvni->vrf_id = vlan_if->vrf_id;
8237 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
8238 if (zl3vni)
8239 listnode_add_sort(zl3vni->l2vnis, zvni);
8240 }
8241
8242 /* If part of a bridge, inform BGP about this VNI. */
8243 /* Also, read and populate local MACs and neighbors. */
8244 if (zif->brslave_info.br_if) {
8245 zvni_send_add_to_client(zvni);
8246 zvni_read_mac_neigh(zvni, ifp);
8247 }
d62a17ae 8248 }
13d60d35 8249
d62a17ae 8250 return 0;
13d60d35 8251}
8252
8253/*
8254 * Handle VxLAN interface delete. Locate and remove entry in hash table
8255 * and update BGP, if required.
8256 */
d62a17ae 8257int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 8258{
d62a17ae 8259 vni_t vni;
b7cfce93
MK
8260 struct zebra_if *zif = NULL;
8261 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 8262 zebra_vni_t *zvni = NULL;
8263 zebra_l3vni_t *zl3vni = NULL;
13d60d35 8264
2853fed6 8265 /* Check if EVPN is enabled. */
8266 if (!is_evpn_enabled())
d62a17ae 8267 return 0;
13d60d35 8268
d62a17ae 8269 zif = ifp->info;
8270 assert(zif);
8271 vxl = &zif->l2info.vxl;
8272 vni = vxl->vni;
13d60d35 8273
643215ce 8274 zl3vni = zl3vni_lookup(vni);
8275 if (zl3vni) {
b7cfce93
MK
8276
8277 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8278 zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
8279 ifp->ifindex);
13d60d35 8280
b7cfce93
MK
8281 /* process oper-down for l3-vni */
8282 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2232a77c 8283
b7cfce93 8284 /* remove the association with vxlan_if */
b67a60d2 8285 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
b7cfce93
MK
8286 zl3vni->vxlan_if = NULL;
8287 } else {
13d60d35 8288
b7cfce93 8289 /* process if-del for l2-vni*/
b7cfce93 8290 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8291 zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
8292 ifp->ifindex);
b7cfce93
MK
8293
8294 /* Locate hash entry; it is expected to exist. */
8295 zvni = zvni_lookup(vni);
8296 if (!zvni) {
9df414fe 8297 zlog_debug(
b7cfce93
MK
8298 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8299 ifp->name, ifp->ifindex, vni);
8300 return 0;
8301 }
8302
8303 /* remove from l3-vni list */
8304 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
8305 if (zl3vni)
8306 listnode_delete(zl3vni->l2vnis, zvni);
8307
8308 /* Delete VNI from BGP. */
8309 zvni_send_del_to_client(zvni->vni);
8310
8311 /* Free up all neighbors and MAC, if any. */
8312 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
8313 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
8314
8315 /* Free up all remote VTEPs, if any. */
8316 zvni_vtep_del_all(zvni, 0);
8317
8318 /* Delete the hash entry. */
8319 if (zvni_del(zvni)) {
e914ccbe 8320 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
1c50c1c0
QY
8321 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8322 zvni, ifp->name, ifp->ifindex, zvni->vni);
b7cfce93
MK
8323 return -1;
8324 }
d62a17ae 8325 }
d62a17ae 8326 return 0;
13d60d35 8327}
8328
8329/*
8330 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8331 */
d7c0a89a 8332int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
d62a17ae 8333{
d62a17ae 8334 vni_t vni;
b7cfce93
MK
8335 struct zebra_if *zif = NULL;
8336 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 8337 zebra_vni_t *zvni = NULL;
8338 zebra_l3vni_t *zl3vni = NULL;
d62a17ae 8339
2853fed6 8340 /* Check if EVPN is enabled. */
8341 if (!is_evpn_enabled())
d62a17ae 8342 return 0;
8343
8344 zif = ifp->info;
8345 assert(zif);
8346 vxl = &zif->l2info.vxl;
8347 vni = vxl->vni;
8348
643215ce 8349 zl3vni = zl3vni_lookup(vni);
8350 if (zl3vni) {
af026ae4 8351
b7cfce93
MK
8352 if (IS_ZEBRA_DEBUG_VXLAN)
8353 zlog_debug(
8354 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
996c9314
LB
8355 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
8356 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
8357 zif->brslave_info.bridge_ifindex, chgflags);
8358
8359 /* Removed from bridge? Cleanup and return */
8360 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8361 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
8362 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8363 return 0;
8364 }
8365
8366 /* access-vlan change - process oper down, associate with new
523cafc4 8367 * svi_if and then process oper up again
8368 */
b7cfce93
MK
8369 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
8370 if (if_is_operative(ifp)) {
8371 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8372 zl3vni->svi_if = NULL;
8373 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
bca63dc8 8374 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
8375 if (is_l3vni_oper_up(zl3vni))
8376 zebra_vxlan_process_l3vni_oper_up(
996c9314 8377 zl3vni);
b7cfce93
MK
8378 }
8379 }
d62a17ae 8380
12eeac84
MK
8381 /*
8382 * local-ip change - process oper down, associate with new
8383 * local-ip and then process oper up again
8384 */
8385 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
8386 if (if_is_operative(ifp)) {
8387 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8388 zl3vni->local_vtep_ip = vxl->vtep_ip;
8389 if (is_l3vni_oper_up(zl3vni))
8390 zebra_vxlan_process_l3vni_oper_up(
996c9314 8391 zl3vni);
12eeac84
MK
8392 }
8393 }
8394
bca63dc8
MK
8395 /* Update local tunnel IP. */
8396 zl3vni->local_vtep_ip = vxl->vtep_ip;
8397
12eeac84
MK
8398 /* if we have a valid new master, process l3-vni oper up */
8399 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
8400 if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
b7cfce93
MK
8401 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8402 }
8403 } else {
d62a17ae 8404
b7cfce93
MK
8405 /* Update VNI hash. */
8406 zvni = zvni_lookup(vni);
8407 if (!zvni) {
9df414fe 8408 zlog_debug(
b7cfce93
MK
8409 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8410 ifp->name, ifp->ifindex, vni);
8411 return -1;
8412 }
d62a17ae 8413
b7cfce93
MK
8414 if (IS_ZEBRA_DEBUG_VXLAN)
8415 zlog_debug(
8416 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
996c9314
LB
8417 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
8418 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
8419 zif->brslave_info.bridge_ifindex, chgflags);
8420
8421 /* Removed from bridge? Cleanup and return */
8422 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8423 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
8424 /* Delete from client, remove all remote VTEPs */
8425 /* Also, free up all MACs and neighbors. */
8426 zvni_send_del_to_client(zvni->vni);
8427 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
8428 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
8429 zvni_vtep_del_all(zvni, 1);
8430 return 0;
8431 }
d62a17ae 8432
b7cfce93
MK
8433 /* Handle other changes. */
8434 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
8435 /* Remove all existing local neigh and MACs for this VNI
8436 * (including from BGP)
8437 */
8438 zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
8439 zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
8440 }
d62a17ae 8441
b7cfce93
MK
8442 zvni->local_vtep_ip = vxl->vtep_ip;
8443 zvni->vxlan_if = ifp;
d62a17ae 8444
b7cfce93
MK
8445 /* Take further actions needed.
8446 * Note that if we are here, there is a change of interest.
8447 */
8448 /* If down or not mapped to a bridge, we're done. */
8449 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8450 return 0;
d62a17ae 8451
b7cfce93
MK
8452 /* Inform BGP, if there is a change of interest. */
8453 if (chgflags
8454 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
8455 zvni_send_add_to_client(zvni);
8456
8457 /* If there is a valid new master or a VLAN mapping change,
8458 * read and populate local MACs and neighbors.
8459 * Also, reinstall any remote MACs and neighbors
8460 * for this VNI (based on new VLAN).
8461 */
8462 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8463 zvni_read_mac_neigh(zvni, ifp);
8464 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
8465 struct mac_walk_ctx m_wctx;
8466 struct neigh_walk_ctx n_wctx;
8467
8468 zvni_read_mac_neigh(zvni, ifp);
8469
8470 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
8471 m_wctx.zvni = zvni;
996c9314 8472 hash_iterate(zvni->mac_table, zvni_install_mac_hash,
b7cfce93
MK
8473 &m_wctx);
8474
8475 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
8476 n_wctx.zvni = zvni;
8477 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
8478 &n_wctx);
8479 }
d62a17ae 8480 }
8481
8482 return 0;
13d60d35 8483}
8484
8485/*
8486 * Handle VxLAN interface add.
8487 */
d62a17ae 8488int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 8489{
d62a17ae 8490 vni_t vni;
b7cfce93
MK
8491 struct zebra_if *zif = NULL;
8492 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 8493 zebra_vni_t *zvni = NULL;
8494 zebra_l3vni_t *zl3vni = NULL;
13d60d35 8495
2853fed6 8496 /* Check if EVPN is enabled. */
8497 if (!is_evpn_enabled())
d62a17ae 8498 return 0;
13d60d35 8499
d62a17ae 8500 zif = ifp->info;
8501 assert(zif);
8502 vxl = &zif->l2info.vxl;
8503 vni = vxl->vni;
13d60d35 8504
643215ce 8505 zl3vni = zl3vni_lookup(vni);
8506 if (zl3vni) {
13d60d35 8507
b7cfce93 8508 /* process if-add for l3-vni*/
b7cfce93
MK
8509 if (IS_ZEBRA_DEBUG_VXLAN)
8510 zlog_debug(
8511 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
996c9314
LB
8512 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
8513 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
8514 zif->brslave_info.bridge_ifindex);
8515
b7cfce93 8516 /* associate with vxlan_if */
b67a60d2 8517 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
8518 zl3vni->vxlan_if = ifp;
8519
8520 /* Associate with SVI, if any. We can associate with svi-if only
8521 * after association with vxlan_if is complete */
8522 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8523
8524 if (is_l3vni_oper_up(zl3vni))
8525 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8526 } else {
8527
8528 /* process if-add for l2-vni */
b7cfce93
MK
8529 struct interface *vlan_if = NULL;
8530
8531 /* Create or update VNI hash. */
8532 zvni = zvni_lookup(vni);
8533 if (!zvni) {
8534 zvni = zvni_add(vni);
8535 if (!zvni) {
af4c2728 8536 flog_err(
e914ccbe 8537 EC_ZEBRA_VNI_ADD_FAILED,
b7cfce93
MK
8538 "Failed to add VNI hash, IF %s(%u) VNI %u",
8539 ifp->name, ifp->ifindex, vni);
8540 return -1;
8541 }
8542 }
8543
8544 zvni->local_vtep_ip = vxl->vtep_ip;
8545 zvni->vxlan_if = ifp;
8546 vlan_if = zvni_map_to_svi(vxl->access_vlan,
8547 zif->brslave_info.br_if);
8548 if (vlan_if) {
8549 zvni->vrf_id = vlan_if->vrf_id;
8550 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
8551 if (zl3vni)
8552 listnode_add_sort(zl3vni->l2vnis, zvni);
8553 }
8554
8555 if (IS_ZEBRA_DEBUG_VXLAN)
8556 zlog_debug(
8557 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8558 vni,
996c9314 8559 vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
08ab35fe 8560 : VRF_DEFAULT_NAME,
996c9314
LB
8561 ifp->name, ifp->ifindex, vxl->access_vlan,
8562 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
8563 zif->brslave_info.bridge_ifindex);
8564
8565 /* If down or not mapped to a bridge, we're done. */
8566 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8567 return 0;
8568
8569 /* Inform BGP */
8570 zvni_send_add_to_client(zvni);
8571
8572 /* Read and populate local MACs and neighbors */
8573 zvni_read_mac_neigh(zvni, ifp);
8574 }
8575
8576 return 0;
8577}
8578
996c9314
LB
8579int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
8580 char *err, int err_str_sz, int filter,
8581 int add)
b7cfce93
MK
8582{
8583 zebra_l3vni_t *zl3vni = NULL;
8584 struct zebra_vrf *zvrf_default = NULL;
8585
8586 zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
8587 if (!zvrf_default)
8588 return -1;
8589
8590 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 8591 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
b7cfce93
MK
8592 add ? "ADD" : "DEL");
8593
8594 if (add) {
8595
8596 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
8597
8598 /* check if the vni is already present under zvrf */
8599 if (zvrf->l3vni) {
3f02fbab 8600 snprintf(err, err_str_sz,
b7cfce93
MK
8601 "VNI is already configured under the vrf");
8602 return -1;
8603 }
8604
8605 /* check if this VNI is already present in the system */
8606 zl3vni = zl3vni_lookup(vni);
8607 if (zl3vni) {
3f02fbab 8608 snprintf(err, err_str_sz,
b7cfce93
MK
8609 "VNI is already configured as L3-VNI");
8610 return -1;
8611 }
8612
8613 /* add the L3-VNI to the global table */
8614 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
8615 if (!zl3vni) {
996c9314 8616 snprintf(err, err_str_sz, "Could not add L3-VNI");
b7cfce93
MK
8617 return -1;
8618 }
8619
8620 /* associate the vrf with vni */
8621 zvrf->l3vni = vni;
8622
c48d9f5f
MK
8623 /* set the filter in l3vni to denote if we are using l3vni only
8624 * for prefix routes
8625 */
8626 if (filter)
8627 SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
8628
b7cfce93 8629 /* associate with vxlan-intf;
523cafc4 8630 * we need to associate with the vxlan-intf first
8631 */
b7cfce93
MK
8632 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
8633
8634 /* associate with corresponding SVI interface, we can associate
8635 * with svi-if only after vxlan interface association is
523cafc4 8636 * complete
8637 */
b7cfce93
MK
8638 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8639
8640 /* formulate l2vni list */
996c9314
LB
8641 hash_iterate(zvrf_default->vni_table, zvni_add_to_l3vni_list,
8642 zl3vni);
b7cfce93
MK
8643
8644 if (is_l3vni_oper_up(zl3vni))
8645 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8646
8647 } else {
8648 zl3vni = zl3vni_lookup(vni);
8649 if (!zl3vni) {
3f02fbab 8650 snprintf(err, err_str_sz, "VNI doesn't exist");
d62a17ae 8651 return -1;
8652 }
b7cfce93 8653
cf299714
MK
8654 if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
8655 snprintf(err, ERR_STR_SZ,
8656 "prefix-routes-only is not set for the vni");
8657 return -1;
8658 }
8659
b7cfce93
MK
8660 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8661
5e06422c 8662 /* delete and uninstall all rmacs */
996c9314 8663 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
5e06422c
MK
8664 zl3vni);
8665
8666 /* delete and uninstall all next-hops */
996c9314 8667 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
5e06422c
MK
8668 zl3vni);
8669
b7cfce93
MK
8670 zvrf->l3vni = 0;
8671 zl3vni_del(zl3vni);
8672
8673 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
d62a17ae 8674 }
b7cfce93
MK
8675 return 0;
8676}
13d60d35 8677
84915b0a 8678int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
8679{
8680 zebra_l3vni_t *zl3vni = NULL;
8681
8682 if (zvrf->l3vni)
8683 zl3vni = zl3vni_lookup(zvrf->l3vni);
8684 if (!zl3vni)
8685 return 0;
8686
8687 zl3vni->vrf_id = zvrf_id(zvrf);
8688 if (is_l3vni_oper_up(zl3vni))
8689 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8690 return 0;
8691}
8692
8693int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
b7cfce93
MK
8694{
8695 zebra_l3vni_t *zl3vni = NULL;
13d60d35 8696
84915b0a 8697 if (zvrf->l3vni)
8698 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93 8699 if (!zl3vni)
d62a17ae 8700 return 0;
13d60d35 8701
84915b0a 8702 zl3vni->vrf_id = VRF_UNKNOWN;
b7cfce93 8703 zebra_vxlan_process_l3vni_oper_down(zl3vni);
84915b0a 8704 return 0;
8705}
8706
8707int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
8708{
8709 zebra_l3vni_t *zl3vni = NULL;
8710 vni_t vni;
8711
8712 if (zvrf->l3vni)
8713 zl3vni = zl3vni_lookup(zvrf->l3vni);
8714 if (!zl3vni)
8715 return 0;
8716
8717 vni = zl3vni->vni;
b7cfce93 8718 zl3vni_del(zl3vni);
84915b0a 8719 zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
2232a77c 8720
d62a17ae 8721 return 0;
13d60d35 8722}
8723
fbac9605
DS
8724/*
8725 * Handle message from client to specify the flooding mechanism for
8726 * BUM packets. The default is to do head-end (ingress) replication
8727 * and the other supported option is to disable it. This applies to
8728 * all BUM traffic and disabling it applies to both the transmit and
8729 * receive direction.
8730 */
8731void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
8732{
8733 struct stream *s;
8734 enum vxlan_flood_control flood_ctrl;
8735
8736 if (zvrf_id(zvrf) != VRF_DEFAULT) {
8737 zlog_err("EVPN flood control for non-default VRF %u",
8738 zvrf_id(zvrf));
8739 return;
8740 }
8741
8742 s = msg;
8743 STREAM_GETC(s, flood_ctrl);
8744
8745 if (IS_ZEBRA_DEBUG_VXLAN)
8746 zlog_debug("EVPN flood control %u, currently %u",
8747 flood_ctrl, zvrf->vxlan_flood_ctrl);
8748
8749 if (zvrf->vxlan_flood_ctrl == flood_ctrl)
8750 return;
8751
8752 zvrf->vxlan_flood_ctrl = flood_ctrl;
8753
8754 /* Install or uninstall flood entries corresponding to
8755 * remote VTEPs.
8756 */
8757 hash_iterate(zvrf->vni_table, zvni_handle_flooding_remote_vteps,
8758 zvrf);
8759
8760stream_failure:
8761 return;
8762}
8763
278e26de
CS
8764/*
8765 * Handle message from client to enable/disable advertisement of svi macip
8766 * routes
8767 */
8768void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
8769{
8770 struct stream *s;
8771 int advertise;
8772 vni_t vni = 0;
8773 zebra_vni_t *zvni = NULL;
8774 struct interface *ifp = NULL;
8775
8776 if (zvrf_id(zvrf) != VRF_DEFAULT) {
8777 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8778 zvrf_id(zvrf));
8779 return;
8780 }
8781
8782 s = msg;
8783 STREAM_GETC(s, advertise);
8784 STREAM_GETL(s, vni);
8785
8786 if (!vni) {
8787 if (IS_ZEBRA_DEBUG_VXLAN)
8788 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8789 advertise ? "enabled" : "disabled",
8790 advertise_gw_macip_enabled(NULL)
8791 ? "enabled"
8792 : "disabled");
8793
8794 if (zvrf->advertise_svi_macip == advertise)
8795 return;
8796
8797
8798 if (advertise) {
8799 zvrf->advertise_svi_macip = advertise;
8800 hash_iterate(zvrf->vni_table,
8801 zvni_gw_macip_add_for_vni_hash, NULL);
8802 } else {
8803 hash_iterate(zvrf->vni_table,
8804 zvni_svi_macip_del_for_vni_hash, NULL);
8805 zvrf->advertise_svi_macip = advertise;
8806 }
8807
8808 } else {
8809 struct zebra_if *zif = NULL;
8810 struct zebra_l2info_vxlan zl2_info;
8811 struct interface *vlan_if = NULL;
8812
8813 zvni = zvni_lookup(vni);
8814 if (!zvni)
8815 return;
8816
8817 if (IS_ZEBRA_DEBUG_VXLAN)
8818 zlog_debug(
8819 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8820 advertise ? "enabled" : "disabled", vni,
8821 advertise_svi_macip_enabled(zvni)
8822 ? "enabled"
8823 : "disabled");
8824
8825 if (zvni->advertise_svi_macip == advertise)
8826 return;
8827
8828 ifp = zvni->vxlan_if;
8829 if (!ifp)
8830 return;
8831
8832 zif = ifp->info;
8833
8834 /* If down or not mapped to a bridge, we're done. */
8835 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8836 return;
8837
8838 zl2_info = zif->l2info.vxl;
8839
8840 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
8841 zif->brslave_info.br_if);
8842 if (!vlan_if)
8843 return;
8844
8845 if (advertise) {
8846 zvni->advertise_svi_macip = advertise;
8847 /* Add primary SVI MAC-IP */
8848 zvni_add_macip_for_intf(vlan_if, zvni);
8849 } else {
8850 /* Del primary MAC-IP */
8851 zvni_del_macip_for_intf(vlan_if, zvni);
8852 zvni->advertise_svi_macip = advertise;
8853 }
8854 }
8855
8856stream_failure:
8857 return;
8858}
8859
31310b25
MK
8860/*
8861 * Handle message from client to enable/disable advertisement of g/w macip
8862 * routes
8863 */
89f4e507 8864void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
31310b25
MK
8865{
8866 struct stream *s;
8867 int advertise;
8868 vni_t vni = 0;
8869 zebra_vni_t *zvni = NULL;
8870 struct interface *ifp = NULL;
8871 struct zebra_if *zif = NULL;
8872 struct zebra_l2info_vxlan zl2_info;
8873 struct interface *vlan_if = NULL;
8874
8875 if (zvrf_id(zvrf) != VRF_DEFAULT) {
9df414fe
QY
8876 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8877 zvrf_id(zvrf));
8068a649 8878 return;
31310b25
MK
8879 }
8880
1002497a 8881 s = msg;
2017b3ea 8882 STREAM_GETC(s, advertise);
31310b25
MK
8883 vni = stream_get3(s);
8884
8885 zvni = zvni_lookup(vni);
8886 if (!zvni)
8068a649 8887 return;
31310b25
MK
8888
8889 if (zvni->advertise_subnet == advertise)
8068a649 8890 return;
31310b25
MK
8891
8892 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
8893 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8894 advertise ? "enabled" : "disabled", vni,
8895 zvni->advertise_subnet ? "enabled" : "disabled");
31310b25
MK
8896
8897
8898 zvni->advertise_subnet = advertise;
8899
8900 ifp = zvni->vxlan_if;
8901 if (!ifp)
8068a649 8902 return;
31310b25
MK
8903
8904 zif = ifp->info;
8905
8906 /* If down or not mapped to a bridge, we're done. */
8907 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 8908 return;
31310b25
MK
8909
8910 zl2_info = zif->l2info.vxl;
8911
996c9314
LB
8912 vlan_if =
8913 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
31310b25 8914 if (!vlan_if)
8068a649 8915 return;
31310b25
MK
8916
8917 if (zvni->advertise_subnet)
8918 zvni_advertise_subnet(zvni, vlan_if, 1);
8919 else
8920 zvni_advertise_subnet(zvni, vlan_if, 0);
2017b3ea
DS
8921
8922stream_failure:
8923 return;
31310b25
MK
8924}
8925
1a98c087
MK
8926/*
8927 * Handle message from client to enable/disable advertisement of g/w macip
8928 * routes
8929 */
89f4e507 8930void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
1a98c087
MK
8931{
8932 struct stream *s;
8933 int advertise;
8934 vni_t vni = 0;
8935 zebra_vni_t *zvni = NULL;
b5ebdc9b 8936 struct interface *ifp = NULL;
1a98c087 8937
2853fed6 8938 if (zvrf_id(zvrf) != VRF_DEFAULT) {
9df414fe
QY
8939 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8940 zvrf_id(zvrf));
8068a649 8941 return;
2853fed6 8942 }
8943
1002497a 8944 s = msg;
ec93aa12 8945 STREAM_GETC(s, advertise);
cc6d5476 8946 STREAM_GETL(s, vni);
1a98c087
MK
8947
8948 if (!vni) {
8949 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 8950 zlog_debug("EVPN gateway macip Adv %s, currently %s",
1a98c087 8951 advertise ? "enabled" : "disabled",
2853fed6 8952 advertise_gw_macip_enabled(NULL)
1a98c087
MK
8953 ? "enabled"
8954 : "disabled");
8955
8956 if (zvrf->advertise_gw_macip == advertise)
8068a649 8957 return;
1a98c087
MK
8958
8959 zvrf->advertise_gw_macip = advertise;
8960
2853fed6 8961 if (advertise_gw_macip_enabled(zvni))
1a98c087 8962 hash_iterate(zvrf->vni_table,
2853fed6 8963 zvni_gw_macip_add_for_vni_hash, NULL);
1a98c087
MK
8964 else
8965 hash_iterate(zvrf->vni_table,
2853fed6 8966 zvni_gw_macip_del_for_vni_hash, NULL);
1a98c087
MK
8967
8968 } else {
8969 struct zebra_if *zif = NULL;
8970 struct zebra_l2info_vxlan zl2_info;
8971 struct interface *vlan_if = NULL;
8972 struct interface *vrr_if = NULL;
8973
01a6143b
MK
8974 zvni = zvni_lookup(vni);
8975 if (!zvni)
124ead27 8976 return;
01a6143b 8977
1a98c087
MK
8978 if (IS_ZEBRA_DEBUG_VXLAN)
8979 zlog_debug(
2853fed6 8980 "EVPN gateway macip Adv %s on VNI %d , currently %s",
1a98c087 8981 advertise ? "enabled" : "disabled", vni,
996c9314
LB
8982 advertise_gw_macip_enabled(zvni) ? "enabled"
8983 : "disabled");
1a98c087 8984
1a98c087 8985 if (zvni->advertise_gw_macip == advertise)
8068a649 8986 return;
1a98c087
MK
8987
8988 zvni->advertise_gw_macip = advertise;
8989
b5ebdc9b 8990 ifp = zvni->vxlan_if;
8991 if (!ifp)
8068a649 8992 return;
b5ebdc9b 8993
8994 zif = ifp->info;
8995
8996 /* If down or not mapped to a bridge, we're done. */
b682f6de 8997 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 8998 return;
b5ebdc9b 8999
1a98c087
MK
9000 zl2_info = zif->l2info.vxl;
9001
2853fed6 9002 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
1a98c087
MK
9003 zif->brslave_info.br_if);
9004 if (!vlan_if)
8068a649 9005 return;
1a98c087 9006
2853fed6 9007 if (advertise_gw_macip_enabled(zvni)) {
1a98c087
MK
9008 /* Add primary SVI MAC-IP */
9009 zvni_add_macip_for_intf(vlan_if, zvni);
9010
9011 /* Add VRR MAC-IP - if any*/
9012 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
9013 if (vrr_if)
9014 zvni_add_macip_for_intf(vrr_if, zvni);
9015 } else {
9016 /* Del primary MAC-IP */
9017 zvni_del_macip_for_intf(vlan_if, zvni);
9018
9019 /* Del VRR MAC-IP - if any*/
9020 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
9021 if (vrr_if)
9022 zvni_del_macip_for_intf(vrr_if, zvni);
9023 }
9024 }
9025
ec93aa12 9026stream_failure:
8068a649 9027 return;
1a98c087
MK
9028}
9029
9030
13d60d35 9031/*
9032 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9033 * When enabled, the VNI hash table will be built and MAC FDB table read;
9034 * when disabled, the entries should be deleted and remote VTEPs and MACs
9035 * uninstalled from the kernel.
fbac9605
DS
9036 * This also informs the setting for BUM handling at the time this change
9037 * occurs; it is relevant only when specifying "learn".
13d60d35 9038 */
89f4e507 9039void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
13d60d35 9040{
655b04d1
MK
9041 struct stream *s = NULL;
9042 int advertise = 0;
fbac9605 9043 enum vxlan_flood_control flood_ctrl;
13d60d35 9044
2853fed6 9045 if (zvrf_id(zvrf) != VRF_DEFAULT) {
9df414fe
QY
9046 zlog_debug("EVPN VNI Adv for non-default VRF %u",
9047 zvrf_id(zvrf));
8068a649 9048 return;
2853fed6 9049 }
9050
1002497a 9051 s = msg;
ec93aa12 9052 STREAM_GETC(s, advertise);
fbac9605 9053 STREAM_GETC(s, flood_ctrl);
13d60d35 9054
d62a17ae 9055 if (IS_ZEBRA_DEBUG_VXLAN)
fbac9605 9056 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
d62a17ae 9057 advertise ? "enabled" : "disabled",
fbac9605
DS
9058 is_evpn_enabled() ? "enabled" : "disabled",
9059 flood_ctrl);
13d60d35 9060
d62a17ae 9061 if (zvrf->advertise_all_vni == advertise)
8068a649 9062 return;
13d60d35 9063
d62a17ae 9064 zvrf->advertise_all_vni = advertise;
2853fed6 9065 if (is_evpn_enabled()) {
fbac9605
DS
9066 /* Note BUM handling */
9067 zvrf->vxlan_flood_ctrl = flood_ctrl;
9068
d62a17ae 9069 /* Build VNI hash table and inform BGP. */
2853fed6 9070 zvni_build_hash_table();
2232a77c 9071
1a98c087
MK
9072 /* Add all SVI (L3 GW) MACs to BGP*/
9073 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
2853fed6 9074 NULL);
1a98c087 9075
d62a17ae 9076 /* Read the MAC FDB */
9077 macfdb_read(zvrf->zns);
2232a77c 9078
d62a17ae 9079 /* Read neighbors */
9080 neigh_read(zvrf->zns);
9081 } else {
9082 /* Cleanup VTEPs for all VNIs - uninstall from
9083 * kernel and free entries.
9084 */
9085 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
655b04d1
MK
9086
9087 /* cleanup all l3vnis */
89272910 9088 hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL);
d62a17ae 9089 }
13d60d35 9090
ec93aa12 9091stream_failure:
8068a649 9092 return;
13d60d35 9093}
9094
9095/*
9096 * Allocate VNI hash table for this VRF and do other initialization.
9097 * NOTE: Currently supported only for default VRF.
9098 */
d62a17ae 9099void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 9100{
d62a17ae 9101 if (!zvrf)
9102 return;
9103 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
9104 "Zebra VRF VNI Table");
13d60d35 9105}
9106
84915b0a 9107/* Cleanup VNI info, but don't free the table. */
9108void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
9109{
9110 if (!zvrf)
9111 return;
9112 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9113}
9114
13d60d35 9115/* Close all VNI handling */
d62a17ae 9116void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 9117{
2853fed6 9118 if (!zvrf)
9119 return;
d62a17ae 9120 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9b67b514 9121 hash_free(zvrf->vni_table);
13d60d35 9122}
b7cfce93
MK
9123
9124/* init the l3vni table */
6548050a 9125void zebra_vxlan_init(void)
b7cfce93 9126{
89272910
DS
9127 zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
9128 "Zebra VRF L3 VNI table");
b7cfce93
MK
9129}
9130
9131/* free l3vni table */
6548050a 9132void zebra_vxlan_disable(void)
b7cfce93 9133{
89272910 9134 hash_free(zrouter.l3vni_table);
b7cfce93 9135}
d3135ba3 9136
9137/* get the l3vni svi ifindex */
9138ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
9139{
9140 zebra_l3vni_t *zl3vni = NULL;
9141
9142 zl3vni = zl3vni_from_vrf(vrf_id);
9143 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
9144 return 0;
9145
9146 return zl3vni->svi_if->ifindex;
9147}
c80a972c
CS
9148
9149static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
9150{
9151 struct zebra_vrf *zvrf = NULL;
9152 zebra_neigh_t *nbr = NULL;
9153 zebra_vni_t *zvni = NULL;
9154 char buf1[INET6_ADDRSTRLEN];
9155 char buf2[ETHER_ADDR_STRLEN];
9156
9157 nbr = THREAD_ARG(t);
9158
9159 /* since this is asynchronous we need sanity checks*/
8a3bc58e
DS
9160 zvrf = vrf_info_lookup(nbr->zvni->vrf_id);
9161 if (!zvrf)
979777b2 9162 return 0;
c80a972c
CS
9163
9164 zvni = zvni_lookup(nbr->zvni->vni);
9165 if (!zvni)
979777b2 9166 return 0;
c80a972c 9167
8a3bc58e
DS
9168 nbr = zvni_neigh_lookup(zvni, &nbr->ip);
9169 if (!nbr)
979777b2 9170 return 0;
c80a972c
CS
9171
9172 if (IS_ZEBRA_DEBUG_VXLAN)
9173 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9174 __PRETTY_FUNCTION__,
9175 prefix_mac2str(&nbr->emac, buf1, sizeof(buf1)),
9176 ipaddr2str(&nbr->ip, buf2, sizeof(buf2)),
9177 nbr->flags,
9178 nbr->dad_count, zvni->vni);
9179
9180 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
9181 nbr->dad_count = 0;
9182 nbr->detect_start_time.tv_sec = 0;
9183 nbr->detect_start_time.tv_usec = 0;
9184 nbr->dad_dup_detect_time = 0;
9185 nbr->dad_ip_auto_recovery_timer = NULL;
9186
9187 /* Send to BGP */
9188 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
9189 zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip, &nbr->emac,
9190 nbr->flags, nbr->loc_seq);
9191 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
9192 zvni_neigh_install(zvni, nbr);
9193 }
9194
c80a972c
CS
9195 return 0;
9196}
9197
9198static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
9199{
9200 struct zebra_vrf *zvrf = NULL;
9201 zebra_mac_t *mac = NULL;
9202 zebra_vni_t *zvni = NULL;
9203 struct listnode *node = NULL;
9204 zebra_neigh_t *nbr = NULL;
9205 char buf[ETHER_ADDR_STRLEN];
9206
9207 mac = THREAD_ARG(t);
9208
9209 /* since this is asynchronous we need sanity checks*/
8a3bc58e
DS
9210 zvrf = vrf_info_lookup(mac->zvni->vrf_id);
9211 if (!zvrf)
979777b2 9212 return 0;
c80a972c
CS
9213
9214 zvni = zvni_lookup(mac->zvni->vni);
9215 if (!zvni)
979777b2 9216 return 0;
c80a972c 9217
8a3bc58e
DS
9218 mac = zvni_mac_lookup(zvni, &mac->macaddr);
9219 if (!mac)
979777b2 9220 return 0;
c80a972c
CS
9221
9222 if (IS_ZEBRA_DEBUG_VXLAN)
9223 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9224 __PRETTY_FUNCTION__,
9225 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
9226 mac->flags,
9227 mac->dad_count,
9228 listcount(mac->neigh_list));
9229
9230 /* Remove all IPs as duplicate associcated with this MAC */
9231 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
a4445ece 9232 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
c80a972c
CS
9233 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
9234 ZEBRA_NEIGH_SET_INACTIVE(nbr);
9235 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
9236 zvni_neigh_install(zvni, nbr);
9237 }
9238
9239 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
9240 nbr->dad_count = 0;
9241 nbr->detect_start_time.tv_sec = 0;
9242 nbr->dad_dup_detect_time = 0;
9243 }
9244
9245 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
9246 mac->dad_count = 0;
9247 mac->detect_start_time.tv_sec = 0;
9248 mac->detect_start_time.tv_usec = 0;
9249 mac->dad_dup_detect_time = 0;
9250 mac->dad_mac_auto_recovery_timer = NULL;
9251
9252 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
9253 /* Inform to BGP */
9254 if (zvni_mac_send_add_to_client(zvni->vni, &mac->macaddr,
9255 mac->flags, mac->loc_seq))
9256 return -1;
9257
9258 /* Process all neighbors associated with this MAC. */
9259 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
9260
9261 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
9262 zvni_process_neigh_on_remote_mac_add(zvni, mac);
9263
9264 /* Install the entry. */
9265 zvni_mac_install(zvni, mac);
9266 }
9267
c80a972c
CS
9268 return 0;
9269}