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