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