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