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