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