]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
Merge pull request #1664 from chiragshah6/ospfv3_dev
[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
7cf15b25 1169 zclient_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
7cf15b25 2534 zclient_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
7cf15b25 2568 zclient_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
523cafc4 2628 /*
2629 * we need to associate with SVI.
b7cfce93 2630 * we can associate with svi-if only after association
523cafc4 2631 * with vxlan-intf is complete
2632 */
b7cfce93
MK
2633 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
2634
2635 if (is_l3vni_oper_up(zl3vni))
2636 zebra_vxlan_process_l3vni_oper_up(zl3vni);
2637
2638 } else {
2639 zebra_vni_t *zvni = NULL;
2640 zebra_l3vni_t *zl3vni = NULL;
2641 struct interface *vlan_if = NULL;
2642
2643 if (IS_ZEBRA_DEBUG_VXLAN)
2644 zlog_debug(
2645 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2646 ifp->name, ifp->ifindex, vni,
2647 inet_ntoa(vxl->vtep_ip));
2648
2649 /* VNI hash entry is not expected to exist. */
2650 zvni = zvni_lookup(vni);
2651 if (zvni) {
2652 zlog_err(
2653 "VNI hash already present for IF %s(%u) L2-VNI %u",
2654 ifp->name, ifp->ifindex, vni);
2655 continue;
2656 }
2657
2658 zvni = zvni_add(vni);
2659 if (!zvni) {
2660 zlog_err(
2661 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2662 ifp->name, ifp->ifindex, vni);
2663 return;
2664 }
2665
2666 zvni->local_vtep_ip = vxl->vtep_ip;
2667 zvni->vxlan_if = ifp;
2668 vlan_if = zvni_map_to_svi(vxl->access_vlan,
2669 zif->brslave_info.br_if);
2670 if (vlan_if) {
2671 zvni->vrf_id = vlan_if->vrf_id;
2672 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
2673 if (zl3vni)
2674 listnode_add_sort(zl3vni->l2vnis, zvni);
2675 }
2676
2677
2678 /* Inform BGP if intf is up and mapped to bridge. */
2679 if (if_is_operative(ifp) && zif->brslave_info.br_if)
2680 zvni_send_add_to_client(zvni);
2681 }
d62a17ae 2682 }
2232a77c 2683}
2684
2685/*
2686 * See if remote VTEP matches with prefix.
2687 */
d62a17ae 2688static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
2232a77c 2689{
d62a17ae 2690 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
2232a77c 2691}
2692
2693/*
2694 * Locate remote VTEP in VNI hash table.
2695 */
d62a17ae 2696static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2697{
d62a17ae 2698 zebra_vtep_t *zvtep;
2232a77c 2699
d62a17ae 2700 if (!zvni)
2701 return NULL;
2232a77c 2702
d62a17ae 2703 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2704 if (zvni_vtep_match(vtep_ip, zvtep))
2705 break;
2706 }
2232a77c 2707
d62a17ae 2708 return zvtep;
2232a77c 2709}
2710
2711/*
2712 * Add remote VTEP to VNI hash table.
2713 */
d62a17ae 2714static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2715{
d62a17ae 2716 zebra_vtep_t *zvtep;
2232a77c 2717
d62a17ae 2718 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
2719 if (!zvtep) {
2720 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni->vni);
2721 return NULL;
2722 }
2232a77c 2723
d62a17ae 2724 zvtep->vtep_ip = *vtep_ip;
2232a77c 2725
d62a17ae 2726 if (zvni->vteps)
2727 zvni->vteps->prev = zvtep;
2728 zvtep->next = zvni->vteps;
2729 zvni->vteps = zvtep;
2232a77c 2730
d62a17ae 2731 return zvtep;
2232a77c 2732}
2733
2734/*
2735 * Remove remote VTEP from VNI hash table.
2736 */
d62a17ae 2737static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
2232a77c 2738{
d62a17ae 2739 if (zvtep->next)
2740 zvtep->next->prev = zvtep->prev;
2741 if (zvtep->prev)
2742 zvtep->prev->next = zvtep->next;
2743 else
2744 zvni->vteps = zvtep->next;
2232a77c 2745
d62a17ae 2746 zvtep->prev = zvtep->next = NULL;
2747 XFREE(MTYPE_ZVNI_VTEP, zvtep);
2232a77c 2748
d62a17ae 2749 return 0;
2232a77c 2750}
2751
2752/*
2753 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2754 * uninstall from kernel if asked to.
2755 */
d62a17ae 2756static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
2232a77c 2757{
d62a17ae 2758 zebra_vtep_t *zvtep, *zvtep_next;
2232a77c 2759
d62a17ae 2760 if (!zvni)
2761 return -1;
2232a77c 2762
d62a17ae 2763 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
2764 zvtep_next = zvtep->next;
2765 if (uninstall)
2766 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
2767 zvni_vtep_del(zvni, zvtep);
2768 }
2232a77c 2769
d62a17ae 2770 return 0;
2232a77c 2771}
2772
2773/*
2774 * Install remote VTEP into the kernel.
2775 */
d62a17ae 2776static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2777{
d62a17ae 2778 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2779}
2780
2781/*
2782 * Uninstall remote VTEP from the kernel.
2783 */
d62a17ae 2784static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2785{
d62a17ae 2786 if (!zvni->vxlan_if) {
2787 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2788 zvni->vni, zvni);
2789 return -1;
2790 }
2232a77c 2791
d62a17ae 2792 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2793}
2794
2795/*
2796 * Cleanup VNI/VTEP and update kernel
2797 */
d62a17ae 2798static void zvni_cleanup_all(struct hash_backet *backet, void *zvrf)
2232a77c 2799{
b7cfce93
MK
2800 zebra_vni_t *zvni = NULL;
2801 zebra_l3vni_t *zl3vni = NULL;
2232a77c 2802
d62a17ae 2803 zvni = (zebra_vni_t *)backet->data;
2804 if (!zvni)
2805 return;
2232a77c 2806
b7cfce93
MK
2807 /* remove from l3-vni list */
2808 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
2809 if (zl3vni)
2810 listnode_delete(zl3vni->l2vnis, zvni);
2811
d62a17ae 2812 /* Free up all neighbors and MACs, if any. */
2853fed6 2813 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
2814 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
2232a77c 2815
d62a17ae 2816 /* Free up all remote VTEPs, if any. */
2817 zvni_vtep_del_all(zvni, 1);
2232a77c 2818
d62a17ae 2819 /* Delete the hash entry. */
2853fed6 2820 zvni_del(zvni);
2232a77c 2821}
2822
655b04d1
MK
2823/* cleanup L3VNI */
2824static void zl3vni_cleanup_all(struct hash_backet *backet,
2825 void *args)
2826{
2827 zebra_l3vni_t *zl3vni = NULL;
2828
2829 zl3vni = (zebra_l3vni_t *)backet->data;
2830 if (!zl3vni)
2831 return;
2832
2833 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2834}
2835
6134fd82 2836static int is_host_present_in_host_list(struct list *list,
2837 struct prefix *host)
2838{
2839 struct listnode *node = NULL;
2840 struct prefix *p = NULL;
2841
2842 for (ALL_LIST_ELEMENTS_RO(list, node, p)) {
2843 if (prefix_same(p, host))
2844 return 1;
2845 }
2846 return 0;
2847}
2848
2849static void host_list_add_host(struct list *list,
2850 struct prefix *host)
2851{
2852 struct prefix *p = NULL;
2853
2854 p = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct prefix));
2855 memcpy(p, host, sizeof(struct prefix));
2856
2857 listnode_add_sort(list, p);
2858}
2859
2860static void host_list_delete_host(struct list *list,
2861 struct prefix *host)
2862{
2863 struct listnode *node = NULL, *nnode = NULL, *node_to_del = NULL;
2864 struct prefix *p = NULL;
2865
2866 for (ALL_LIST_ELEMENTS(list, node, nnode, p)) {
2867 if (prefix_same(p, host)) {
2868 XFREE(MTYPE_HOST_PREFIX, p);
2869 node_to_del = node;
2870 }
2871 }
2872
2873 if (node_to_del)
2874 list_delete_node(list, node_to_del);
2875}
2876
b7cfce93
MK
2877/*
2878 * Look up MAC hash entry.
2879 */
2dbad57f 2880static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
b7cfce93
MK
2881 struct ethaddr *rmac)
2882{
2883 zebra_mac_t tmp;
2884 zebra_mac_t *pmac;
2885
2886 memset(&tmp, 0, sizeof(tmp));
2887 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
2888 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
2232a77c 2889
b7cfce93 2890 return pmac;
2dbad57f 2891}
2232a77c 2892
cec2e17d 2893/*
b7cfce93 2894 * Callback to allocate RMAC hash entry.
cec2e17d 2895 */
2dbad57f 2896static void *zl3vni_rmac_alloc(void *p)
d62a17ae 2897{
b7cfce93
MK
2898 const zebra_mac_t *tmp_rmac = p;
2899 zebra_mac_t *zrmac;
d62a17ae 2900
b7cfce93
MK
2901 zrmac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
2902 *zrmac = *tmp_rmac;
d62a17ae 2903
b7cfce93 2904 return ((void *)zrmac);
2dbad57f 2905}
cd233079 2906
b7cfce93
MK
2907/*
2908 * Add RMAC entry to l3-vni
2909 */
2dbad57f 2910static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni,
b7cfce93
MK
2911 struct ethaddr *rmac)
2912{
2913 zebra_mac_t tmp_rmac;
2914 zebra_mac_t *zrmac = NULL;
d62a17ae 2915
b7cfce93
MK
2916 memset(&tmp_rmac, 0, sizeof(zebra_mac_t));
2917 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
2918 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
2919 assert(zrmac);
d62a17ae 2920
6134fd82 2921 zrmac->host_list = list_new();
2922 zrmac->host_list->cmp = (int (*)(void *, void *))prefix_cmp;
b7cfce93 2923
2dbad57f 2924 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
2925 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
2926
b7cfce93 2927 return zrmac;
2dbad57f 2928}
cec2e17d 2929
2930/*
b7cfce93 2931 * Delete MAC entry.
cec2e17d 2932 */
2dbad57f 2933static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni,
b7cfce93 2934 zebra_mac_t *zrmac)
cec2e17d 2935{
b7cfce93 2936 zebra_mac_t *tmp_rmac;
cd233079 2937
55aabf6f 2938 if (zrmac->host_list)
bb7a24ab 2939 list_delete_and_null(&zrmac->host_list);
55aabf6f 2940 zrmac->host_list = NULL;
cd233079 2941
b7cfce93
MK
2942 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
2943 if (tmp_rmac)
2944 XFREE(MTYPE_MAC, tmp_rmac);
cd233079 2945
b7cfce93 2946 return 0;
2dbad57f 2947}
cec2e17d 2948
2949/*
b7cfce93 2950 * Install remote RMAC into the kernel.
cec2e17d 2951 */
2dbad57f 2952static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni,
b7cfce93 2953 zebra_mac_t *zrmac)
cec2e17d 2954{
b7cfce93
MK
2955 struct zebra_if *zif = NULL;
2956 struct zebra_l2info_vxlan *vxl = NULL;
cec2e17d 2957
b7cfce93
MK
2958 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE)) ||
2959 !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
2960 return 0;
2961
2962 zif = zl3vni->vxlan_if->info;
2963 if (!zif)
2964 return -1;
2965
2966 vxl = &zif->l2info.vxl;
2967
2968 return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
2969 &zrmac->macaddr,
2970 zrmac->fwd_info.r_vtep_ip, 0);
2dbad57f 2971}
b7cfce93
MK
2972
2973/*
2974 * Uninstall remote RMAC from the kernel.
2975 */
2dbad57f 2976static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni,
b7cfce93
MK
2977 zebra_mac_t *zrmac)
2978{
2979 char buf[ETHER_ADDR_STRLEN];
2980 struct zebra_if *zif = NULL;
2981 struct zebra_l2info_vxlan *vxl = NULL;
2982
2983 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE)) ||
2984 !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
2985 return 0;
2986
2987 if (!zl3vni->vxlan_if) {
523cafc4 2988 zlog_err(
2989 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
b7cfce93
MK
2990 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
2991 zl3vni->vni, zl3vni);
2992 return -1;
2993 }
2994
2995 zif = zl3vni->vxlan_if->info;
2996 if (!zif)
2997 return -1;
2998
2999 vxl = &zif->l2info.vxl;
3000
3001 return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
3002 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
2dbad57f 3003}
3004
3005/* handle rmac add */
6134fd82 3006static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni,
3007 struct ethaddr *rmac,
3008 struct ipaddr *vtep_ip,
3009 struct prefix *host_prefix)
2dbad57f 3010{
3011 char buf[ETHER_ADDR_STRLEN];
3012 char buf1[INET6_ADDRSTRLEN];
3013 zebra_mac_t *zrmac = NULL;
3014
3015 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3016 if (!zrmac) {
3017
3018 zrmac = zl3vni_rmac_add(zl3vni, rmac);
3019 if (!zrmac) {
3020 zlog_warn(
3021 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3022 prefix_mac2str(rmac, buf,
3023 sizeof(buf)),
3024 zl3vni->vni, ipaddr2str(vtep_ip, buf1,
3025 sizeof(buf1)));
3026 return -1;
3027 }
3028 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
3029 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
3030
3031 /* install rmac in kernel */
3032 zl3vni_rmac_install(zl3vni, zrmac);
3033 }
6134fd82 3034
3035 if (!is_host_present_in_host_list(zrmac->host_list, host_prefix))
3036 host_list_add_host(zrmac->host_list, host_prefix);
2dbad57f 3037 return 0;
3038}
3039
3040
3041/* handle rmac delete */
6134fd82 3042static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni,
3043 struct ethaddr *rmac,
3044 struct prefix *host_prefix)
2dbad57f 3045{
3046 zebra_mac_t *zrmac = NULL;
3047
3048 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3049 if (!zrmac)
3050 return -1;
3051
6134fd82 3052 host_list_delete_host(zrmac->host_list, host_prefix);
3053 if (list_isempty(zrmac->host_list)) {
2dbad57f 3054
3055 /* uninstall from kernel */
3056 zl3vni_rmac_uninstall(zl3vni, zrmac);
3057
3058 /* del the rmac entry */
3059 zl3vni_rmac_del(zl3vni, zrmac);
3060 }
3061 return 0;
3062}
b7cfce93
MK
3063
3064/*
3065 * Look up nh hash entry on a l3-vni.
3066 */
2dbad57f 3067static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni,
b7cfce93
MK
3068 struct ipaddr *ip)
3069{
3070 zebra_neigh_t tmp;
3071 zebra_neigh_t *n;
3072
3073 memset(&tmp, 0, sizeof(tmp));
3074 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
3075 n = hash_lookup(zl3vni->nh_table, &tmp);
3076
3077 return n;
2dbad57f 3078}
b7cfce93
MK
3079
3080
3081/*
3082 * Callback to allocate NH hash entry on L3-VNI.
3083 */
2dbad57f 3084static void *zl3vni_nh_alloc(void *p)
b7cfce93
MK
3085{
3086 const zebra_neigh_t *tmp_n = p;
3087 zebra_neigh_t *n;
3088
3089 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
3090 *n = *tmp_n;
3091
3092 return ((void *)n);
2dbad57f 3093}
b7cfce93
MK
3094
3095/*
3096 * Add neighbor entry.
3097 */
2dbad57f 3098static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni,
b7cfce93
MK
3099 struct ipaddr *ip,
3100 struct ethaddr *mac)
3101{
3102 zebra_neigh_t tmp_n;
3103 zebra_neigh_t *n = NULL;
3104
3105 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
3106 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
3107 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
3108 assert(n);
3109
6134fd82 3110 n->host_list = list_new();
3111 n->host_list->cmp = (int (*)(void *, void *))prefix_cmp;
3112
b7cfce93 3113 memcpy(&n->emac, mac, ETH_ALEN);
2dbad57f 3114 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3115 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
b7cfce93
MK
3116
3117 return n;
2dbad57f 3118}
b7cfce93
MK
3119
3120/*
3121 * Delete neighbor entry.
3122 */
2dbad57f 3123static int zl3vni_nh_del(zebra_l3vni_t *zl3vni,
b7cfce93
MK
3124 zebra_neigh_t *n)
3125{
3126 zebra_neigh_t *tmp_n;
3127
55aabf6f 3128 if (n->host_list)
bb7a24ab 3129 list_delete_and_null(&n->host_list);
55aabf6f
MK
3130 n->host_list = NULL;
3131
b7cfce93
MK
3132 tmp_n = hash_release(zl3vni->nh_table, n);
3133 if (tmp_n)
3134 XFREE(MTYPE_NEIGH, tmp_n);
3135
3136 return 0;
2dbad57f 3137}
b7cfce93
MK
3138
3139/*
3140 * Install remote nh as neigh into the kernel.
3141 */
2dbad57f 3142static int zl3vni_nh_install(zebra_l3vni_t *zl3vni,
b7cfce93
MK
3143 zebra_neigh_t *n)
3144{
3145 if (!is_l3vni_oper_up(zl3vni))
3146 return -1;
3147
3148 if (!(n->flags & ZEBRA_NEIGH_REMOTE) ||
3149 !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
3150 return 0;
3151
3152 return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac);
2dbad57f 3153}
b7cfce93
MK
3154
3155/*
3156 * Uninstall remote nh from the kernel.
3157 */
2dbad57f 3158static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni,
b7cfce93
MK
3159 zebra_neigh_t *n)
3160{
3161 if (!is_l3vni_oper_up(zl3vni))
3162 return -1;
3163
3164 if (!(n->flags & ZEBRA_NEIGH_REMOTE) ||
3165 !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
3166 return 0;
3167
3168 return kernel_del_neigh(zl3vni->svi_if, &n->ip);
2dbad57f 3169}
3170
3171/* add remote vtep as a neigh entry */
6134fd82 3172static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni,
3173 struct ipaddr *vtep_ip,
3174 struct ethaddr *rmac,
3175 struct prefix *host_prefix)
2dbad57f 3176{
3177 char buf[ETHER_ADDR_STRLEN];
3178 char buf1[INET6_ADDRSTRLEN];
3179 zebra_neigh_t *nh = NULL;
3180
3181 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
3182 if (!nh) {
3183 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
3184 if (!nh) {
3185
3186 zlog_warn(
3187 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3188 ipaddr2str(vtep_ip, buf1,
3189 sizeof(buf1)),
3190 prefix_mac2str(rmac, buf,
3191 sizeof(buf)),
3192 zl3vni->vni);
3193 return -1;
3194 }
3195
3196 /* install the nh neigh in kernel */
3197 zl3vni_nh_install(zl3vni, nh);
3198 }
6134fd82 3199
3200 if (!is_host_present_in_host_list(nh->host_list, host_prefix))
3201 host_list_add_host(nh->host_list, host_prefix);
3202
2dbad57f 3203 return 0;
3204}
3205
3206/* handle nh neigh delete */
6134fd82 3207static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni,
3208 struct ipaddr *vtep_ip,
3209 struct prefix *host_prefix)
2dbad57f 3210{
3211 zebra_neigh_t *nh = NULL;
3212
3213 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
3214 if (!nh)
3215 return -1;
3216
6134fd82 3217 host_list_delete_host(nh->host_list, host_prefix);
3218 if (list_isempty(nh->host_list)) {
2dbad57f 3219
3220 /* uninstall from kernel */
3221 zl3vni_nh_uninstall(zl3vni, nh);
3222
3223 /* delete the nh entry */
3224 zl3vni_nh_del(zl3vni, nh);
3225 }
3226
3227 return 0;
3228}
b7cfce93 3229
3bcbba10 3230/* handle neigh update from kernel - the only thing of interest is to
3231 * readd stale entries.
3232 */
3233static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni,
523cafc4 3234 struct ipaddr *ip, u_int16_t state)
3bcbba10 3235{
c05a738b 3236#ifdef GNU_LINUX
3bcbba10 3237 zebra_neigh_t *n = NULL;
3238
3239 n = zl3vni_nh_lookup(zl3vni, ip);
3240 if (!n)
3241 return 0;
3242
3243 /* all next hop neigh are remote and installed by frr.
3244 * If the kernel has aged this entry, re-install.
3245 */
3246 if (state & NUD_STALE)
3247 zl3vni_nh_install(zl3vni, n);
c05a738b 3248#endif
3bcbba10 3249 return 0;
3250}
3251
8c9b80b9
MK
3252/* handle neigh delete from kernel */
3253static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni,
3254 struct ipaddr *ip)
3255{
3256 zebra_neigh_t *n = NULL;
3257
3258 n = zl3vni_nh_lookup(zl3vni, ip);
3259 if (!n)
3260 return 0;
3261
3262 /* all next hop neigh are remote and installed by frr.
3263 * If we get an age out notification for these neigh entries, we have to
523cafc4 3264 * install it back
3265 */
8c9b80b9
MK
3266 zl3vni_nh_install(zl3vni, n);
3267
3268 return 0;
3269}
3270
b7cfce93
MK
3271/*
3272 * Hash function for L3 VNI.
3273 */
3274static unsigned int l3vni_hash_keymake(void *p)
3275{
3276 const zebra_l3vni_t *zl3vni = p;
3277
3278 return jhash_1word(zl3vni->vni, 0);
3279}
3280
3281/*
3282 * Compare 2 L3 VNI hash entries.
3283 */
3284static int l3vni_hash_cmp(const void *p1, const void *p2)
3285{
3286 const zebra_l3vni_t *zl3vni1 = p1;
3287 const zebra_l3vni_t *zl3vni2 = p2;
3288
3289 return (zl3vni1->vni == zl3vni2->vni);
3290}
3291
3292/*
3293 * Callback to allocate L3 VNI hash entry.
3294 */
3295static void *zl3vni_alloc(void *p)
3296{
3297 zebra_l3vni_t *zl3vni = NULL;
3298 const zebra_l3vni_t *tmp_l3vni = p;
3299
3300 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(zebra_l3vni_t));
3301 zl3vni->vni = tmp_l3vni->vni;
3302 return ((void *)zl3vni);
3303}
3304
3305/*
3306 * Look up L3 VNI hash entry.
3307 */
3308static zebra_l3vni_t *zl3vni_lookup(vni_t vni)
3309{
3310 struct zebra_ns *zns;
3311 zebra_l3vni_t tmp_l3vni;
3312 zebra_l3vni_t *zl3vni = NULL;
3313
3314 zns = zebra_ns_lookup(NS_DEFAULT);
3315 assert(zns);
3316 memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t));
3317 tmp_l3vni.vni = vni;
3318 zl3vni = hash_lookup(zns->l3vni_table, &tmp_l3vni);
3319
3320 return zl3vni;
3321}
3322
3323/*
3324 * Add L3 VNI hash entry.
3325 */
3326static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
3327{
3328 zebra_l3vni_t tmp_zl3vni;
3329 struct zebra_ns *zns = NULL;
3330 zebra_l3vni_t *zl3vni = NULL;
3331
3332 zns = zebra_ns_lookup(NS_DEFAULT);
3333 assert(zns);
3334
3335 memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t));
3336 tmp_zl3vni.vni = vni;
3337
3338 zl3vni = hash_get(zns->l3vni_table, &tmp_zl3vni, zl3vni_alloc);
3339 assert(zl3vni);
3340
3341 zl3vni->vrf_id = vrf_id;
3342 zl3vni->svi_if = NULL;
3343 zl3vni->vxlan_if = NULL;
3344 zl3vni->l2vnis = list_new();
3345 zl3vni->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp;
3346
3347 /* Create hash table for remote RMAC */
3348 zl3vni->rmac_table =
3349 hash_create(mac_hash_keymake, mac_cmp,
3350 "Zebra L3-VNI RMAC-Table");
3351
3352 /* Create hash table for neighbors */
3353 zl3vni->nh_table = hash_create(neigh_hash_keymake, neigh_cmp,
3354 "Zebra L3-VNI next-hop table");
3355
3356 return zl3vni;
3357}
3358
3359/*
3360 * Delete L3 VNI hash entry.
3361 */
3362static int zl3vni_del(zebra_l3vni_t *zl3vni)
3363{
3364 struct zebra_ns *zns;
3365 zebra_l3vni_t *tmp_zl3vni;
3366
3367 zns = zebra_ns_lookup(NS_DEFAULT);
3368 assert(zns);
3369
3370 /* free the list of l2vnis */
3371 list_delete_and_null(&zl3vni->l2vnis);
3372 zl3vni->l2vnis = NULL;
3373
3374 /* Free the rmac table */
3375 hash_free(zl3vni->rmac_table);
3376 zl3vni->rmac_table = NULL;
3377
3378 /* Free the nh table */
3379 hash_free(zl3vni->nh_table);
3380 zl3vni->nh_table = NULL;
3381
3382 /* Free the VNI hash entry and allocated memory. */
3383 tmp_zl3vni = hash_release(zns->l3vni_table, zl3vni);
3384 if (tmp_zl3vni)
3385 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
3386
3387 return 0;
3388}
3389
3390static int is_vni_l3(vni_t vni)
3391{
3392 zebra_l3vni_t *zl3vni = NULL;
3393
3394 zl3vni = zl3vni_lookup(vni);
3395 if (zl3vni)
3396 return 1;
3397 return 0;
3398}
3399
3400static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
3401{
3402 struct zebra_ns *zns = NULL;
3403 struct route_node *rn = NULL;
3404 struct interface *ifp = NULL;
3405
3406 /* loop through all vxlan-interface */
3407 zns = zebra_ns_lookup(NS_DEFAULT);
3408 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3409
3410 struct zebra_if *zif = NULL;
3411 struct zebra_l2info_vxlan *vxl = NULL;
3412
3413 ifp = (struct interface *)rn->info;
3414 if (!ifp)
3415 continue;
3416
3417 zif = ifp->info;
3418 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3419 continue;
3420
3421 vxl = &zif->l2info.vxl;
b67a60d2 3422 if (vxl->vni == zl3vni->vni) {
3423 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 3424 return ifp;
b67a60d2 3425 }
b7cfce93
MK
3426 }
3427
3428 return NULL;
3429}
3430
3431static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
3432{
3433 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
3434 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
3435
3436 if (!zl3vni->vxlan_if)
3437 return NULL;
3438
3439 zif = zl3vni->vxlan_if->info;
3440 if (!zif)
3441 return NULL;
3442
3443 vxl = &zif->l2info.vxl;
3444
3445 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
3446}
3447
3448static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
3449{
3450 struct zebra_vrf *zvrf = NULL;
3451
3452 zvrf = zebra_vrf_lookup_by_id(vrf_id);
3453 if (!zvrf)
3454 return NULL;
3455
3456 return zl3vni_lookup(zvrf->l3vni);
3457}
3458
3459/*
3460 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3461 * neighbor notifications, to see if they are of interest.
3462 */
3463static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp,
3464 struct interface *br_if)
3465{
3466 int found = 0;
3467 vlanid_t vid = 0;
3468 u_char bridge_vlan_aware = 0;
3469 zebra_l3vni_t *zl3vni = NULL;
3470 struct zebra_ns *zns = NULL;
3471 struct route_node *rn = NULL;
3472 struct zebra_if *zif = NULL;
3473 struct interface *tmp_if = NULL;
3474 struct zebra_l2info_bridge *br = NULL;
3475 struct zebra_l2info_vxlan *vxl = NULL;
3476
3477 if (!br_if)
3478 return NULL;
3479
3480 /* Make sure the linked interface is a bridge. */
3481 if (!IS_ZEBRA_IF_BRIDGE(br_if))
3482 return NULL;
3483
3484 /* Determine if bridge is VLAN-aware or not */
3485 zif = br_if->info;
3486 assert(zif);
3487 br = &zif->l2info.br;
3488 bridge_vlan_aware = br->vlan_aware;
3489 if (bridge_vlan_aware) {
3490 struct zebra_l2info_vlan *vl;
3491
3492 if (!IS_ZEBRA_IF_VLAN(ifp))
3493 return NULL;
3494
3495 zif = ifp->info;
3496 assert(zif);
3497 vl = &zif->l2info.vl;
3498 vid = vl->vid;
3499 }
3500
3501 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3502 /* TODO: Optimize with a hash. */
3503 zns = zebra_ns_lookup(NS_DEFAULT);
3504 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3505 tmp_if = (struct interface *)rn->info;
3506 if (!tmp_if)
3507 continue;
3508 zif = tmp_if->info;
3509 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3510 continue;
3511 if (!if_is_operative(tmp_if))
3512 continue;
3513 vxl = &zif->l2info.vxl;
3514
3515 if (zif->brslave_info.br_if != br_if)
3516 continue;
3517
3518 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3519 found = 1;
3520 break;
3521 }
3522 }
3523
3524 if (!found)
3525 return NULL;
3526
3527 zl3vni = zl3vni_lookup(vxl->vni);
3528 return zl3vni;
3529}
3530
3531/*
3532 * Inform BGP about l3-vni.
3533 */
3534static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
3535{
3536 struct stream *s = NULL;
3537 struct zserv *client = NULL;
3538 struct ethaddr rmac;
3539 char buf[ETHER_ADDR_STRLEN];
3540
6f3a2003 3541 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
3542 /* BGP may not be running. */
3543 if (!client)
3544 return 0;
3545
3546 /* get the rmac */
3547 memset(&rmac, 0, sizeof(struct ethaddr));
3548 zl3vni_get_rmac(zl3vni, &rmac);
3549
3550 s = client->obuf;
3551 stream_reset(s);
3552
7cf15b25 3553 zclient_create_header(s, ZEBRA_L3VNI_ADD,
b7cfce93
MK
3554 zl3vni_vrf_id(zl3vni));
3555 stream_putl(s, zl3vni->vni);
3556 stream_put(s, &rmac, sizeof(struct ethaddr));
b67a60d2 3557 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
b7cfce93
MK
3558
3559 /* Write packet size. */
3560 stream_putw_at(s, 0, stream_get_endp(s));
3561
3562 if (IS_ZEBRA_DEBUG_VXLAN)
b67a60d2 3563 zlog_debug("Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s to %s",
b7cfce93
MK
3564 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
3565 prefix_mac2str(&rmac, buf, sizeof(buf)),
b67a60d2 3566 inet_ntoa(zl3vni->local_vtep_ip),
b7cfce93
MK
3567 zebra_route_string(client->proto));
3568
3569 client->l3vniadd_cnt++;
3570 return zebra_server_send_message(client);
3571}
3572
3573/*
3574 * Inform BGP about local l3-VNI deletion.
3575 */
3576static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
3577{
3578 struct stream *s = NULL;
3579 struct zserv *client = NULL;
3580
6f3a2003 3581 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
3582 /* BGP may not be running. */
3583 if (!client)
3584 return 0;
3585
3586 s = client->obuf;
3587 stream_reset(s);
3588
7cf15b25 3589 zclient_create_header(s, ZEBRA_L3VNI_DEL,
b7cfce93
MK
3590 zl3vni_vrf_id(zl3vni));
3591 stream_putl(s, zl3vni->vni);
3592
3593 /* Write packet size. */
3594 stream_putw_at(s, 0, stream_get_endp(s));
3595
3596 if (IS_ZEBRA_DEBUG_VXLAN)
3597 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s",
3598 zl3vni->vni,
3599 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
3600 zebra_route_string(client->proto));
3601
3602 client->l3vnidel_cnt++;
3603 return zebra_server_send_message(client);
3604}
3605
3606static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
3607{
3608 if (IS_ZEBRA_DEBUG_VXLAN)
655b04d1 3609 zlog_debug("L3-VNI %u is UP - send add to BGP",
b7cfce93
MK
3610 zl3vni->vni);
3611
3612 /* send l3vni add to BGP */
3613 zl3vni_send_add_to_client(zl3vni);
3614}
3615
3616static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni)
3617{
3618 if (IS_ZEBRA_DEBUG_VXLAN)
655b04d1 3619 zlog_debug("L3-VNI %u is Down - Send del to BGP",
b7cfce93
MK
3620 zl3vni->vni);
3621
3622 /* send l3-vni del to BGP*/
3623 zl3vni_send_del_to_client(zl3vni);
3624}
3625
3626static void zvni_add_to_l3vni_list(struct hash_backet *backet,
3627 void *ctxt)
3628{
3629 zebra_vni_t *zvni = (zebra_vni_t *) backet->data;
3630 zebra_l3vni_t *zl3vni = (zebra_l3vni_t *) ctxt;
3631
3632 if (zvni->vrf_id == zl3vni_vrf_id(zl3vni))
3633 listnode_add_sort(zl3vni->l2vnis, zvni);
3634}
3635
b7cfce93
MK
3636/*
3637 * handle transition of vni from l2 to l3 and vice versa
3638 */
3639static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf,
3640 vni_t vni, int add)
3641{
3642 zebra_vni_t *zvni = NULL;
3643
3644 /* There is a possibility that VNI notification was already received
3645 * from kernel and we programmed it as L2-VNI
3646 * In such a case we need to delete this L2-VNI first, so
3647 * that it can be reprogrammed as L3-VNI in the system. It is also
3648 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3649 * interface is still present in kernel. In this case to keep it
523cafc4 3650 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3651 */
b7cfce93
MK
3652 if (add) {
3653 /* Locate hash entry */
3654 zvni = zvni_lookup(vni);
3655 if (!zvni)
3656 return 0;
3657
3658 if (IS_ZEBRA_DEBUG_VXLAN)
3659 zlog_debug("Del L2-VNI %u - transition to L3-VNI",
3660 vni);
3661
3662 /* Delete VNI from BGP. */
3663 zvni_send_del_to_client(zvni->vni);
3664
3665 /* Free up all neighbors and MAC, if any. */
3666 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
3667 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
3668
3669 /* Free up all remote VTEPs, if any. */
3670 zvni_vtep_del_all(zvni, 0);
3671
3672 /* Delete the hash entry. */
3673 if (zvni_del(zvni)) {
3674 zlog_err("Failed to del VNI hash %p, VNI %u",
3675 zvni, zvni->vni);
3676 return -1;
3677 }
3678 } else {
3679 /* TODO_MITESH: This needs to be thought through. We don't have
3680 * enough information at this point to reprogram the vni as
3681 * l2-vni. One way is to store the required info in l3-vni and
523cafc4 3682 * used it solely for this purpose
3683 */
b7cfce93
MK
3684 }
3685
3686 return 0;
3687}
3688
5e06422c
MK
3689/* delete and uninstall rmac hash entry */
3690static void zl3vni_del_rmac_hash_entry(struct hash_backet *backet,
3691 void *ctx)
3692{
3693 zebra_mac_t *zrmac = NULL;
3694 zebra_l3vni_t *zl3vni = NULL;
3695
3696 zrmac = (zebra_mac_t *)backet->data;
3697 zl3vni = (zebra_l3vni_t *)ctx;
3698 zl3vni_rmac_uninstall(zl3vni, zrmac);
3699 zl3vni_rmac_del(zl3vni, zrmac);
3700}
3701
3702/* delete and uninstall nh hash entry */
3703static void zl3vni_del_nh_hash_entry(struct hash_backet *backet,
3704 void *ctx)
3705{
3706 zebra_neigh_t *n = NULL;
3707 zebra_l3vni_t *zl3vni = NULL;
3708
3709 n = (zebra_neigh_t *)backet->data;
3710 zl3vni = (zebra_l3vni_t *)ctx;
3711 zl3vni_nh_uninstall(zl3vni, n);
3712 zl3vni_nh_del(zl3vni, n);
3713}
3714
b7cfce93
MK
3715/* Public functions */
3716
2dbad57f 3717/* handle evpn route in vrf table */
3718void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
3719 struct ethaddr *rmac,
6134fd82 3720 struct ipaddr *vtep_ip,
3721 struct prefix *host_prefix)
2dbad57f 3722{
3723 zebra_l3vni_t *zl3vni = NULL;
3724
3725 zl3vni = zl3vni_from_vrf(vrf_id);
3726 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
3727 return;
3728
3729 /* add the next hop neighbor */
6134fd82 3730 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
2dbad57f 3731
3732 /* add the rmac */
6134fd82 3733 zl3vni_remote_rmac_add(zl3vni, rmac, vtep_ip, host_prefix);
2dbad57f 3734}
3735
3736/* handle evpn vrf route delete */
3737void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
3738 struct ethaddr *rmac,
6134fd82 3739 struct ipaddr *vtep_ip,
3740 struct prefix *host_prefix)
2dbad57f 3741{
3742 zebra_l3vni_t *zl3vni = NULL;
3743
3744 zl3vni = zl3vni_from_vrf(vrf_id);
5e06422c 3745 if (!zl3vni)
2dbad57f 3746 return;
3747
3748 /* delete the next hop entry */
6134fd82 3749 zl3vni_remote_nh_del(zl3vni, vtep_ip, host_prefix);
2dbad57f 3750
3751 /* delete the rmac entry */
6134fd82 3752 zl3vni_remote_rmac_del(zl3vni, rmac, host_prefix);
2dbad57f 3753}
3754
9aa741ea
MK
3755void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty,
3756 vni_t l3vni,
316f4ca4
MK
3757 struct ethaddr *rmac,
3758 u_char use_json)
9aa741ea
MK
3759{
3760 zebra_l3vni_t *zl3vni = NULL;
3761 zebra_mac_t *zrmac = NULL;
316f4ca4 3762 json_object *json = NULL;
9aa741ea 3763
316f4ca4
MK
3764 if (!is_evpn_enabled()) {
3765 if (use_json)
3766 vty_out(vty, "{}\n");
9aa741ea 3767 return;
316f4ca4
MK
3768 }
3769
3770 if (use_json)
3771 json = json_object_new_object();
9aa741ea
MK
3772
3773 zl3vni = zl3vni_lookup(l3vni);
3774 if (!zl3vni) {
316f4ca4
MK
3775 if (use_json)
3776 vty_out(vty, "{}\n");
3777 else
3778 vty_out(vty, "%% L3-VNI %u doesnt exist\n",
3779 l3vni);
9aa741ea
MK
3780 return;
3781 }
3782
3783 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3784 if (!zrmac) {
316f4ca4
MK
3785 if (use_json)
3786 vty_out(vty, "{}\n");
3787 else
3788 vty_out(vty,
3789 "%% Requested RMAC doesnt exist in L3-VNI %u",
3790 l3vni);
9aa741ea
MK
3791 return;
3792 }
3793
316f4ca4
MK
3794 zl3vni_print_rmac(zrmac, vty, json);
3795
3796 if (use_json) {
3797 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3798 json, JSON_C_TO_STRING_PRETTY));
3799 json_object_free(json);
3800 }
9aa741ea 3801}
2dbad57f 3802
b7cfce93
MK
3803void zebra_vxlan_print_rmacs_l3vni(struct vty *vty,
3804 vni_t l3vni,
3805 u_char use_json)
3806{
3807 zebra_l3vni_t *zl3vni;
3808 u_int32_t num_rmacs;
3809 struct rmac_walk_ctx wctx;
3810 json_object *json = NULL;
b7cfce93
MK
3811
3812 if (!is_evpn_enabled())
3813 return;
3814
3815 zl3vni = zl3vni_lookup(l3vni);
3816 if (!zl3vni) {
3817 if (use_json)
3818 vty_out(vty, "{}\n");
3819 else
3820 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
3821 return;
3822 }
3823 num_rmacs = hashcount(zl3vni->rmac_table);
3824 if (!num_rmacs)
3825 return;
3826
75223c9e 3827 if (use_json)
b7cfce93 3828 json = json_object_new_object();
b7cfce93
MK
3829
3830 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
3831 wctx.vty = vty;
75223c9e 3832 wctx.json = json;
b7cfce93
MK
3833 if (!use_json) {
3834 vty_out(vty,
3835 "Number of Remote RMACs known for this VNI: %u\n",
3836 num_rmacs);
3837 vty_out(vty, "%-17s %-21s %-6s\n", "MAC",
3838 "Remote VTEP", "Refcnt");
3839 } else
3840 json_object_int_add(json, "numRmacs", num_rmacs);
3841
3842 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
3843
3844 if (use_json) {
b7cfce93
MK
3845 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3846 json, JSON_C_TO_STRING_PRETTY));
3847 json_object_free(json);
3848 }
3849}
3850
3851void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty,
3852 u_char use_json)
3853{
3854 struct zebra_ns *zns = NULL;
b7cfce93 3855 json_object *json = NULL;
c0b4eaa4 3856 void *args[2];
b7cfce93
MK
3857
3858 if (!is_evpn_enabled()) {
3859 if (use_json)
3860 vty_out(vty, "{}\n");
3861 return;
3862 }
3863
3864 zns = zebra_ns_lookup(NS_DEFAULT);
c0b4eaa4
MK
3865 if (!zns) {
3866 if (use_json)
3867 vty_out(vty, "{}\n");
b7cfce93 3868 return;
c0b4eaa4 3869 }
b7cfce93
MK
3870
3871 if (use_json)
3872 json = json_object_new_object();
3873
c0b4eaa4
MK
3874 args[0] = vty;
3875 args[1] = json;
3876 hash_iterate(zns->l3vni_table,
3877 (void (*)(struct hash_backet *,
3878 void *))zl3vni_print_rmac_hash_all_vni,
3879 args);
b7cfce93
MK
3880
3881 if (use_json) {
3882 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3883 json, JSON_C_TO_STRING_PRETTY));
3884 json_object_free(json);
3885 }
3886}
3887
9aa741ea
MK
3888void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty,
3889 vni_t l3vni,
c0e519d3
MK
3890 struct ipaddr *ip,
3891 u_char use_json)
9aa741ea
MK
3892{
3893 zebra_l3vni_t *zl3vni = NULL;
3894 zebra_neigh_t *n = NULL;
c0e519d3 3895 json_object *json = NULL;
9aa741ea 3896
c0e519d3
MK
3897 if (!is_evpn_enabled()) {
3898 if (use_json)
3899 vty_out(vty, "{}\n");
9aa741ea 3900 return;
c0e519d3
MK
3901 }
3902
3903 if (use_json)
3904 json = json_object_new_object();
9aa741ea
MK
3905
3906 zl3vni = zl3vni_lookup(l3vni);
3907 if (!zl3vni) {
c0e519d3
MK
3908 if (use_json)
3909 vty_out(vty, "{}\n");
3910 else
3911 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
9aa741ea
MK
3912 return;
3913 }
3914
3915 n = zl3vni_nh_lookup(zl3vni, ip);
3916 if (!n) {
c0e519d3
MK
3917 if (use_json)
3918 vty_out(vty, "{}\n");
3919 else
3920 vty_out(vty,
3921 "%% Requested next-hop not present for L3-VNI %u",
3922 l3vni);
9aa741ea
MK
3923 return;
3924 }
3925
c0e519d3
MK
3926 zl3vni_print_nh(n, vty, json);
3927
3928 if (use_json) {
3929 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3930 json, JSON_C_TO_STRING_PRETTY));
3931 json_object_free(json);
3932 }
9aa741ea
MK
3933}
3934
b7cfce93
MK
3935void zebra_vxlan_print_nh_l3vni(struct vty *vty,
3936 vni_t l3vni,
3937 u_char use_json)
3938{
3939 u_int32_t num_nh;
2dbad57f 3940 struct nh_walk_ctx wctx;
b7cfce93 3941 json_object *json = NULL;
b7cfce93
MK
3942 zebra_l3vni_t *zl3vni = NULL;
3943
3944 if (!is_evpn_enabled())
3945 return;
3946
3947 zl3vni = zl3vni_lookup(l3vni);
3948 if (!zl3vni) {
3949 if (use_json)
3950 vty_out(vty, "{}\n");
3951 else
3952 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
3953 return;
3954 }
3955
3956 num_nh = hashcount(zl3vni->nh_table);
3957 if (!num_nh)
3958 return;
3959
9187f600 3960 if (use_json)
b7cfce93 3961 json = json_object_new_object();
b7cfce93 3962
2dbad57f 3963 wctx.vty = vty;
9187f600 3964 wctx.json = json;
b7cfce93
MK
3965 if (!use_json) {
3966 vty_out(vty,
3967 "Number of NH Neighbors known for this VNI: %u\n",
3968 num_nh);
2dbad57f 3969 vty_out(vty, "%-15s %-17s %6s\n", "IP",
b7cfce93
MK
3970 "RMAC", "Refcnt");
3971 } else
3972 json_object_int_add(json, "numNh", num_nh);
3973
3974 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
3975
3976 if (use_json) {
b7cfce93
MK
3977 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3978 json, JSON_C_TO_STRING_PRETTY));
3979 json_object_free(json);
3980 }
3981}
3982
3983void zebra_vxlan_print_nh_all_l3vni(struct vty *vty,
3984 u_char use_json)
3985{
2dbad57f 3986 struct zebra_ns *zns = NULL;
2dbad57f 3987 json_object *json = NULL;
32798965 3988 void *args[2];
2dbad57f 3989
3990 if (!is_evpn_enabled()) {
3991 if (use_json)
3992 vty_out(vty, "{}\n");
3993 return;
3994 }
3995
3996 zns = zebra_ns_lookup(NS_DEFAULT);
3997 if (!zns)
3998 return;
3999
4000 if (use_json)
4001 json = json_object_new_object();
4002
32798965
MK
4003 args[0] = vty;
4004 args[1] = json;
4005 hash_iterate(zns->l3vni_table,
4006 (void (*)(struct hash_backet *,
4007 void *))zl3vni_print_nh_hash_all_vni,
4008 args);
2dbad57f 4009
4010 if (use_json) {
4011 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4012 json, JSON_C_TO_STRING_PRETTY));
4013 json_object_free(json);
4014 }
b7cfce93
MK
4015 return;
4016}
4017
4018/*
4019 * Display L3 VNI information (VTY command handler).
4020 */
4021void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, u_char use_json)
4022{
4023 void *args[2];
4024 json_object *json = NULL;
4025 zebra_l3vni_t *zl3vni = NULL;
4026
b2ee5a13
MK
4027 if (!is_evpn_enabled()) {
4028 if (use_json)
4029 vty_out(vty, "{}\n");
b7cfce93 4030 return;
b2ee5a13 4031 }
b7cfce93
MK
4032
4033 zl3vni = zl3vni_lookup(vni);
4034 if (!zl3vni) {
4035 if (use_json)
4036 vty_out(vty, "{}\n");
4037 else
4038 vty_out(vty, "%% VNI %u does not exist\n", vni);
4039 return;
4040 }
4041
4042 if (use_json)
4043 json = json_object_new_object();
4044
b2ee5a13
MK
4045 args[0] = vty;
4046 args[1] = json;
b7cfce93
MK
4047 zl3vni_print(zl3vni, (void *)args);
4048
4049 if (use_json) {
4050 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4051 json, JSON_C_TO_STRING_PRETTY));
4052 json_object_free(json);
4053 }
4054}
4055
4056/*
4057 * Display L3 VNI hash table (VTY command handler).
4058 */
4059void zebra_vxlan_print_l3vnis(struct vty *vty, u_char use_json)
4060{
4061 u_int32_t num_vnis;
4062 void *args[2];
4063 json_object *json = NULL;
4064 struct zebra_ns *zns = NULL;
4065
51d8de8f
MK
4066 if (!is_evpn_enabled()) {
4067 if (use_json)
4068 vty_out(vty, "{}\n");
b7cfce93 4069 return;
51d8de8f 4070 }
b7cfce93
MK
4071
4072 zns = zebra_ns_lookup(NS_DEFAULT);
4073 assert(zns);
4074
4075 num_vnis = hashcount(zns->l3vni_table);
4076 if (!num_vnis) {
4077 if (use_json)
4078 vty_out(vty, "{}\n");
4079 return;
4080 }
4081
4082 if (use_json) {
4083 json = json_object_new_object();
4084 json_object_int_add(json, "numVnis", num_vnis);
4085 } else {
4086 vty_out(vty, "Number of L3 VNIs: %u\n", num_vnis);
b67a60d2 4087 vty_out(vty, "%-10s %-15s %-20s %-20s %-5s %-37s %-18s\n",
4088 "VNI", "Local-ip", "Vx-intf", "L3-SVI", "State",
4089 "VRF", "Rmac");
b7cfce93
MK
4090 }
4091
51d8de8f
MK
4092 args[0] = vty;
4093 args[1] = json;
b7cfce93
MK
4094 hash_iterate(zns->l3vni_table,
4095 (void (*)(struct hash_backet *, void *))zl3vni_print_hash,
4096 args);
4097
4098 if (use_json) {
4099 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4100 json, JSON_C_TO_STRING_PRETTY));
4101 json_object_free(json);
4102 }
4103}
4104
4105/*
4106 * Display Neighbors for a VNI (VTY command handler).
4107 */
4108void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
4109 vni_t vni, u_char use_json)
4110{
4111 zebra_vni_t *zvni;
4112 u_int32_t num_neigh;
4113 struct neigh_walk_ctx wctx;
4114 json_object *json = NULL;
4115
4116 if (!is_evpn_enabled())
4117 return;
4118 zvni = zvni_lookup(vni);
4119 if (!zvni) {
4120 if (use_json)
4121 vty_out(vty, "{}\n");
4122 else
4123 vty_out(vty, "%% VNI %u does not exist\n", vni);
4124 return;
4125 }
4126 num_neigh = hashcount(zvni->neigh_table);
4127 if (!num_neigh)
4128 return;
4129
4130 if (use_json)
4131 json = json_object_new_object();
4132
4133 /* Since we have IPv6 addresses to deal with which can vary widely in
4134 * size, we try to be a bit more elegant in display by first computing
4135 * the maximum width.
4136 */
4137 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4138 wctx.zvni = zvni;
4139 wctx.vty = vty;
4140 wctx.addr_width = 15;
4141 wctx.json = json;
4142 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
4143
4144 if (!use_json) {
4145 vty_out(vty,
4146 "Number of ARPs (local and remote) known for this VNI: %u\n",
4147 num_neigh);
4148 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
4149 "Type", "MAC", "Remote VTEP");
4150 } else
4151 json_object_int_add(json, "numArpNd", num_neigh);
4152
4153 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
4154 if (use_json) {
4155 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4156 json, JSON_C_TO_STRING_PRETTY));
4157 json_object_free(json);
4158 }
4159}
4160
4161/*
4162 * Display neighbors across all VNIs (VTY command handler).
4163 */
4164void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
4165 u_char use_json)
4166{
4167 json_object *json = NULL;
4168 void *args[2];
4169
4170 if (!is_evpn_enabled())
4171 return;
4172
4173 if (use_json)
4174 json = json_object_new_object();
4175
4176 args[0] = vty;
4177 args[1] = json;
4178 hash_iterate(zvrf->vni_table,
4179 (void (*)(struct hash_backet *,
4180 void *))zvni_print_neigh_hash_all_vni,
4181 args);
4182 if (use_json) {
4183 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4184 json, JSON_C_TO_STRING_PRETTY));
4185 json_object_free(json);
4186 }
4187}
4188
4189/*
4190 * Display specific neighbor for a VNI, if present (VTY command handler).
4191 */
4192void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
4193 struct zebra_vrf *zvrf, vni_t vni,
4194 struct ipaddr *ip, u_char use_json)
4195{
4196 zebra_vni_t *zvni;
4197 zebra_neigh_t *n;
4198 json_object *json = NULL;
4199
4200 if (!is_evpn_enabled())
4201 return;
4202 zvni = zvni_lookup(vni);
4203 if (!zvni) {
4204 if (use_json)
cd233079
CS
4205 vty_out(vty, "{}\n");
4206 else
4207 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4208 return;
4209 }
4210 n = zvni_neigh_lookup(zvni, ip);
4211 if (!n) {
cd233079
CS
4212 if (!use_json)
4213 vty_out(vty,
4214 "%% Requested neighbor does not exist in VNI %u\n",
4215 vni);
d62a17ae 4216 return;
4217 }
cd233079
CS
4218 if (use_json)
4219 json = json_object_new_object();
4220
4221 zvni_print_neigh(n, vty, json);
cec2e17d 4222
cd233079
CS
4223 if (use_json) {
4224 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4225 json, JSON_C_TO_STRING_PRETTY));
4226 json_object_free(json);
4227 }
cec2e17d 4228}
4229
4230/*
4231 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4232 * By definition, these are remote neighbors.
4233 */
d62a17ae 4234void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
4235 vni_t vni, struct in_addr vtep_ip,
4236 u_char use_json)
cec2e17d 4237{
d62a17ae 4238 zebra_vni_t *zvni;
4239 u_int32_t num_neigh;
4240 struct neigh_walk_ctx wctx;
cd233079 4241 json_object *json = NULL;
cec2e17d 4242
2853fed6 4243 if (!is_evpn_enabled())
d62a17ae 4244 return;
2853fed6 4245 zvni = zvni_lookup(vni);
d62a17ae 4246 if (!zvni) {
cd233079
CS
4247 if (use_json)
4248 vty_out(vty, "{}\n");
4249 else
4250 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4251 return;
4252 }
4253 num_neigh = hashcount(zvni->neigh_table);
4254 if (!num_neigh)
4255 return;
cec2e17d 4256
d62a17ae 4257 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4258 wctx.zvni = zvni;
4259 wctx.vty = vty;
4260 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
4261 wctx.r_vtep_ip = vtep_ip;
cd233079 4262 wctx.json = json;
d62a17ae 4263 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
4264
4265 if (use_json) {
4266 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4267 json, JSON_C_TO_STRING_PRETTY));
4268 json_object_free(json);
4269 }
cec2e17d 4270}
4271
4272/*
4273 * Display MACs for a VNI (VTY command handler).
4274 */
d62a17ae 4275void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 4276 vni_t vni, u_char use_json)
cec2e17d 4277{
d62a17ae 4278 zebra_vni_t *zvni;
4279 u_int32_t num_macs;
4280 struct mac_walk_ctx wctx;
cd233079
CS
4281 json_object *json = NULL;
4282 json_object *json_mac = NULL;
cec2e17d 4283
2853fed6 4284 if (!is_evpn_enabled())
d62a17ae 4285 return;
2853fed6 4286 zvni = zvni_lookup(vni);
d62a17ae 4287 if (!zvni) {
cd233079
CS
4288 if (use_json)
4289 vty_out(vty, "{}\n");
4290 else
4291 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4292 return;
4293 }
790f8dc5 4294 num_macs = num_valid_macs(zvni);
d62a17ae 4295 if (!num_macs)
4296 return;
cec2e17d 4297
cd233079
CS
4298 if (use_json) {
4299 json = json_object_new_object();
4300 json_mac = json_object_new_object();
4301 }
4302
d62a17ae 4303 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4304 wctx.zvni = zvni;
4305 wctx.vty = vty;
cd233079 4306 wctx.json = json_mac;
cec2e17d 4307
cd233079
CS
4308 if (!use_json) {
4309 vty_out(vty,
4310 "Number of MACs (local and remote) known for this VNI: %u\n",
4311 num_macs);
4312 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4313 "Intf/Remote VTEP", "VLAN");
4314 } else
4315 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 4316
d62a17ae 4317 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
4318
4319 if (use_json) {
4320 json_object_object_add(json, "macs", json_mac);
4321 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4322 json, JSON_C_TO_STRING_PRETTY));
4323 json_object_free(json);
4324 }
cec2e17d 4325}
4326
4327/*
4328 * Display MACs for all VNIs (VTY command handler).
4329 */
cd233079
CS
4330void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
4331 u_char use_json)
cec2e17d 4332{
d62a17ae 4333 struct mac_walk_ctx wctx;
cd233079 4334 json_object *json = NULL;
cec2e17d 4335
2853fed6 4336 if (!is_evpn_enabled()) {
cd233079
CS
4337 if (use_json)
4338 vty_out(vty, "{}\n");
d62a17ae 4339 return;
cd233079
CS
4340 }
4341 if (use_json)
4342 json = json_object_new_object();
4343
d62a17ae 4344 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4345 wctx.vty = vty;
cd233079 4346 wctx.json = json;
d62a17ae 4347 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
4348
4349 if (use_json) {
4350 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4351 json, JSON_C_TO_STRING_PRETTY));
4352 json_object_free(json);
4353 }
cec2e17d 4354}
4355
4356/*
4357 * Display MACs for all VNIs (VTY command handler).
4358 */
d62a17ae 4359void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
4360 struct zebra_vrf *zvrf,
cd233079
CS
4361 struct in_addr vtep_ip,
4362 u_char use_json)
cec2e17d 4363{
d62a17ae 4364 struct mac_walk_ctx wctx;
cd233079 4365 json_object *json = NULL;
cec2e17d 4366
2853fed6 4367 if (!is_evpn_enabled())
d62a17ae 4368 return;
cd233079
CS
4369
4370 if (use_json)
4371 json = json_object_new_object();
4372
d62a17ae 4373 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4374 wctx.vty = vty;
4375 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4376 wctx.r_vtep_ip = vtep_ip;
cd233079 4377 wctx.json = json;
d62a17ae 4378 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
4379
4380 if (use_json) {
4381 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4382 json, JSON_C_TO_STRING_PRETTY));
4383 json_object_free(json);
4384 }
cec2e17d 4385}
4386
4387/*
4388 * Display specific MAC for a VNI, if present (VTY command handler).
4389 */
d62a17ae 4390void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
4391 vni_t vni, struct ethaddr *macaddr)
cec2e17d 4392{
d62a17ae 4393 zebra_vni_t *zvni;
4394 zebra_mac_t *mac;
cec2e17d 4395
2853fed6 4396 if (!is_evpn_enabled())
d62a17ae 4397 return;
2853fed6 4398 zvni = zvni_lookup(vni);
d62a17ae 4399 if (!zvni) {
4400 vty_out(vty, "%% VNI %u does not exist\n", vni);
4401 return;
4402 }
4403 mac = zvni_mac_lookup(zvni, macaddr);
4404 if (!mac) {
4405 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
4406 vni);
4407 return;
4408 }
cec2e17d 4409
d62a17ae 4410 zvni_print_mac(mac, vty);
cec2e17d 4411}
4412
4413/*
4414 * Display MACs for a VNI from specific VTEP (VTY command handler).
4415 */
d62a17ae 4416void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
4417 vni_t vni, struct in_addr vtep_ip,
4418 u_char use_json)
cec2e17d 4419{
d62a17ae 4420 zebra_vni_t *zvni;
4421 u_int32_t num_macs;
4422 struct mac_walk_ctx wctx;
cd233079
CS
4423 json_object *json = NULL;
4424 json_object *json_mac = NULL;
cec2e17d 4425
2853fed6 4426 if (!is_evpn_enabled())
d62a17ae 4427 return;
2853fed6 4428 zvni = zvni_lookup(vni);
d62a17ae 4429 if (!zvni) {
cd233079
CS
4430 if (use_json)
4431 vty_out(vty, "{}\n");
4432 else
4433 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4434 return;
4435 }
790f8dc5 4436 num_macs = num_valid_macs(zvni);
d62a17ae 4437 if (!num_macs)
4438 return;
cd233079
CS
4439
4440 if (use_json) {
4441 json = json_object_new_object();
4442 json_mac = json_object_new_object();
4443 }
4444
d62a17ae 4445 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4446 wctx.zvni = zvni;
4447 wctx.vty = vty;
4448 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4449 wctx.r_vtep_ip = vtep_ip;
cd233079 4450 wctx.json = json_mac;
d62a17ae 4451 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
4452
4453 if (use_json) {
4454 json_object_int_add(json, "numMacs", wctx.count);
4455 if (wctx.count)
4456 json_object_object_add(json, "macs", json_mac);
4457 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4458 json, JSON_C_TO_STRING_PRETTY));
4459 json_object_free(json);
4460 }
cec2e17d 4461}
4462
4463
4464/*
4465 * Display VNI information (VTY command handler).
4466 */
cd233079
CS
4467void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
4468 u_char use_json)
cec2e17d 4469{
d62a17ae 4470 zebra_vni_t *zvni;
cd233079
CS
4471 json_object *json = NULL;
4472 void *args[2];
cec2e17d 4473
2853fed6 4474 if (!is_evpn_enabled())
d62a17ae 4475 return;
2853fed6 4476 zvni = zvni_lookup(vni);
d62a17ae 4477 if (!zvni) {
cd233079
CS
4478 if (use_json)
4479 vty_out(vty, "{}\n");
4480 else
4481 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4482 return;
4483 }
cd233079
CS
4484 if (use_json)
4485 json = json_object_new_object();
4486 args[0] = vty;
4487 args[1] = json;
4488 zvni_print(zvni, (void *)args);
4489 if (use_json) {
4490 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4491 json, JSON_C_TO_STRING_PRETTY));
4492 json_object_free(json);
4493 }
cec2e17d 4494}
4495
4496/*
4497 * Display VNI hash table (VTY command handler).
4498 */
cd233079
CS
4499void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
4500 u_char use_json)
cec2e17d 4501{
d62a17ae 4502 u_int32_t num_vnis;
cd233079
CS
4503 json_object *json = NULL;
4504 void *args[2];
cec2e17d 4505
2853fed6 4506 if (!is_evpn_enabled())
d62a17ae 4507 return;
4508 num_vnis = hashcount(zvrf->vni_table);
cd233079
CS
4509 if (!num_vnis) {
4510 if (use_json)
4511 vty_out(vty, "{}\n");
d62a17ae 4512 return;
cd233079
CS
4513 }
4514 if (use_json) {
4515 json = json_object_new_object();
ddd16ed5
MK
4516 json_object_string_add(json, "advertiseGatewayMacip",
4517 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
4518 json_object_int_add(json, "numVnis", num_vnis);
4519 } else {
ddd16ed5
MK
4520 vty_out(vty, "Advertise gateway mac-ip: %s\n",
4521 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079 4522 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
b7cfce93 4523 vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s %-37s\n", "VNI",
cd233079 4524 "VxLAN IF", "VTEP IP", "# MACs", "# ARPs",
b7cfce93 4525 "# Remote VTEPs", "VRF");
cd233079
CS
4526 }
4527 args[0] = vty;
4528 args[1] = json;
4529
4530 hash_iterate(zvrf->vni_table,
4531 (void (*)(struct hash_backet *, void *))zvni_print_hash,
4532 args);
4533
4534 if (use_json) {
4535 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4536 json, JSON_C_TO_STRING_PRETTY));
4537 json_object_free(json);
4538 }
cec2e17d 4539}
4540
2232a77c 4541/*
4542 * Handle neighbor delete (on a VLAN device / L3 interface) from the
4543 * kernel. This may result in either the neighbor getting deleted from
4544 * our database or being re-added to the kernel (if it is a valid
4545 * remote neighbor).
4546 */
d62a17ae 4547int zebra_vxlan_local_neigh_del(struct interface *ifp,
4548 struct interface *link_if, struct ipaddr *ip)
4549{
d62a17ae 4550 char buf[INET6_ADDRSTRLEN];
b6938a74 4551 char buf2[ETHER_ADDR_STRLEN];
b7cfce93
MK
4552 zebra_neigh_t *n = NULL;
4553 zebra_vni_t *zvni = NULL;
4554 zebra_mac_t *zmac = NULL;
8c9b80b9 4555 zebra_l3vni_t *zl3vni = NULL;
b7cfce93 4556
8c9b80b9 4557 /* check if this is a remote neigh entry corresponding to remote
523cafc4 4558 * next-hop
4559 */
8c9b80b9
MK
4560 zl3vni = zl3vni_from_svi(ifp, link_if);
4561 if (zl3vni)
4562 return zl3vni_local_nh_del(zl3vni, ip);
d62a17ae 4563
4564 /* We are only interested in neighbors on an SVI that resides on top
4565 * of a VxLAN bridge.
4566 */
b7cfce93 4567 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 4568 if (!zvni)
4569 return 0;
8c9b80b9 4570
d62a17ae 4571 if (!zvni->vxlan_if) {
4572 zlog_err(
4573 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4574 zvni->vni, zvni);
4575 return -1;
4576 }
4577
4578 if (IS_ZEBRA_DEBUG_VXLAN)
8c9b80b9 4579 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
2853fed6 4580 ipaddr2str(ip, buf, sizeof(buf)),
8c9b80b9 4581 ifp->name, ifp->ifindex, zvni->vni);
d62a17ae 4582
4583 /* If entry doesn't exist, nothing to do. */
4584 n = zvni_neigh_lookup(zvni, ip);
4585 if (!n)
4586 return 0;
4587
b6938a74
MK
4588 zmac = zvni_mac_lookup(zvni, &n->emac);
4589 if (!zmac) {
4590 if (IS_ZEBRA_DEBUG_VXLAN)
4591 zlog_err(
2853fed6 4592 "Trying to del a neigh %s without a mac %s on VNI %u",
4593 ipaddr2str(ip, buf, sizeof(buf)),
b6938a74
MK
4594 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
4595 zvni->vni);
4596
4597 return 0;
4598 }
4599
d62a17ae 4600 /* If it is a remote entry, the kernel has aged this out or someone has
4601 * deleted it, it needs to be re-installed as Quagga is the owner.
4602 */
4603 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
4604 zvni_neigh_install(zvni, n);
4605 return 0;
4606 }
4607
d62a17ae 4608 /* Remove neighbor from BGP. */
b6938a74 4609 if (IS_ZEBRA_NEIGH_ACTIVE(n))
2853fed6 4610 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
b6938a74 4611 0);
d62a17ae 4612
4613 /* Delete this neighbor entry. */
4614 zvni_neigh_del(zvni, n);
4615
b6938a74
MK
4616 /* see if the AUTO mac needs to be deleted */
4617 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
f51d8a27 4618 && !listcount(zmac->neigh_list))
b6938a74
MK
4619 zvni_mac_del(zvni, zmac);
4620
d62a17ae 4621 return 0;
2232a77c 4622}
4623
4624/*
859b32c0
MK
4625 * Handle neighbor add or update (on a VLAN device / L3 interface)
4626 * from the kernel.
2232a77c 4627 */
d62a17ae 4628int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
4629 struct interface *link_if,
4630 struct ipaddr *ip,
4631 struct ethaddr *macaddr, u_int16_t state,
4632 u_char ext_learned)
4633{
d62a17ae 4634 char buf[ETHER_ADDR_STRLEN];
4635 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
4636 zebra_vni_t *zvni = NULL;
4637 zebra_neigh_t *n = NULL;
4638 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
3bcbba10 4639 zebra_l3vni_t *zl3vni = NULL;
4640
4641 /* check if this is a remote neigh entry corresponding to remote
4642 * next-hop
4643 */
4644 zl3vni = zl3vni_from_svi(ifp, link_if);
4645 if (zl3vni)
4646 return zl3vni_local_nh_add_update(zl3vni, ip, state);
b7cfce93 4647
d62a17ae 4648 /* We are only interested in neighbors on an SVI that resides on top
4649 * of a VxLAN bridge.
4650 */
b7cfce93 4651 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 4652 if (!zvni)
4653 return 0;
4654
d62a17ae 4655 if (IS_ZEBRA_DEBUG_VXLAN)
4656 zlog_debug(
8c9b80b9 4657 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
2853fed6 4658 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 4659 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
4660 ifp->ifindex, state, ext_learned ? "ext-learned " : "",
8c9b80b9 4661 zvni->vni);
d62a17ae 4662
b6938a74
MK
4663 /* create a dummy MAC if the MAC is not already present */
4664 zmac = zvni_mac_lookup(zvni, macaddr);
4665 if (!zmac) {
4666 if (IS_ZEBRA_DEBUG_VXLAN)
4667 zlog_debug(
2853fed6 4668 "AUTO MAC %s created for neigh %s on VNI %u",
b6938a74
MK
4669 prefix_mac2str(macaddr, buf, sizeof(buf)),
4670 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
4671
4672 zmac = zvni_mac_add(zvni, macaddr);
4673 if (!zmac) {
2853fed6 4674 zlog_warn("Failed to add MAC %s VNI %u",
b6938a74
MK
4675 prefix_mac2str(macaddr, buf, sizeof(buf)),
4676 zvni->vni);
4677 return -1;
4678 }
4679
4680 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
4681 memset(&zmac->flags, 0, sizeof(u_int32_t));
4682 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
4683 }
4684
d62a17ae 4685 /* If same entry already exists, it might be a change or it might be a
4686 * move from remote to local.
4687 */
4688 n = zvni_neigh_lookup(zvni, ip);
4689 if (n) {
4690 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
4691 if (memcmp(n->emac.octet, macaddr->octet,
ff8b7eb8 4692 ETH_ALEN)
d62a17ae 4693 == 0) {
b682f6de 4694 /* Update any params and return - client doesn't
4695 * care about a purely local change.
4696 */
4697 n->ifindex = ifp->ifindex;
4698 return 0;
57f7feb6 4699 }
b682f6de 4700
57f7feb6
MK
4701 /* If the MAC has changed,
4702 * need to issue a delete first
4703 * as this means a different MACIP route.
4704 * Also, need to do some unlinking/relinking.
4705 */
2853fed6 4706 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
60466a63 4707 &n->emac, 0);
57f7feb6
MK
4708 old_zmac = zvni_mac_lookup(zvni, &n->emac);
4709 if (old_zmac) {
60466a63 4710 listnode_delete(old_zmac->neigh_list, n);
57f7feb6 4711 zvni_deref_ip2mac(zvni, old_zmac, 0);
b682f6de 4712 }
57f7feb6
MK
4713
4714 /* Set "local" forwarding info. */
4715 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4716 n->ifindex = ifp->ifindex;
4717 memcpy(&n->emac, macaddr, ETH_ALEN);
4718
4719 /* Link to new MAC */
4720 listnode_add_sort(zmac->neigh_list, n);
d62a17ae 4721 } else if (ext_learned)
4722 /* The neighbor is remote and that is the notification we got.
9d303b37 4723 */
d62a17ae 4724 {
859b32c0 4725 /* TODO: Evaluate if we need to do anything here. */
d62a17ae 4726 return 0;
4727 } else
4728 /* Neighbor has moved from remote to local. */
4729 {
4730 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
4731 n->r_vtep_ip.s_addr = 0;
b682f6de 4732 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4733 n->ifindex = ifp->ifindex;
d62a17ae 4734 }
4735 } else {
b6938a74 4736 n = zvni_neigh_add(zvni, ip, macaddr);
d62a17ae 4737 if (!n) {
4738 zlog_err(
2853fed6 4739 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
4740 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 4741 prefix_mac2str(macaddr, buf, sizeof(buf)),
4742 ifp->name, ifp->ifindex, zvni->vni);
4743 return -1;
4744 }
b682f6de 4745 /* Set "local" forwarding info. */
4746 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4747 n->ifindex = ifp->ifindex;
d62a17ae 4748 }
4749
b6938a74
MK
4750 /* Before we program this in BGP, we need to check if MAC is locally
4751 * learnt as well */
4752 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
4753 if (IS_ZEBRA_DEBUG_VXLAN)
4754 zlog_debug(
2853fed6 4755 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
4756 ipaddr2str(ip, buf2, sizeof(buf2)),
b6938a74
MK
4757 prefix_mac2str(macaddr, buf, sizeof(buf)),
4758 zvni->vni);
4759
4760 return 0;
4761 }
4762
b682f6de 4763 /* Inform BGP. */
4764 if (IS_ZEBRA_DEBUG_VXLAN)
8c9b80b9 4765 zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
2853fed6 4766 ipaddr2str(ip, buf2, sizeof(buf2)),
60466a63 4767 prefix_mac2str(macaddr, buf, sizeof(buf)),
8c9b80b9 4768 zvni->vni);
b682f6de 4769 ZEBRA_NEIGH_SET_ACTIVE(n);
b7cfce93 4770
2853fed6 4771 return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
2232a77c 4772}
4773
b682f6de 4774
2232a77c 4775/*
4776 * Handle message from client to delete a remote MACIP for a VNI.
4777 */
e4bd522a 4778int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
d62a17ae 4779 struct zebra_vrf *zvrf)
4780{
4781 struct stream *s;
4782 vni_t vni;
4783 struct ethaddr macaddr;
4784 struct ipaddr ip;
4785 struct in_addr vtep_ip;
4786 zebra_vni_t *zvni;
4787 zebra_mac_t *mac;
4788 zebra_neigh_t *n;
4789 u_short l = 0, ipa_len;
4790 char buf[ETHER_ADDR_STRLEN];
4791 char buf1[INET6_ADDRSTRLEN];
b5ebdc9b 4792 struct interface *ifp = NULL;
4793 struct zebra_if *zif = NULL;
d62a17ae 4794
b7cfce93 4795 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
4796 memset(&ip, 0, sizeof(struct ipaddr));
4797 memset(&vtep_ip, 0, sizeof(struct in_addr));
4798
d62a17ae 4799 s = client->ibuf;
4800
4801 while (l < length) {
4802 /* Obtain each remote MACIP and process. */
4803 /* Message contains VNI, followed by MAC followed by IP (if any)
4804 * followed by remote VTEP IP.
4805 */
4806 mac = NULL;
4807 n = NULL;
4808 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
4809 STREAM_GETL(s, vni);
4810 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
4811 STREAM_GETL(s, ipa_len);
d62a17ae 4812 if (ipa_len) {
4813 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
4814 : IPADDR_V6;
ec93aa12 4815 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 4816 }
ff8b7eb8 4817 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 4818 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4819 l += IPV4_MAX_BYTELEN;
4820
4821 if (IS_ZEBRA_DEBUG_VXLAN)
4822 zlog_debug(
23a06e11 4823 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
d62a17ae 4824 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4825 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
4826 inet_ntoa(vtep_ip),
4827 zebra_route_string(client->proto));
4828
4829 /* Locate VNI hash entry - expected to exist. */
2853fed6 4830 zvni = zvni_lookup(vni);
d62a17ae 4831 if (!zvni) {
4832 if (IS_ZEBRA_DEBUG_VXLAN)
4833 zlog_debug(
4834 "Failed to locate VNI hash upon remote MACIP DEL, "
2853fed6 4835 "VNI %u",
4836 vni);
d62a17ae 4837 continue;
4838 }
b5ebdc9b 4839 ifp = zvni->vxlan_if;
af026ae4 4840 if (!ifp) {
d62a17ae 4841 zlog_err(
4842 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
4843 vni, zvni);
4844 continue;
4845 }
b5ebdc9b 4846 zif = ifp->info;
4847
4848 /* If down or not mapped to a bridge, we're done. */
b682f6de 4849 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 4850 continue;
d62a17ae 4851
4852 /* The remote VTEP specified is normally expected to exist, but
4853 * it is
4854 * possible that the peer may delete the VTEP before deleting
4855 * any MACs
4856 * referring to the VTEP, in which case the handler (see
4857 * remote_vtep_del)
4858 * would have already deleted the MACs.
4859 */
4860 if (!zvni_vtep_find(zvni, &vtep_ip))
4861 continue;
4862
d62a17ae 4863 mac = zvni_mac_lookup(zvni, &macaddr);
4864 if (ipa_len)
4865 n = zvni_neigh_lookup(zvni, &ip);
4866
4867 if (n && !mac) {
4868 zlog_err(
2853fed6 4869 "Failed to locate MAC %s for neigh %s VNI %u",
d62a17ae 4870 prefix_mac2str(&macaddr, buf, sizeof(buf)),
2853fed6 4871 ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
d62a17ae 4872 continue;
4873 }
4874
4875 /* If the remote mac or neighbor doesn't exist there is nothing
4876 * more
4877 * to do. Otherwise, uninstall the entry and then remove it.
4878 */
4879 if (!mac && !n)
4880 continue;
4881
4882 /* Uninstall remote neighbor or MAC. */
4883 if (n) {
4884 /* When the MAC changes for an IP, it is possible the
4885 * client may
4886 * update the new MAC before trying to delete the "old"
4887 * neighbor
4888 * (as these are two different MACIP routes). Do the
4889 * delete only
4890 * if the MAC matches.
4891 */
4892 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
4893 && (memcmp(n->emac.octet, macaddr.octet,
ff8b7eb8 4894 ETH_ALEN)
d62a17ae 4895 == 0)) {
4896 zvni_neigh_uninstall(zvni, n);
4897 zvni_neigh_del(zvni, n);
4898 zvni_deref_ip2mac(zvni, mac, 1);
4899 }
4900 } else {
4901 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
2853fed6 4902 zvni_process_neigh_on_remote_mac_del(zvni,
b6938a74
MK
4903 mac);
4904
0a97666d 4905 if (list_isempty(mac->neigh_list)) {
d62a17ae 4906 zvni_mac_uninstall(zvni, mac, 0);
4907 zvni_mac_del(zvni, mac);
4908 } else
4909 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
4910 }
4911 }
4912 }
4913
ec93aa12 4914stream_failure:
d62a17ae 4915 return 0;
2232a77c 4916}
4917
4918/*
4919 * Handle message from client to add a remote MACIP for a VNI. This
4920 * could be just the add of a MAC address or the add of a neighbor
4921 * (IP+MAC).
4922 */
e4bd522a 4923int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
d62a17ae 4924 struct zebra_vrf *zvrf)
4925{
4926 struct stream *s;
4927 vni_t vni;
4928 struct ethaddr macaddr;
4929 struct ipaddr ip;
4930 struct in_addr vtep_ip;
4931 zebra_vni_t *zvni;
4932 zebra_vtep_t *zvtep;
4933 zebra_mac_t *mac, *old_mac;
4934 zebra_neigh_t *n;
4935 u_short l = 0, ipa_len;
4936 int update_mac = 0, update_neigh = 0;
4937 char buf[ETHER_ADDR_STRLEN];
4938 char buf1[INET6_ADDRSTRLEN];
4939 u_char sticky;
b5ebdc9b 4940 struct interface *ifp = NULL;
4941 struct zebra_if *zif = NULL;
d62a17ae 4942
b7cfce93 4943 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
4944 memset(&ip, 0, sizeof(struct ipaddr));
4945 memset(&vtep_ip, 0, sizeof(struct in_addr));
4946
ec93aa12
DS
4947 if (!EVPN_ENABLED(zvrf)) {
4948 zlog_warn("%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
4949 __PRETTY_FUNCTION__);
4950 return -1;
4951 }
d62a17ae 4952
4953 s = client->ibuf;
4954
4955 while (l < length) {
4956 /* Obtain each remote MACIP and process. */
4957 /* Message contains VNI, followed by MAC followed by IP (if any)
4958 * followed by remote VTEP IP.
4959 */
4960 update_mac = update_neigh = 0;
4961 mac = NULL;
4962 n = NULL;
4963 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
4964 STREAM_GETL(s, vni);
4965 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
4966 STREAM_GETL(s, ipa_len);
d62a17ae 4967 if (ipa_len) {
4968 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
4969 : IPADDR_V6;
ec93aa12 4970 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 4971 }
ff8b7eb8 4972 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 4973 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4974 l += IPV4_MAX_BYTELEN;
4975
4976 /* Get 'sticky' flag. */
ec93aa12 4977 STREAM_GETC(s, sticky);
d62a17ae 4978 l++;
4979
4980 if (IS_ZEBRA_DEBUG_VXLAN)
4981 zlog_debug(
b80320d7 4982 "Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
2853fed6 4983 sticky ? "sticky " : "",
d62a17ae 4984 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4985 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
4986 inet_ntoa(vtep_ip),
4987 zebra_route_string(client->proto));
4988
4989 /* Locate VNI hash entry - expected to exist. */
2853fed6 4990 zvni = zvni_lookup(vni);
d62a17ae 4991 if (!zvni) {
4992 zlog_err(
2853fed6 4993 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
4994 vni);
d62a17ae 4995 continue;
4996 }
b5ebdc9b 4997 ifp = zvni->vxlan_if;
4998 if (!ifp) {
d62a17ae 4999 zlog_err(
5000 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5001 vni, zvni);
5002 continue;
5003 }
b5ebdc9b 5004 zif = ifp->info;
5005
5006 /* If down or not mapped to a bridge, we're done. */
b682f6de 5007 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 5008 continue;
5009
5010 /* The remote VTEP specified should normally exist, but it is
5011 * possible
5012 * that when peering comes up, peer may advertise MACIP routes
5013 * before
5014 * advertising type-3 routes.
5015 */
5016 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5017 if (!zvtep) {
5018 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5019 zlog_err(
2853fed6 5020 "Failed to add remote VTEP, VNI %u zvni %p",
5021 vni, zvni);
d62a17ae 5022 continue;
5023 }
5024
5025 zvni_vtep_install(zvni, &vtep_ip);
5026 }
5027
5028 /* First, check if the remote MAC is unknown or has a change. If
5029 * so,
5030 * that needs to be updated first. Note that client could
5031 * install
5032 * MAC and MACIP separately or just install the latter.
5033 */
5034 mac = zvni_mac_lookup(zvni, &macaddr);
5035 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
5036 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
5037 != sticky
5038 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
5039 update_mac = 1;
5040
5041 if (update_mac) {
5042 if (!mac) {
5043 mac = zvni_mac_add(zvni, &macaddr);
5044 if (!mac) {
5045 zlog_warn(
2853fed6 5046 "Failed to add MAC %s VNI %u Remote VTEP %s",
d62a17ae 5047 prefix_mac2str(&macaddr, buf,
5048 sizeof(buf)),
5049 vni, inet_ntoa(vtep_ip));
5050 return -1;
5051 }
5052
5053 /* Is this MAC created for a MACIP? */
5054 if (ipa_len)
5055 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 5056 }
5057
5058 /* Set "auto" and "remote" forwarding info. */
5059 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5060 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
5061 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5062 mac->fwd_info.r_vtep_ip = vtep_ip;
5063
5064 if (sticky)
5065 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5066 else
5067 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5068
2853fed6 5069 zvni_process_neigh_on_remote_mac_add(zvni, mac);
b6938a74 5070
d62a17ae 5071 /* Install the entry. */
5072 zvni_mac_install(zvni, mac);
5073 }
5074
5075 /* If there is no IP, continue - after clearing AUTO flag of
5076 * MAC. */
5077 if (!ipa_len) {
5078 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5079 continue;
5080 }
5081
5082 /* Check if the remote neighbor itself is unknown or has a
5083 * change.
5084 * If so, create or update and then install the entry.
5085 */
5086 n = zvni_neigh_lookup(zvni, &ip);
5087 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5088 || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0)
5089 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip))
5090 update_neigh = 1;
5091
5092 if (update_neigh) {
5093 if (!n) {
b6938a74 5094 n = zvni_neigh_add(zvni, &ip, &macaddr);
d62a17ae 5095 if (!n) {
5096 zlog_warn(
2853fed6 5097 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
d62a17ae 5098 ipaddr2str(&ip, buf1,
5099 sizeof(buf1)),
5100 prefix_mac2str(&macaddr, buf,
5101 sizeof(buf)),
5102 vni, inet_ntoa(vtep_ip));
5103 return -1;
5104 }
5105
d62a17ae 5106 } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
5107 != 0) {
0a97666d
MK
5108 /* MAC change, update neigh list for old and new
5109 * mac */
d62a17ae 5110 old_mac = zvni_mac_lookup(zvni, &n->emac);
0a97666d
MK
5111 if (old_mac) {
5112 listnode_delete(old_mac->neigh_list, n);
d62a17ae 5113 zvni_deref_ip2mac(zvni, old_mac, 1);
0a97666d
MK
5114 }
5115 listnode_add_sort(mac->neigh_list, n);
b6938a74 5116 memcpy(&n->emac, &macaddr, ETH_ALEN);
d62a17ae 5117 }
5118
5119 /* Set "remote" forwarding info. */
5120 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
5121 /* TODO: Handle MAC change. */
d62a17ae 5122 n->r_vtep_ip = vtep_ip;
5123 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
5124
5125 /* Install the entry. */
5126 zvni_neigh_install(zvni, n);
5127 }
5128 }
5129
ec93aa12 5130stream_failure:
d62a17ae 5131 return 0;
13d60d35 5132}
5133
5134/*
2232a77c 5135 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5136 * us, this must involve a multihoming scenario. Treat this as implicit delete
5137 * of any prior local MAC.
13d60d35 5138 */
d62a17ae 5139int zebra_vxlan_check_del_local_mac(struct interface *ifp,
5140 struct interface *br_if,
5141 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5142{
d62a17ae 5143 struct zebra_if *zif;
d62a17ae 5144 struct zebra_l2info_vxlan *vxl;
5145 vni_t vni;
5146 zebra_vni_t *zvni;
5147 zebra_mac_t *mac;
5148 char buf[ETHER_ADDR_STRLEN];
5149 u_char sticky;
13d60d35 5150
d62a17ae 5151 zif = ifp->info;
5152 assert(zif);
5153 vxl = &zif->l2info.vxl;
5154 vni = vxl->vni;
13d60d35 5155
2853fed6 5156 /* Check if EVPN is enabled. */
5157 if (!is_evpn_enabled())
d62a17ae 5158 return 0;
13d60d35 5159
d62a17ae 5160 /* Locate hash entry; it is expected to exist. */
2853fed6 5161 zvni = zvni_lookup(vni);
d62a17ae 5162 if (!zvni)
5163 return 0;
13d60d35 5164
d62a17ae 5165 /* If entry doesn't exist, nothing to do. */
5166 mac = zvni_mac_lookup(zvni, macaddr);
5167 if (!mac)
5168 return 0;
13d60d35 5169
d62a17ae 5170 /* Is it a local entry? */
5171 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5172 return 0;
13d60d35 5173
d62a17ae 5174 if (IS_ZEBRA_DEBUG_VXLAN)
5175 zlog_debug(
2853fed6 5176 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5177 prefix_mac2str(macaddr, buf, sizeof(buf)),
d62a17ae 5178 ifp->name, ifp->ifindex, vni);
13d60d35 5179
d62a17ae 5180 /* Remove MAC from BGP. */
5181 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
2853fed6 5182 zvni_mac_send_del_to_client(zvni->vni, macaddr,
1a98c087 5183 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
13d60d35 5184
b6938a74
MK
5185 /*
5186 * If there are no neigh associated with the mac delete the mac
5187 * else mark it as AUTO for forward reference
5188 */
5189 if (!listcount(mac->neigh_list)) {
5190 zvni_mac_del(zvni, mac);
5191 } else {
5192 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5193 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5194 }
13d60d35 5195
d62a17ae 5196 return 0;
13d60d35 5197}
5198
5199/*
2232a77c 5200 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5201 * This can happen because the remote MAC entries are also added as "dynamic",
5202 * so the kernel can ageout the entry.
13d60d35 5203 */
d62a17ae 5204int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
5205 struct interface *br_if,
5206 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5207{
d62a17ae 5208 struct zebra_if *zif;
d62a17ae 5209 struct zebra_l2info_vxlan *vxl;
5210 vni_t vni;
5211 zebra_vni_t *zvni;
5212 zebra_mac_t *mac;
5213 char buf[ETHER_ADDR_STRLEN];
2232a77c 5214
d62a17ae 5215 zif = ifp->info;
5216 assert(zif);
5217 vxl = &zif->l2info.vxl;
5218 vni = vxl->vni;
2232a77c 5219
2853fed6 5220 /* Check if EVPN is enabled. */
5221 if (!is_evpn_enabled())
d62a17ae 5222 return 0;
2232a77c 5223
d62a17ae 5224 /* Locate hash entry; it is expected to exist. */
2853fed6 5225 zvni = zvni_lookup(vni);
d62a17ae 5226 if (!zvni)
5227 return 0;
13d60d35 5228
d62a17ae 5229 /* If entry doesn't exist, nothing to do. */
5230 mac = zvni_mac_lookup(zvni, macaddr);
5231 if (!mac)
5232 return 0;
2232a77c 5233
d62a17ae 5234 /* Is it a remote entry? */
5235 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
5236 return 0;
2232a77c 5237
d62a17ae 5238 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5239 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
d62a17ae 5240 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5241 ifp->ifindex, vni);
13d60d35 5242
d62a17ae 5243 zvni_mac_install(zvni, mac);
5244 return 0;
13d60d35 5245}
5246
5247/*
2232a77c 5248 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 5249 */
d62a17ae 5250int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
5251 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5252{
d62a17ae 5253 zebra_vni_t *zvni;
5254 zebra_mac_t *mac;
d62a17ae 5255 char buf[ETHER_ADDR_STRLEN];
5256 u_char sticky;
13d60d35 5257
d62a17ae 5258 /* We are interested in MACs only on ports or (port, VLAN) that
5259 * map to a VNI.
5260 */
5261 zvni = zvni_map_vlan(ifp, br_if, vid);
5262 if (!zvni)
5263 return 0;
5264 if (!zvni->vxlan_if) {
5265 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5266 zvni->vni, zvni);
5267 return -1;
5268 }
13d60d35 5269
d62a17ae 5270 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5271 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
d62a17ae 5272 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5273 ifp->ifindex, vid, zvni->vni);
2232a77c 5274
d62a17ae 5275 /* If entry doesn't exist, nothing to do. */
5276 mac = zvni_mac_lookup(zvni, macaddr);
5277 if (!mac)
5278 return 0;
2232a77c 5279
d62a17ae 5280 /* Is it a local entry? */
5281 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5282 return 0;
2232a77c 5283
d62a17ae 5284 /* Remove MAC from BGP. */
5285 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
2853fed6 5286 zvni_mac_send_del_to_client(zvni->vni, macaddr,
1a98c087 5287 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
2232a77c 5288
b6938a74 5289 /* Update all the neigh entries associated with this mac */
2853fed6 5290 zvni_process_neigh_on_local_mac_del(zvni, mac);
b6938a74
MK
5291
5292 /*
5293 * If there are no neigh associated with the mac delete the mac
5294 * else mark it as AUTO for forward reference
5295 */
5296 if (!listcount(mac->neigh_list)) {
5297 zvni_mac_del(zvni, mac);
5298 } else {
5299 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5300 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5301 }
2232a77c 5302
d62a17ae 5303 return 0;
13d60d35 5304}
5305
5306/*
2232a77c 5307 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 5308 */
d62a17ae 5309int zebra_vxlan_local_mac_add_update(struct interface *ifp,
5310 struct interface *br_if,
5311 struct ethaddr *macaddr, vlanid_t vid,
5312 u_char sticky)
5313{
5314 zebra_vni_t *zvni;
5315 zebra_mac_t *mac;
d62a17ae 5316 char buf[ETHER_ADDR_STRLEN];
5317 int add = 1;
5318 u_char mac_sticky;
5319
5320 /* We are interested in MACs only on ports or (port, VLAN) that
5321 * map to a VNI.
5322 */
5323 zvni = zvni_map_vlan(ifp, br_if, vid);
5324 if (!zvni) {
5325 if (IS_ZEBRA_DEBUG_VXLAN)
5326 zlog_debug(
2853fed6 5327 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5328 sticky ? "sticky " : "",
d62a17ae 5329 prefix_mac2str(macaddr, buf, sizeof(buf)),
5330 ifp->name, ifp->ifindex, vid);
5331 return 0;
5332 }
5333
5334 if (!zvni->vxlan_if) {
5335 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5336 zvni->vni, zvni);
5337 return -1;
5338 }
5339
5340 if (IS_ZEBRA_DEBUG_VXLAN)
5341 zlog_debug(
2853fed6 5342 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5343 sticky ? "sticky " : "",
d62a17ae 5344 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5345 ifp->ifindex, vid, zvni->vni);
5346
5347 /* If same entry already exists, nothing to do. */
5348 mac = zvni_mac_lookup(zvni, macaddr);
5349 if (mac) {
5350 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
5351 mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
5352 ? 1
5353 : 0;
5354
b6938a74 5355
b8ce75a5
MK
5356 /*
5357 * return if nothing has changed.
5358 * inform bgp if sticky flag has changed
5359 * update locally and do not inform bgp if local
5360 * parameters like interface has changed
5361 */
d62a17ae 5362 if (mac_sticky == sticky
5363 && mac->fwd_info.local.ifindex == ifp->ifindex
5364 && mac->fwd_info.local.vid == vid) {
5365 if (IS_ZEBRA_DEBUG_VXLAN)
5366 zlog_debug(
2853fed6 5367 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
d62a17ae 5368 "entry exists and has not changed ",
d62a17ae 5369 sticky ? "sticky " : "",
5370 prefix_mac2str(macaddr, buf,
5371 sizeof(buf)),
5372 ifp->name, ifp->ifindex, vid,
5373 zvni->vni);
5374 return 0;
b6938a74 5375 } else if (mac_sticky != sticky) {
b8ce75a5 5376 add = 1;
b6938a74 5377 } else {
b8ce75a5
MK
5378 add = 0; /* This is an update of local
5379 interface. */
b6938a74 5380 }
421bb26a
MK
5381 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5382 /*
5383 * If we have already learned the MAC as a remote sticky
5384 * MAC,
5385 * this is a operator error and we must log a warning
5386 */
8f4b98ee 5387 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
421bb26a
MK
5388 zlog_warn(
5389 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5390 prefix_mac2str(macaddr, buf,
5391 sizeof(buf)),
5392 inet_ntoa(mac->fwd_info.r_vtep_ip),
5393 zvni->vni);
8f4b98ee
MK
5394 return 0;
5395 }
d62a17ae 5396 }
5397 }
5398
d62a17ae 5399 if (!mac) {
5400 mac = zvni_mac_add(zvni, macaddr);
5401 if (!mac) {
2853fed6 5402 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
d62a17ae 5403 prefix_mac2str(macaddr, buf, sizeof(buf)),
5404 ifp->name, ifp->ifindex, vid);
5405 return -1;
5406 }
5407 }
5408
5409 /* Set "local" forwarding info. */
5410 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
b6938a74 5411 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 5412 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
b6938a74 5413 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
d62a17ae 5414 mac->fwd_info.local.ifindex = ifp->ifindex;
5415 mac->fwd_info.local.vid = vid;
5416
5417 if (sticky)
5418 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5419 else
5420 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5421
5422 /* Inform BGP if required. */
b6938a74 5423 if (add) {
2853fed6 5424 zvni_process_neigh_on_local_mac_add(zvni, mac);
5425 return zvni_mac_send_add_to_client(zvni->vni, macaddr,
b6938a74
MK
5426 sticky);
5427 }
d62a17ae 5428
5429 return 0;
2232a77c 5430}
13d60d35 5431
5432/*
5433 * Handle message from client to delete a remote VTEP for a VNI.
5434 */
e4bd522a 5435int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
d62a17ae 5436 struct zebra_vrf *zvrf)
5437{
5438 struct stream *s;
5439 u_short l = 0;
5440 vni_t vni;
5441 struct in_addr vtep_ip;
5442 zebra_vni_t *zvni;
5443 zebra_vtep_t *zvtep;
b5ebdc9b 5444 struct interface *ifp;
5445 struct zebra_if *zif;
d62a17ae 5446
ec93aa12
DS
5447 if (!is_evpn_enabled()) {
5448 zlog_warn("%s: EVPN is not enabled yet we have received a vtep del command",
5449 __PRETTY_FUNCTION__);
5450 return -1;
5451 }
5452
2853fed6 5453 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5454 zlog_err("Recv MACIP DEL for non-default VRF %u",
5455 zvrf_id(zvrf));
5456 return -1;
5457 }
5458
d62a17ae 5459 s = client->ibuf;
5460
5461 while (l < length) {
5462 /* Obtain each remote VTEP and process. */
ec93aa12 5463 STREAM_GETL(s, vni);
d62a17ae 5464 l += 4;
ec93aa12 5465 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5466 l += IPV4_MAX_BYTELEN;
5467
5468 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5469 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5470 inet_ntoa(vtep_ip), vni,
d62a17ae 5471 zebra_route_string(client->proto));
5472
5473 /* Locate VNI hash entry - expected to exist. */
2853fed6 5474 zvni = zvni_lookup(vni);
d62a17ae 5475 if (!zvni) {
5476 if (IS_ZEBRA_DEBUG_VXLAN)
5477 zlog_debug(
5478 "Failed to locate VNI hash upon remote VTEP DEL, "
2853fed6 5479 "VNI %u",
5480 vni);
d62a17ae 5481 continue;
5482 }
5483
b5ebdc9b 5484 ifp = zvni->vxlan_if;
5485 if (!ifp) {
60466a63
QY
5486 zlog_err(
5487 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5488 zvni->vni, zvni);
b682f6de 5489 continue;
b5ebdc9b 5490 }
5491 zif = ifp->info;
5492
5493 /* If down or not mapped to a bridge, we're done. */
b682f6de 5494 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 5495 continue;
5496
d62a17ae 5497 /* If the remote VTEP does not exist, there's nothing more to
5498 * do.
5499 * Otherwise, uninstall any remote MACs pointing to this VTEP
5500 * and
5501 * then, the VTEP entry itself and remove it.
5502 */
5503 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5504 if (!zvtep)
5505 continue;
5506
5507 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
5508 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
5509 zvni_vtep_uninstall(zvni, &vtep_ip);
5510 zvni_vtep_del(zvni, zvtep);
5511 }
5512
ec93aa12 5513stream_failure:
d62a17ae 5514 return 0;
13d60d35 5515}
5516
5517/*
5518 * Handle message from client to add a remote VTEP for a VNI.
5519 */
e4bd522a 5520int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
d62a17ae 5521 struct zebra_vrf *zvrf)
5522{
5523 struct stream *s;
5524 u_short l = 0;
5525 vni_t vni;
5526 struct in_addr vtep_ip;
5527 zebra_vni_t *zvni;
b5ebdc9b 5528 struct interface *ifp;
5529 struct zebra_if *zif;
d62a17ae 5530
ec93aa12
DS
5531 if (!is_evpn_enabled()) {
5532 zlog_warn("%s: EVPN not enabled yet we received a vtep_add zapi call",
5533 __PRETTY_FUNCTION__);
5534 return -1;
5535 }
5536
2853fed6 5537 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5538 zlog_err("Recv MACIP ADD for non-default VRF %u",
5539 zvrf_id(zvrf));
5540 return -1;
5541 }
d62a17ae 5542
5543 s = client->ibuf;
5544
5545 while (l < length) {
5546 /* Obtain each remote VTEP and process. */
ec93aa12 5547 STREAM_GETL(s, vni);
d62a17ae 5548 l += 4;
ec93aa12 5549 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5550 l += IPV4_MAX_BYTELEN;
5551
5552 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5553 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5554 inet_ntoa(vtep_ip), vni,
d62a17ae 5555 zebra_route_string(client->proto));
5556
5557 /* Locate VNI hash entry - expected to exist. */
2853fed6 5558 zvni = zvni_lookup(vni);
d62a17ae 5559 if (!zvni) {
5560 zlog_err(
2853fed6 5561 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5562 vni);
d62a17ae 5563 continue;
5564 }
b5ebdc9b 5565
5566 ifp = zvni->vxlan_if;
5567 if (!ifp) {
d62a17ae 5568 zlog_err(
5569 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5570 zvni->vni, zvni);
5571 continue;
5572 }
5573
b5ebdc9b 5574 zif = ifp->info;
d62a17ae 5575
b5ebdc9b 5576 /* If down or not mapped to a bridge, we're done. */
b682f6de 5577 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 5578 continue;
5579
b682f6de 5580 /* If the remote VTEP already exists,
5581 there's nothing more to do. */
b5ebdc9b 5582 if (zvni_vtep_find(zvni, &vtep_ip))
d62a17ae 5583 continue;
5584
5585 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5586 zlog_err(
2853fed6 5587 "Failed to add remote VTEP, VNI %u zvni %p",
5588 vni, zvni);
d62a17ae 5589 continue;
5590 }
5591
5592 zvni_vtep_install(zvni, &vtep_ip);
5593 }
5594
ec93aa12 5595stream_failure:
d62a17ae 5596 return 0;
13d60d35 5597}
5598
1a98c087
MK
5599/*
5600 * Add/Del gateway macip to evpn
5601 * g/w can be:
5602 * 1. SVI interface on a vlan aware bridge
5603 * 2. SVI interface on a vlan unaware bridge
5604 * 3. vrr interface (MACVLAN) associated to a SVI
5605 * We advertise macip routes for an interface if it is associated to VxLan vlan
5606 */
5607int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
5608 int add)
5609{
5610 struct ipaddr ip;
5611 struct ethaddr macaddr;
5612 zebra_vni_t *zvni = NULL;
1a98c087
MK
5613
5614 memset(&ip, 0, sizeof(struct ipaddr));
5615 memset(&macaddr, 0, sizeof(struct ethaddr));
5616
2853fed6 5617 /* Check if EVPN is enabled. */
5618 if (!is_evpn_enabled())
297a21b6
MK
5619 return 0;
5620
1a98c087
MK
5621 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
5622 struct interface *svi_if =
5623 NULL; /* SVI corresponding to the MACVLAN */
5624 struct zebra_if *ifp_zif =
5625 NULL; /* Zebra daemon specific info for MACVLAN */
5626 struct zebra_if *svi_if_zif =
5627 NULL; /* Zebra daemon specific info for SVI*/
5628
5629 ifp_zif = ifp->info;
5630 if (!ifp_zif)
5631 return -1;
5632
71349e03
MK
5633 /*
5634 * for a MACVLAN interface the link represents the svi_if
5635 */
5636 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
5637 ifp_zif->link_ifindex);
1a98c087 5638 if (!svi_if) {
2853fed6 5639 zlog_err("MACVLAN %s(%u) without link information",
5640 ifp->name, ifp->ifindex);
1a98c087
MK
5641 return -1;
5642 }
5643
5644 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
5645 /*
5646 * If it is a vlan aware bridge then the link gives the
5647 * bridge information
5648 */
5649 struct interface *svi_if_link = NULL;
5650
1a98c087 5651 svi_if_zif = svi_if->info;
71349e03
MK
5652 if (svi_if_zif) {
5653 svi_if_link = if_lookup_by_index_per_ns(
60466a63
QY
5654 zebra_ns_lookup(NS_DEFAULT),
5655 svi_if_zif->link_ifindex);
b7cfce93 5656 zvni = zvni_from_svi(svi_if, svi_if_link);
71349e03 5657 }
1a98c087 5658 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
5659 /*
5660 * If it is a vlan unaware bridge then svi is the bridge
5661 * itself
5662 */
b7cfce93 5663 zvni = zvni_from_svi(svi_if, svi_if);
1a98c087
MK
5664 }
5665 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
5666 struct zebra_if *svi_if_zif =
71349e03
MK
5667 NULL; /* Zebra daemon specific info for SVI */
5668 struct interface *svi_if_link =
5669 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
5670
5671 svi_if_zif = ifp->info;
60466a63
QY
5672 svi_if_link = if_lookup_by_index_per_ns(
5673 zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex);
71349e03 5674 if (svi_if_zif && svi_if_link)
b7cfce93 5675 zvni = zvni_from_svi(ifp, svi_if_link);
1a98c087 5676 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
b7cfce93 5677 zvni = zvni_from_svi(ifp, ifp);
1a98c087
MK
5678 }
5679
5680 if (!zvni)
5681 return 0;
5682
5683 if (!zvni->vxlan_if) {
5684 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5685 zvni->vni, zvni);
5686 return -1;
5687 }
5688
1a98c087
MK
5689
5690 /* check if we are advertising gw macip routes */
2853fed6 5691 if (!advertise_gw_macip_enabled(zvni))
1a98c087
MK
5692 return 0;
5693
5694 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
5695
5696 if (p->family == AF_INET) {
5697 ip.ipa_type = IPADDR_V4;
5698 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
5699 sizeof(struct in_addr));
5700 } else if (p->family == AF_INET6) {
5701 ip.ipa_type = IPADDR_V6;
5702 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
5703 sizeof(struct in6_addr));
5704 }
5705
5706
5707 if (add)
5708 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
5709 else
5710 zvni_gw_macip_del(ifp, zvni, &ip);
5711
5712 return 0;
5713}
5714
2232a77c 5715/*
b7cfce93
MK
5716 * Handle SVI interface going down.
5717 * SVI can be associated to either L3-VNI or L2-VNI.
5718 * For L2-VNI: At this point, this is a NOP since
5719 * the kernel deletes the neighbor entries on this SVI (if any).
5720 * We only need to update the vrf corresponding to zvni.
5721 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5722 * from bgp
2232a77c 5723 */
d62a17ae 5724int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 5725{
b7cfce93
MK
5726 zebra_l3vni_t *zl3vni = NULL;
5727
5728 zl3vni = zl3vni_from_svi(ifp, link_if);
5729 if (zl3vni) {
5730
5731 /* process l3-vni down */
5732 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5733
5734 /* remove association with svi-if */
5735 zl3vni->svi_if = NULL;
5736 } else {
5737 zebra_vni_t *zvni = NULL;
5738
5739 /* since we dont have svi corresponding to zvni, we associate it
5740 * to default vrf. Note: the corresponding neigh entries on the
5741 * SVI would have already been deleted */
5742 zvni = zvni_from_svi(ifp, link_if);
5743 if (zvni) {
5744 zvni->vrf_id = VRF_DEFAULT;
5745
5746 /* update the tenant vrf in BGP */
5747 zvni_send_add_to_client(zvni);
5748 }
5749 }
d62a17ae 5750 return 0;
2232a77c 5751}
5752
5753/*
b7cfce93
MK
5754 * Handle SVI interface coming up.
5755 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5756 * vxlan intf).
5757 * For L2-VNI: we need to install any remote neighbors entried (used for
5758 * apr-suppression)
5759 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
2232a77c 5760 */
d62a17ae 5761int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 5762{
b7cfce93
MK
5763 zebra_vni_t *zvni = NULL;
5764 zebra_l3vni_t *zl3vni = NULL;
2232a77c 5765
b7cfce93
MK
5766 zl3vni = zl3vni_from_svi(ifp, link_if);
5767 if (zl3vni) {
2232a77c 5768
b7cfce93
MK
5769 /* associate with svi */
5770 zl3vni->svi_if = ifp;
2232a77c 5771
b7cfce93
MK
5772 /* process oper-up */
5773 if (is_l3vni_oper_up(zl3vni))
5774 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5775 } else {
5776
5777 /* process SVI up for l2-vni */
5778 struct neigh_walk_ctx n_wctx;
5779
5780 zvni = zvni_from_svi(ifp, link_if);
5781 if (!zvni)
5782 return 0;
5783
5784 if (!zvni->vxlan_if) {
5785 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
5786 zvni->vni, zvni);
5787 return -1;
5788 }
5789
5790 if (IS_ZEBRA_DEBUG_VXLAN)
5791 zlog_debug("SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
5792 ifp->name, ifp->ifindex, zvni->vni,
5793 vrf_id_to_name(ifp->vrf_id));
2232a77c 5794
b7cfce93
MK
5795 /* update the vrf information for l2-vni and inform bgp */
5796 zvni->vrf_id = ifp->vrf_id;
5797 zvni_send_add_to_client(zvni);
5798
5799 /* Install any remote neighbors for this VNI. */
5800 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
5801 n_wctx.zvni = zvni;
5802 hash_iterate(zvni->neigh_table,
5803 zvni_install_neigh_hash,
5804 &n_wctx);
5805 }
2232a77c 5806
d62a17ae 5807 return 0;
2232a77c 5808}
5809
13d60d35 5810/*
b7cfce93 5811 * Handle VxLAN interface down
13d60d35 5812 */
d62a17ae 5813int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 5814{
d62a17ae 5815 vni_t vni;
b7cfce93
MK
5816 struct zebra_if *zif = NULL;
5817 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 5818
2853fed6 5819 /* Check if EVPN is enabled. */
5820 if (!is_evpn_enabled())
d62a17ae 5821 return 0;
13d60d35 5822
d62a17ae 5823 zif = ifp->info;
5824 assert(zif);
5825 vxl = &zif->l2info.vxl;
5826 vni = vxl->vni;
13d60d35 5827
13d60d35 5828
b7cfce93
MK
5829 if (is_vni_l3(vni)) {
5830
5831 /* process-if-down for l3-vni */
5832 zebra_l3vni_t *zl3vni = NULL;
5833
5834 if (IS_ZEBRA_DEBUG_VXLAN)
5835 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN",
5836 ifp->name, ifp->ifindex, vni);
5837
5838 zl3vni = zl3vni_lookup(vni);
5839 if (!zl3vni) {
5840 zlog_err(
5841 "Failed to locate L3-VNI hash at DOWN, IF %s(%u) VNI %u",
5842 ifp->name, ifp->ifindex, vni);
5843 return -1;
5844 }
5845
5846 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5847
5848 } else {
5849 /* process if-down for l2-vni */
5850 zebra_vni_t *zvni;
5851
5852 if (IS_ZEBRA_DEBUG_VXLAN)
5853 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN",
5854 ifp->name, ifp->ifindex, vni);
13d60d35 5855
b7cfce93
MK
5856 /* Locate hash entry; it is expected to exist. */
5857 zvni = zvni_lookup(vni);
5858 if (!zvni) {
5859 zlog_err(
5860 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
5861 ifp->name, ifp->ifindex, vni);
5862 return -1;
5863 }
13d60d35 5864
b7cfce93 5865 assert(zvni->vxlan_if == ifp);
13d60d35 5866
b7cfce93
MK
5867 /* Delete this VNI from BGP. */
5868 zvni_send_del_to_client(zvni->vni);
2232a77c 5869
b7cfce93
MK
5870 /* Free up all neighbors and MACs, if any. */
5871 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
5872 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
13d60d35 5873
b7cfce93
MK
5874 /* Free up all remote VTEPs, if any. */
5875 zvni_vtep_del_all(zvni, 1);
5876 }
d62a17ae 5877 return 0;
13d60d35 5878}
5879
5880/*
5881 * Handle VxLAN interface up - update BGP if required.
5882 */
d62a17ae 5883int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 5884{
d62a17ae 5885 vni_t vni;
b7cfce93
MK
5886 struct zebra_if *zif = NULL;
5887 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 5888
2853fed6 5889 /* Check if EVPN is enabled. */
5890 if (!is_evpn_enabled())
d62a17ae 5891 return 0;
13d60d35 5892
d62a17ae 5893 zif = ifp->info;
5894 assert(zif);
5895 vxl = &zif->l2info.vxl;
5896 vni = vxl->vni;
13d60d35 5897
b7cfce93 5898 if (is_vni_l3(vni)) {
13d60d35 5899
b7cfce93
MK
5900 /* Handle L3-VNI add */
5901 zebra_l3vni_t *zl3vni = NULL;
13d60d35 5902
b7cfce93
MK
5903 if (IS_ZEBRA_DEBUG_VXLAN)
5904 zlog_debug("Intf %s(%u) L3-VNI %u is UP",
5905 ifp->name, ifp->ifindex, vni);
13d60d35 5906
b7cfce93
MK
5907 zl3vni = zl3vni_lookup(vni);
5908 if (!zl3vni) {
5909 zlog_err(
5910 "Failed to locate L3-VNI hash at UP, IF %s(%u) VNI %u",
5911 ifp->name, ifp->ifindex, vni);
5912 return -1;
5913 }
5914
5915 /* we need to associate with SVI, if any, we can associate with
523cafc4 5916 * svi-if only after association with vxlan-intf is complete
5917 */
b7cfce93
MK
5918 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5919
5920 if (is_l3vni_oper_up(zl3vni))
5921 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5922 } else {
5923 /* Handle L2-VNI add */
5924
5925 zebra_vni_t *zvni = NULL;
5926 zebra_l3vni_t *zl3vni = NULL;
5927 struct interface *vlan_if = NULL;
5928
5929 if (IS_ZEBRA_DEBUG_VXLAN)
5930 zlog_debug("Intf %s(%u) L2-VNI %u is UP",
5931 ifp->name, ifp->ifindex, vni);
5932
5933 /* Locate hash entry; it is expected to exist. */
5934 zvni = zvni_lookup(vni);
5935 if (!zvni) {
5936 zlog_err(
5937 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
5938 ifp->name, ifp->ifindex, vni);
5939 return -1;
5940 }
5941
5942 assert(zvni->vxlan_if == ifp);
5943 vlan_if = zvni_map_to_svi(vxl->access_vlan,
5944 zif->brslave_info.br_if);
5945 if (vlan_if) {
5946 zvni->vrf_id = vlan_if->vrf_id;
5947 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
5948 if (zl3vni)
5949 listnode_add_sort(zl3vni->l2vnis, zvni);
5950 }
5951
5952 /* If part of a bridge, inform BGP about this VNI. */
5953 /* Also, read and populate local MACs and neighbors. */
5954 if (zif->brslave_info.br_if) {
5955 zvni_send_add_to_client(zvni);
5956 zvni_read_mac_neigh(zvni, ifp);
5957 }
d62a17ae 5958 }
13d60d35 5959
d62a17ae 5960 return 0;
13d60d35 5961}
5962
5963/*
5964 * Handle VxLAN interface delete. Locate and remove entry in hash table
5965 * and update BGP, if required.
5966 */
d62a17ae 5967int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 5968{
d62a17ae 5969 vni_t vni;
b7cfce93
MK
5970 struct zebra_if *zif = NULL;
5971 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 5972
2853fed6 5973 /* Check if EVPN is enabled. */
5974 if (!is_evpn_enabled())
d62a17ae 5975 return 0;
13d60d35 5976
d62a17ae 5977 zif = ifp->info;
5978 assert(zif);
5979 vxl = &zif->l2info.vxl;
5980 vni = vxl->vni;
13d60d35 5981
b7cfce93 5982 if (is_vni_l3(vni)) {
13d60d35 5983
b7cfce93
MK
5984 /* process if-del for l3-vni */
5985 zebra_l3vni_t *zl3vni = NULL;
5986
5987 if (IS_ZEBRA_DEBUG_VXLAN)
5988 zlog_debug("Del L3-VNI %u intf %s(%u)",
5989 vni, ifp->name, ifp->ifindex);
13d60d35 5990
b7cfce93
MK
5991 zl3vni = zl3vni_lookup(vni);
5992 if (!zl3vni) {
5993 zlog_err(
5994 "Failed to locate L3-VNI hash at del, IF %s(%u) VNI %u",
5995 ifp->name, ifp->ifindex, vni);
5996 return 0;
5997 }
13d60d35 5998
b7cfce93
MK
5999 /* process oper-down for l3-vni */
6000 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2232a77c 6001
b7cfce93 6002 /* remove the association with vxlan_if */
b67a60d2 6003 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
b7cfce93
MK
6004 zl3vni->vxlan_if = NULL;
6005 } else {
13d60d35 6006
b7cfce93
MK
6007 /* process if-del for l2-vni*/
6008 zebra_vni_t *zvni = NULL;
6009 zebra_l3vni_t *zl3vni = NULL;
6010
6011 if (IS_ZEBRA_DEBUG_VXLAN)
6012 zlog_debug("Del L2-VNI %u intf %s(%u)",
6013 vni, ifp->name, ifp->ifindex);
6014
6015 /* Locate hash entry; it is expected to exist. */
6016 zvni = zvni_lookup(vni);
6017 if (!zvni) {
6018 zlog_err(
6019 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6020 ifp->name, ifp->ifindex, vni);
6021 return 0;
6022 }
6023
6024 /* remove from l3-vni list */
6025 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
6026 if (zl3vni)
6027 listnode_delete(zl3vni->l2vnis, zvni);
6028
6029 /* Delete VNI from BGP. */
6030 zvni_send_del_to_client(zvni->vni);
6031
6032 /* Free up all neighbors and MAC, if any. */
6033 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
6034 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
6035
6036 /* Free up all remote VTEPs, if any. */
6037 zvni_vtep_del_all(zvni, 0);
6038
6039 /* Delete the hash entry. */
6040 if (zvni_del(zvni)) {
6041 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6042 zvni, ifp->name, ifp->ifindex, zvni->vni);
6043 return -1;
6044 }
d62a17ae 6045 }
13d60d35 6046
d62a17ae 6047 return 0;
13d60d35 6048}
6049
6050/*
6051 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6052 */
d62a17ae 6053int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
6054{
d62a17ae 6055 vni_t vni;
b7cfce93
MK
6056 struct zebra_if *zif = NULL;
6057 struct zebra_l2info_vxlan *vxl = NULL;
d62a17ae 6058
2853fed6 6059 /* Check if EVPN is enabled. */
6060 if (!is_evpn_enabled())
d62a17ae 6061 return 0;
6062
6063 zif = ifp->info;
6064 assert(zif);
6065 vxl = &zif->l2info.vxl;
6066 vni = vxl->vni;
6067
b7cfce93
MK
6068 if (is_vni_l3(vni)) {
6069 zebra_l3vni_t *zl3vni = NULL;
d62a17ae 6070
b7cfce93
MK
6071 zl3vni = zl3vni_lookup(vni);
6072 if (!zl3vni) {
6073 zlog_err(
6074 "Failed to find L3-VNI hash on update, IF %s(%u) VNI %u",
6075 ifp->name, ifp->ifindex, vni);
6076 return -1;
6077 }
af026ae4 6078
b7cfce93
MK
6079 if (IS_ZEBRA_DEBUG_VXLAN)
6080 zlog_debug(
6081 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6082 vni, ifp->name, ifp->ifindex,
6083 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6084 zif->brslave_info.bridge_ifindex, chgflags);
6085
6086 /* Removed from bridge? Cleanup and return */
6087 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6088 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6089 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6090 return 0;
6091 }
6092
6093 /* access-vlan change - process oper down, associate with new
523cafc4 6094 * svi_if and then process oper up again
6095 */
b7cfce93
MK
6096 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6097 if (if_is_operative(ifp)) {
6098 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6099 zl3vni->svi_if = NULL;
6100 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6101 if (is_l3vni_oper_up(zl3vni))
6102 zebra_vxlan_process_l3vni_oper_up(
6103 zl3vni);
6104 }
6105 }
d62a17ae 6106
b7cfce93
MK
6107 /* if we have a valid new master, process l3-vni oper up */
6108 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
6109 if (is_l3vni_oper_up(zl3vni))
6110 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6111 }
6112 } else {
6113 zebra_vni_t *zvni = NULL;
d62a17ae 6114
b7cfce93
MK
6115 /* Update VNI hash. */
6116 zvni = zvni_lookup(vni);
6117 if (!zvni) {
6118 zlog_err(
6119 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6120 ifp->name, ifp->ifindex, vni);
6121 return -1;
6122 }
d62a17ae 6123
b7cfce93
MK
6124 if (IS_ZEBRA_DEBUG_VXLAN)
6125 zlog_debug(
6126 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6127 vni, ifp->name, ifp->ifindex,
6128 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6129 zif->brslave_info.bridge_ifindex, chgflags);
6130
6131 /* Removed from bridge? Cleanup and return */
6132 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6133 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6134 /* Delete from client, remove all remote VTEPs */
6135 /* Also, free up all MACs and neighbors. */
6136 zvni_send_del_to_client(zvni->vni);
6137 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
6138 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
6139 zvni_vtep_del_all(zvni, 1);
6140 return 0;
6141 }
d62a17ae 6142
b7cfce93
MK
6143 /* Handle other changes. */
6144 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6145 /* Remove all existing local neigh and MACs for this VNI
6146 * (including from BGP)
6147 */
6148 zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6149 zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6150 }
d62a17ae 6151
b7cfce93
MK
6152 zvni->local_vtep_ip = vxl->vtep_ip;
6153 zvni->vxlan_if = ifp;
d62a17ae 6154
b7cfce93
MK
6155 /* Take further actions needed.
6156 * Note that if we are here, there is a change of interest.
6157 */
6158 /* If down or not mapped to a bridge, we're done. */
6159 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6160 return 0;
d62a17ae 6161
b7cfce93
MK
6162 /* Inform BGP, if there is a change of interest. */
6163 if (chgflags
6164 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
6165 zvni_send_add_to_client(zvni);
6166
6167 /* If there is a valid new master or a VLAN mapping change,
6168 * read and populate local MACs and neighbors.
6169 * Also, reinstall any remote MACs and neighbors
6170 * for this VNI (based on new VLAN).
6171 */
6172 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6173 zvni_read_mac_neigh(zvni, ifp);
6174 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6175 struct mac_walk_ctx m_wctx;
6176 struct neigh_walk_ctx n_wctx;
6177
6178 zvni_read_mac_neigh(zvni, ifp);
6179
6180 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6181 m_wctx.zvni = zvni;
6182 hash_iterate(zvni->mac_table,
6183 zvni_install_mac_hash,
6184 &m_wctx);
6185
6186 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6187 n_wctx.zvni = zvni;
6188 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
6189 &n_wctx);
6190 }
d62a17ae 6191 }
6192
6193 return 0;
13d60d35 6194}
6195
6196/*
6197 * Handle VxLAN interface add.
6198 */
d62a17ae 6199int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 6200{
d62a17ae 6201 vni_t vni;
b7cfce93
MK
6202 struct zebra_if *zif = NULL;
6203 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 6204
2853fed6 6205 /* Check if EVPN is enabled. */
6206 if (!is_evpn_enabled())
d62a17ae 6207 return 0;
13d60d35 6208
d62a17ae 6209 zif = ifp->info;
6210 assert(zif);
6211 vxl = &zif->l2info.vxl;
6212 vni = vxl->vni;
13d60d35 6213
b7cfce93 6214 if (is_vni_l3(vni)) {
13d60d35 6215
b7cfce93
MK
6216 /* process if-add for l3-vni*/
6217 zebra_l3vni_t *zl3vni = NULL;
6218
6219 if (IS_ZEBRA_DEBUG_VXLAN)
6220 zlog_debug(
6221 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6222 vni, ifp->name, ifp->ifindex,
6223 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6224 zif->brslave_info.bridge_ifindex);
6225
6226 /*
6227 * we expect the l3-vni has entry to be present here.
6228 * The only place l3-vni is created in zebra is vrf-vni mapping
6229 * command. This might change when we have the switchd support
6230 * for l3-vxlan interface.
6231 */
6232 zl3vni = zl3vni_lookup(vni);
6233 if (!zl3vni) {
d62a17ae 6234 zlog_err(
b7cfce93 6235 "Failed to locate L3-VNI hash at del, IF %s(%u) VNI %u",
2853fed6 6236 ifp->name, ifp->ifindex, vni);
b7cfce93
MK
6237 return 0;
6238 }
6239
6240 /* associate with vxlan_if */
b67a60d2 6241 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
6242 zl3vni->vxlan_if = ifp;
6243
6244 /* Associate with SVI, if any. We can associate with svi-if only
6245 * after association with vxlan_if is complete */
6246 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6247
6248 if (is_l3vni_oper_up(zl3vni))
6249 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6250 } else {
6251
6252 /* process if-add for l2-vni */
6253 zebra_vni_t *zvni = NULL;
6254 zebra_l3vni_t *zl3vni = NULL;
6255 struct interface *vlan_if = NULL;
6256
6257 /* Create or update VNI hash. */
6258 zvni = zvni_lookup(vni);
6259 if (!zvni) {
6260 zvni = zvni_add(vni);
6261 if (!zvni) {
6262 zlog_err(
6263 "Failed to add VNI hash, IF %s(%u) VNI %u",
6264 ifp->name, ifp->ifindex, vni);
6265 return -1;
6266 }
6267 }
6268
6269 zvni->local_vtep_ip = vxl->vtep_ip;
6270 zvni->vxlan_if = ifp;
6271 vlan_if = zvni_map_to_svi(vxl->access_vlan,
6272 zif->brslave_info.br_if);
6273 if (vlan_if) {
6274 zvni->vrf_id = vlan_if->vrf_id;
6275 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
6276 if (zl3vni)
6277 listnode_add_sort(zl3vni->l2vnis, zvni);
6278 }
6279
6280 if (IS_ZEBRA_DEBUG_VXLAN)
6281 zlog_debug(
6282 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6283 vni,
6284 vlan_if ? vrf_id_to_name(vlan_if->vrf_id) :
6285 "Default",
6286 ifp->name, ifp->ifindex,
6287 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6288 zif->brslave_info.bridge_ifindex);
6289
6290 /* If down or not mapped to a bridge, we're done. */
6291 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6292 return 0;
6293
6294 /* Inform BGP */
6295 zvni_send_add_to_client(zvni);
6296
6297 /* Read and populate local MACs and neighbors */
6298 zvni_read_mac_neigh(zvni, ifp);
6299 }
6300
6301 return 0;
6302}
6303
6304int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf,
3f02fbab 6305 vni_t vni,
6306 char *err, int err_str_sz,
b7cfce93
MK
6307 int add)
6308{
6309 zebra_l3vni_t *zl3vni = NULL;
6310 struct zebra_vrf *zvrf_default = NULL;
6311
6312 zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
6313 if (!zvrf_default)
6314 return -1;
6315
6316 if (IS_ZEBRA_DEBUG_VXLAN)
6317 zlog_debug("vrf %s vni %u %s",
6318 zvrf_name(zvrf),
6319 vni,
6320 add ? "ADD" : "DEL");
6321
6322 if (add) {
6323
6324 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
6325
6326 /* check if the vni is already present under zvrf */
6327 if (zvrf->l3vni) {
3f02fbab 6328 snprintf(err, err_str_sz,
b7cfce93
MK
6329 "VNI is already configured under the vrf");
6330 return -1;
6331 }
6332
6333 /* check if this VNI is already present in the system */
6334 zl3vni = zl3vni_lookup(vni);
6335 if (zl3vni) {
3f02fbab 6336 snprintf(err, err_str_sz,
b7cfce93
MK
6337 "VNI is already configured as L3-VNI");
6338 return -1;
6339 }
6340
6341 /* add the L3-VNI to the global table */
6342 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
6343 if (!zl3vni) {
3f02fbab 6344 snprintf(err, err_str_sz,
b7cfce93
MK
6345 "Could not add L3-VNI");
6346 return -1;
6347 }
6348
6349 /* associate the vrf with vni */
6350 zvrf->l3vni = vni;
6351
6352 /* associate with vxlan-intf;
523cafc4 6353 * we need to associate with the vxlan-intf first
6354 */
b7cfce93
MK
6355 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
6356
6357 /* associate with corresponding SVI interface, we can associate
6358 * with svi-if only after vxlan interface association is
523cafc4 6359 * complete
6360 */
b7cfce93
MK
6361 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6362
6363 /* formulate l2vni list */
6364 hash_iterate(zvrf_default->vni_table,
6365 zvni_add_to_l3vni_list, zl3vni);
6366
6367 if (is_l3vni_oper_up(zl3vni))
6368 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6369
6370 } else {
6371 zl3vni = zl3vni_lookup(vni);
6372 if (!zl3vni) {
3f02fbab 6373 snprintf(err, err_str_sz, "VNI doesn't exist");
d62a17ae 6374 return -1;
6375 }
b7cfce93
MK
6376
6377 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6378
5e06422c
MK
6379 /* delete and uninstall all rmacs */
6380 hash_iterate(zl3vni->rmac_table,
6381 zl3vni_del_rmac_hash_entry,
6382 zl3vni);
6383
6384 /* delete and uninstall all next-hops */
6385 hash_iterate(zl3vni->nh_table,
6386 zl3vni_del_nh_hash_entry,
6387 zl3vni);
6388
b7cfce93
MK
6389 zvrf->l3vni = 0;
6390 zl3vni_del(zl3vni);
6391
6392 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
d62a17ae 6393 }
b7cfce93
MK
6394 return 0;
6395}
13d60d35 6396
b7cfce93
MK
6397int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
6398{
6399 zebra_l3vni_t *zl3vni = NULL;
13d60d35 6400
b7cfce93
MK
6401 zl3vni = zl3vni_from_vrf(zvrf_id(zvrf));
6402 if (!zl3vni)
d62a17ae 6403 return 0;
13d60d35 6404
b7cfce93
MK
6405 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6406 zl3vni_del(zl3vni);
6407 zebra_vxlan_handle_vni_transition(zvrf, zl3vni->vni, 0);
2232a77c 6408
d62a17ae 6409 return 0;
13d60d35 6410}
6411
1a98c087
MK
6412/*
6413 * Handle message from client to enable/disable advertisement of g/w macip
6414 * routes
6415 */
e4bd522a
DS
6416int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
6417 struct zebra_vrf *zvrf)
1a98c087
MK
6418{
6419 struct stream *s;
6420 int advertise;
6421 vni_t vni = 0;
6422 zebra_vni_t *zvni = NULL;
b5ebdc9b 6423 struct interface *ifp = NULL;
1a98c087 6424
2853fed6 6425 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6426 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6427 zvrf_id(zvrf));
6428 return -1;
6429 }
6430
1a98c087 6431 s = client->ibuf;
ec93aa12
DS
6432 STREAM_GETC(s, advertise);
6433 STREAM_GET(&vni, s, 3);
1a98c087
MK
6434
6435 if (!vni) {
6436 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 6437 zlog_debug("EVPN gateway macip Adv %s, currently %s",
1a98c087 6438 advertise ? "enabled" : "disabled",
2853fed6 6439 advertise_gw_macip_enabled(NULL)
1a98c087
MK
6440 ? "enabled"
6441 : "disabled");
6442
6443 if (zvrf->advertise_gw_macip == advertise)
6444 return 0;
6445
6446 zvrf->advertise_gw_macip = advertise;
6447
2853fed6 6448 if (advertise_gw_macip_enabled(zvni))
1a98c087 6449 hash_iterate(zvrf->vni_table,
2853fed6 6450 zvni_gw_macip_add_for_vni_hash, NULL);
1a98c087
MK
6451 else
6452 hash_iterate(zvrf->vni_table,
2853fed6 6453 zvni_gw_macip_del_for_vni_hash, NULL);
1a98c087
MK
6454
6455 } else {
6456 struct zebra_if *zif = NULL;
6457 struct zebra_l2info_vxlan zl2_info;
6458 struct interface *vlan_if = NULL;
6459 struct interface *vrr_if = NULL;
6460
6461 if (IS_ZEBRA_DEBUG_VXLAN)
6462 zlog_debug(
2853fed6 6463 "EVPN gateway macip Adv %s on VNI %d , currently %s",
1a98c087 6464 advertise ? "enabled" : "disabled", vni,
2853fed6 6465 advertise_gw_macip_enabled(zvni)
1a98c087
MK
6466 ? "enabled"
6467 : "disabled");
6468
2853fed6 6469 zvni = zvni_lookup(vni);
1a98c087
MK
6470 if (!zvni)
6471 return 0;
6472
6473 if (zvni->advertise_gw_macip == advertise)
6474 return 0;
6475
6476 zvni->advertise_gw_macip = advertise;
6477
b5ebdc9b 6478 ifp = zvni->vxlan_if;
6479 if (!ifp)
6480 return 0;
6481
6482 zif = ifp->info;
6483
6484 /* If down or not mapped to a bridge, we're done. */
b682f6de 6485 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 6486 return 0;
6487
1a98c087
MK
6488 zl2_info = zif->l2info.vxl;
6489
2853fed6 6490 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
1a98c087
MK
6491 zif->brslave_info.br_if);
6492 if (!vlan_if)
6493 return 0;
6494
2853fed6 6495 if (advertise_gw_macip_enabled(zvni)) {
1a98c087
MK
6496 /* Add primary SVI MAC-IP */
6497 zvni_add_macip_for_intf(vlan_if, zvni);
6498
6499 /* Add VRR MAC-IP - if any*/
6500 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6501 if (vrr_if)
6502 zvni_add_macip_for_intf(vrr_if, zvni);
6503 } else {
6504 /* Del primary MAC-IP */
6505 zvni_del_macip_for_intf(vlan_if, zvni);
6506
6507 /* Del VRR MAC-IP - if any*/
6508 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6509 if (vrr_if)
6510 zvni_del_macip_for_intf(vrr_if, zvni);
6511 }
6512 }
6513
ec93aa12 6514stream_failure:
1a98c087
MK
6515 return 0;
6516}
6517
6518
13d60d35 6519/*
6520 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6521 * When enabled, the VNI hash table will be built and MAC FDB table read;
6522 * when disabled, the entries should be deleted and remote VTEPs and MACs
6523 * uninstalled from the kernel.
6524 */
e4bd522a 6525int zebra_vxlan_advertise_all_vni(struct zserv *client,
d62a17ae 6526 u_short length, struct zebra_vrf *zvrf)
13d60d35 6527{
655b04d1
MK
6528 struct stream *s = NULL;
6529 int advertise = 0;
6530 struct zebra_ns *zns = NULL;
13d60d35 6531
2853fed6 6532 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6533 zlog_err("EVPN VNI Adv for non-default VRF %u",
6534 zvrf_id(zvrf));
6535 return -1;
6536 }
6537
d62a17ae 6538 s = client->ibuf;
ec93aa12 6539 STREAM_GETC(s, advertise);
13d60d35 6540
d62a17ae 6541 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 6542 zlog_debug("EVPN VNI Adv %s, currently %s",
d62a17ae 6543 advertise ? "enabled" : "disabled",
2853fed6 6544 is_evpn_enabled() ? "enabled" : "disabled");
13d60d35 6545
d62a17ae 6546 if (zvrf->advertise_all_vni == advertise)
6547 return 0;
13d60d35 6548
d62a17ae 6549 zvrf->advertise_all_vni = advertise;
2853fed6 6550 if (is_evpn_enabled()) {
d62a17ae 6551 /* Build VNI hash table and inform BGP. */
2853fed6 6552 zvni_build_hash_table();
2232a77c 6553
1a98c087
MK
6554 /* Add all SVI (L3 GW) MACs to BGP*/
6555 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
2853fed6 6556 NULL);
1a98c087 6557
d62a17ae 6558 /* Read the MAC FDB */
6559 macfdb_read(zvrf->zns);
2232a77c 6560
d62a17ae 6561 /* Read neighbors */
6562 neigh_read(zvrf->zns);
6563 } else {
6564 /* Cleanup VTEPs for all VNIs - uninstall from
6565 * kernel and free entries.
6566 */
6567 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
655b04d1
MK
6568
6569 /* cleanup all l3vnis */
6570 zns = zebra_ns_lookup(NS_DEFAULT);
6571 if (!zns)
6572 return -1;
6573
6574 hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
d62a17ae 6575 }
13d60d35 6576
ec93aa12 6577stream_failure:
d62a17ae 6578 return 0;
13d60d35 6579}
6580
6581/*
6582 * Allocate VNI hash table for this VRF and do other initialization.
6583 * NOTE: Currently supported only for default VRF.
6584 */
d62a17ae 6585void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 6586{
d62a17ae 6587 if (!zvrf)
6588 return;
6589 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
6590 "Zebra VRF VNI Table");
13d60d35 6591}
6592
6593/* Close all VNI handling */
d62a17ae 6594void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 6595{
2853fed6 6596 if (!zvrf)
6597 return;
d62a17ae 6598 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9b67b514 6599 hash_free(zvrf->vni_table);
13d60d35 6600}
b7cfce93
MK
6601
6602/* init the l3vni table */
6603void zebra_vxlan_ns_init(struct zebra_ns *zns)
6604{
6605 zns->l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
6606 "Zebra VRF L3 VNI table");
6607}
6608
6609/* free l3vni table */
6610void zebra_vxlan_ns_disable(struct zebra_ns *zns)
6611{
6612 hash_free(zns->l3vni_table);
6613}
d3135ba3 6614
6615/* get the l3vni svi ifindex */
6616ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
6617{
6618 zebra_l3vni_t *zl3vni = NULL;
6619
6620 zl3vni = zl3vni_from_vrf(vrf_id);
6621 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
6622 return 0;
6623
6624 return zl3vni->svi_if->ifindex;
6625}