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