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