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