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