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