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