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