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