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