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