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