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