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