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