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