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