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