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