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