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