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