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