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