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