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