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