]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
zebra: json support for show evpn next-hop l3vni <vni>
[mirror_frr.git] / zebra / zebra_vxlan.c
CommitLineData
13d60d35 1/*
2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "if.h"
26#include "prefix.h"
27#include "table.h"
28#include "memory.h"
29#include "log.h"
30#include "linklist.h"
31#include "stream.h"
32#include "hash.h"
33#include "jhash.h"
34#include "vlan.h"
35#include "vxlan.h"
36
37#include "zebra/rib.h"
38#include "zebra/rt.h"
39#include "zebra/zebra_ns.h"
40#include "zebra/zserv.h"
41#include "zebra/debug.h"
42#include "zebra/interface.h"
43#include "zebra/zebra_vrf.h"
44#include "zebra/rt_netlink.h"
45#include "zebra/zebra_vxlan_private.h"
46#include "zebra/zebra_vxlan.h"
47#include "zebra/zebra_memory.h"
48#include "zebra/zebra_l2.h"
cd233079 49#include "lib/json.h"
13d60d35 50
6134fd82 51DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
d62a17ae 52DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
b7cfce93 53DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
13d60d35 54DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP");
d62a17ae 55DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC");
56DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
13d60d35 57
58/* definitions */
59
60
61/* static function declarations */
cd233079 62static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
d62a17ae 63static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
64static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
cd233079 65 void **args);
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 3820 json_object *json = NULL;
b7cfce93
MK
3821 zebra_l3vni_t *zl3vni = NULL;
3822
3823 if (!is_evpn_enabled())
3824 return;
3825
3826 zl3vni = zl3vni_lookup(l3vni);
3827 if (!zl3vni) {
3828 if (use_json)
3829 vty_out(vty, "{}\n");
3830 else
3831 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
3832 return;
3833 }
3834
3835 num_nh = hashcount(zl3vni->nh_table);
3836 if (!num_nh)
3837 return;
3838
9187f600 3839 if (use_json)
b7cfce93 3840 json = json_object_new_object();
b7cfce93 3841
2dbad57f 3842 wctx.vty = vty;
9187f600 3843 wctx.json = json;
b7cfce93
MK
3844 if (!use_json) {
3845 vty_out(vty,
3846 "Number of NH Neighbors known for this VNI: %u\n",
3847 num_nh);
2dbad57f 3848 vty_out(vty, "%-15s %-17s %6s\n", "IP",
b7cfce93
MK
3849 "RMAC", "Refcnt");
3850 } else
3851 json_object_int_add(json, "numNh", num_nh);
3852
3853 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
3854
3855 if (use_json) {
b7cfce93
MK
3856 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3857 json, JSON_C_TO_STRING_PRETTY));
3858 json_object_free(json);
3859 }
3860}
3861
3862void zebra_vxlan_print_nh_all_l3vni(struct vty *vty,
3863 u_char use_json)
3864{
2dbad57f 3865 struct zebra_ns *zns = NULL;
2dbad57f 3866 json_object *json = NULL;
32798965 3867 void *args[2];
2dbad57f 3868
3869 if (!is_evpn_enabled()) {
3870 if (use_json)
3871 vty_out(vty, "{}\n");
3872 return;
3873 }
3874
3875 zns = zebra_ns_lookup(NS_DEFAULT);
3876 if (!zns)
3877 return;
3878
3879 if (use_json)
3880 json = json_object_new_object();
3881
32798965
MK
3882 args[0] = vty;
3883 args[1] = json;
3884 hash_iterate(zns->l3vni_table,
3885 (void (*)(struct hash_backet *,
3886 void *))zl3vni_print_nh_hash_all_vni,
3887 args);
2dbad57f 3888
3889 if (use_json) {
3890 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3891 json, JSON_C_TO_STRING_PRETTY));
3892 json_object_free(json);
3893 }
b7cfce93
MK
3894 return;
3895}
3896
3897/*
3898 * Display L3 VNI information (VTY command handler).
3899 */
3900void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, u_char use_json)
3901{
3902 void *args[2];
3903 json_object *json = NULL;
3904 zebra_l3vni_t *zl3vni = NULL;
3905
b2ee5a13
MK
3906 if (!is_evpn_enabled()) {
3907 if (use_json)
3908 vty_out(vty, "{}\n");
b7cfce93 3909 return;
b2ee5a13 3910 }
b7cfce93
MK
3911
3912 zl3vni = zl3vni_lookup(vni);
3913 if (!zl3vni) {
3914 if (use_json)
3915 vty_out(vty, "{}\n");
3916 else
3917 vty_out(vty, "%% VNI %u does not exist\n", vni);
3918 return;
3919 }
3920
3921 if (use_json)
3922 json = json_object_new_object();
3923
b2ee5a13
MK
3924 args[0] = vty;
3925 args[1] = json;
b7cfce93
MK
3926 zl3vni_print(zl3vni, (void *)args);
3927
3928 if (use_json) {
3929 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3930 json, JSON_C_TO_STRING_PRETTY));
3931 json_object_free(json);
3932 }
3933}
3934
3935/*
3936 * Display L3 VNI hash table (VTY command handler).
3937 */
3938void zebra_vxlan_print_l3vnis(struct vty *vty, u_char use_json)
3939{
3940 u_int32_t num_vnis;
3941 void *args[2];
3942 json_object *json = NULL;
3943 struct zebra_ns *zns = NULL;
3944
51d8de8f
MK
3945 if (!is_evpn_enabled()) {
3946 if (use_json)
3947 vty_out(vty, "{}\n");
b7cfce93 3948 return;
51d8de8f 3949 }
b7cfce93
MK
3950
3951 zns = zebra_ns_lookup(NS_DEFAULT);
3952 assert(zns);
3953
3954 num_vnis = hashcount(zns->l3vni_table);
3955 if (!num_vnis) {
3956 if (use_json)
3957 vty_out(vty, "{}\n");
3958 return;
3959 }
3960
3961 if (use_json) {
3962 json = json_object_new_object();
3963 json_object_int_add(json, "numVnis", num_vnis);
3964 } else {
3965 vty_out(vty, "Number of L3 VNIs: %u\n", num_vnis);
3966 vty_out(vty, "%-10s %-20s %-20s %-5s %-37s %-18s\n", "VNI",
3967 "Vx-intf", "L3-SVI", "State", "VRF", "Rmac");
3968 }
3969
51d8de8f
MK
3970 args[0] = vty;
3971 args[1] = json;
b7cfce93
MK
3972 hash_iterate(zns->l3vni_table,
3973 (void (*)(struct hash_backet *, void *))zl3vni_print_hash,
3974 args);
3975
3976 if (use_json) {
3977 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3978 json, JSON_C_TO_STRING_PRETTY));
3979 json_object_free(json);
3980 }
3981}
3982
3983/*
3984 * Display Neighbors for a VNI (VTY command handler).
3985 */
3986void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
3987 vni_t vni, u_char use_json)
3988{
3989 zebra_vni_t *zvni;
3990 u_int32_t num_neigh;
3991 struct neigh_walk_ctx wctx;
3992 json_object *json = NULL;
3993
3994 if (!is_evpn_enabled())
3995 return;
3996 zvni = zvni_lookup(vni);
3997 if (!zvni) {
3998 if (use_json)
3999 vty_out(vty, "{}\n");
4000 else
4001 vty_out(vty, "%% VNI %u does not exist\n", vni);
4002 return;
4003 }
4004 num_neigh = hashcount(zvni->neigh_table);
4005 if (!num_neigh)
4006 return;
4007
4008 if (use_json)
4009 json = json_object_new_object();
4010
4011 /* Since we have IPv6 addresses to deal with which can vary widely in
4012 * size, we try to be a bit more elegant in display by first computing
4013 * the maximum width.
4014 */
4015 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4016 wctx.zvni = zvni;
4017 wctx.vty = vty;
4018 wctx.addr_width = 15;
4019 wctx.json = json;
4020 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
4021
4022 if (!use_json) {
4023 vty_out(vty,
4024 "Number of ARPs (local and remote) known for this VNI: %u\n",
4025 num_neigh);
4026 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
4027 "Type", "MAC", "Remote VTEP");
4028 } else
4029 json_object_int_add(json, "numArpNd", num_neigh);
4030
4031 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
4032 if (use_json) {
4033 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4034 json, JSON_C_TO_STRING_PRETTY));
4035 json_object_free(json);
4036 }
4037}
4038
4039/*
4040 * Display neighbors across all VNIs (VTY command handler).
4041 */
4042void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
4043 u_char use_json)
4044{
4045 json_object *json = NULL;
4046 void *args[2];
4047
4048 if (!is_evpn_enabled())
4049 return;
4050
4051 if (use_json)
4052 json = json_object_new_object();
4053
4054 args[0] = vty;
4055 args[1] = json;
4056 hash_iterate(zvrf->vni_table,
4057 (void (*)(struct hash_backet *,
4058 void *))zvni_print_neigh_hash_all_vni,
4059 args);
4060 if (use_json) {
4061 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4062 json, JSON_C_TO_STRING_PRETTY));
4063 json_object_free(json);
4064 }
4065}
4066
4067/*
4068 * Display specific neighbor for a VNI, if present (VTY command handler).
4069 */
4070void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
4071 struct zebra_vrf *zvrf, vni_t vni,
4072 struct ipaddr *ip, u_char use_json)
4073{
4074 zebra_vni_t *zvni;
4075 zebra_neigh_t *n;
4076 json_object *json = NULL;
4077
4078 if (!is_evpn_enabled())
4079 return;
4080 zvni = zvni_lookup(vni);
4081 if (!zvni) {
4082 if (use_json)
cd233079
CS
4083 vty_out(vty, "{}\n");
4084 else
4085 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4086 return;
4087 }
4088 n = zvni_neigh_lookup(zvni, ip);
4089 if (!n) {
cd233079
CS
4090 if (!use_json)
4091 vty_out(vty,
4092 "%% Requested neighbor does not exist in VNI %u\n",
4093 vni);
d62a17ae 4094 return;
4095 }
cd233079
CS
4096 if (use_json)
4097 json = json_object_new_object();
4098
4099 zvni_print_neigh(n, vty, json);
cec2e17d 4100
cd233079
CS
4101 if (use_json) {
4102 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4103 json, JSON_C_TO_STRING_PRETTY));
4104 json_object_free(json);
4105 }
cec2e17d 4106}
4107
4108/*
4109 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4110 * By definition, these are remote neighbors.
4111 */
d62a17ae 4112void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
4113 vni_t vni, struct in_addr vtep_ip,
4114 u_char use_json)
cec2e17d 4115{
d62a17ae 4116 zebra_vni_t *zvni;
4117 u_int32_t num_neigh;
4118 struct neigh_walk_ctx wctx;
cd233079 4119 json_object *json = NULL;
cec2e17d 4120
2853fed6 4121 if (!is_evpn_enabled())
d62a17ae 4122 return;
2853fed6 4123 zvni = zvni_lookup(vni);
d62a17ae 4124 if (!zvni) {
cd233079
CS
4125 if (use_json)
4126 vty_out(vty, "{}\n");
4127 else
4128 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4129 return;
4130 }
4131 num_neigh = hashcount(zvni->neigh_table);
4132 if (!num_neigh)
4133 return;
cec2e17d 4134
d62a17ae 4135 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4136 wctx.zvni = zvni;
4137 wctx.vty = vty;
4138 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
4139 wctx.r_vtep_ip = vtep_ip;
cd233079 4140 wctx.json = json;
d62a17ae 4141 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
4142
4143 if (use_json) {
4144 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4145 json, JSON_C_TO_STRING_PRETTY));
4146 json_object_free(json);
4147 }
cec2e17d 4148}
4149
4150/*
4151 * Display MACs for a VNI (VTY command handler).
4152 */
d62a17ae 4153void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 4154 vni_t vni, u_char use_json)
cec2e17d 4155{
d62a17ae 4156 zebra_vni_t *zvni;
4157 u_int32_t num_macs;
4158 struct mac_walk_ctx wctx;
cd233079
CS
4159 json_object *json = NULL;
4160 json_object *json_mac = NULL;
cec2e17d 4161
2853fed6 4162 if (!is_evpn_enabled())
d62a17ae 4163 return;
2853fed6 4164 zvni = zvni_lookup(vni);
d62a17ae 4165 if (!zvni) {
cd233079
CS
4166 if (use_json)
4167 vty_out(vty, "{}\n");
4168 else
4169 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4170 return;
4171 }
790f8dc5 4172 num_macs = num_valid_macs(zvni);
d62a17ae 4173 if (!num_macs)
4174 return;
cec2e17d 4175
cd233079
CS
4176 if (use_json) {
4177 json = json_object_new_object();
4178 json_mac = json_object_new_object();
4179 }
4180
d62a17ae 4181 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4182 wctx.zvni = zvni;
4183 wctx.vty = vty;
cd233079 4184 wctx.json = json_mac;
cec2e17d 4185
cd233079
CS
4186 if (!use_json) {
4187 vty_out(vty,
4188 "Number of MACs (local and remote) known for this VNI: %u\n",
4189 num_macs);
4190 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4191 "Intf/Remote VTEP", "VLAN");
4192 } else
4193 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 4194
d62a17ae 4195 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
4196
4197 if (use_json) {
4198 json_object_object_add(json, "macs", json_mac);
4199 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4200 json, JSON_C_TO_STRING_PRETTY));
4201 json_object_free(json);
4202 }
cec2e17d 4203}
4204
4205/*
4206 * Display MACs for all VNIs (VTY command handler).
4207 */
cd233079
CS
4208void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
4209 u_char use_json)
cec2e17d 4210{
d62a17ae 4211 struct mac_walk_ctx wctx;
cd233079 4212 json_object *json = NULL;
cec2e17d 4213
2853fed6 4214 if (!is_evpn_enabled()) {
cd233079
CS
4215 if (use_json)
4216 vty_out(vty, "{}\n");
d62a17ae 4217 return;
cd233079
CS
4218 }
4219 if (use_json)
4220 json = json_object_new_object();
4221
d62a17ae 4222 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4223 wctx.vty = vty;
cd233079 4224 wctx.json = json;
d62a17ae 4225 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
4226
4227 if (use_json) {
4228 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4229 json, JSON_C_TO_STRING_PRETTY));
4230 json_object_free(json);
4231 }
cec2e17d 4232}
4233
4234/*
4235 * Display MACs for all VNIs (VTY command handler).
4236 */
d62a17ae 4237void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
4238 struct zebra_vrf *zvrf,
cd233079
CS
4239 struct in_addr vtep_ip,
4240 u_char use_json)
cec2e17d 4241{
d62a17ae 4242 struct mac_walk_ctx wctx;
cd233079 4243 json_object *json = NULL;
cec2e17d 4244
2853fed6 4245 if (!is_evpn_enabled())
d62a17ae 4246 return;
cd233079
CS
4247
4248 if (use_json)
4249 json = json_object_new_object();
4250
d62a17ae 4251 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4252 wctx.vty = vty;
4253 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4254 wctx.r_vtep_ip = vtep_ip;
cd233079 4255 wctx.json = json;
d62a17ae 4256 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
4257
4258 if (use_json) {
4259 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4260 json, JSON_C_TO_STRING_PRETTY));
4261 json_object_free(json);
4262 }
cec2e17d 4263}
4264
4265/*
4266 * Display specific MAC for a VNI, if present (VTY command handler).
4267 */
d62a17ae 4268void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
4269 vni_t vni, struct ethaddr *macaddr)
cec2e17d 4270{
d62a17ae 4271 zebra_vni_t *zvni;
4272 zebra_mac_t *mac;
cec2e17d 4273
2853fed6 4274 if (!is_evpn_enabled())
d62a17ae 4275 return;
2853fed6 4276 zvni = zvni_lookup(vni);
d62a17ae 4277 if (!zvni) {
4278 vty_out(vty, "%% VNI %u does not exist\n", vni);
4279 return;
4280 }
4281 mac = zvni_mac_lookup(zvni, macaddr);
4282 if (!mac) {
4283 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
4284 vni);
4285 return;
4286 }
cec2e17d 4287
d62a17ae 4288 zvni_print_mac(mac, vty);
cec2e17d 4289}
4290
4291/*
4292 * Display MACs for a VNI from specific VTEP (VTY command handler).
4293 */
d62a17ae 4294void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
4295 vni_t vni, struct in_addr vtep_ip,
4296 u_char use_json)
cec2e17d 4297{
d62a17ae 4298 zebra_vni_t *zvni;
4299 u_int32_t num_macs;
4300 struct mac_walk_ctx wctx;
cd233079
CS
4301 json_object *json = NULL;
4302 json_object *json_mac = NULL;
cec2e17d 4303
2853fed6 4304 if (!is_evpn_enabled())
d62a17ae 4305 return;
2853fed6 4306 zvni = zvni_lookup(vni);
d62a17ae 4307 if (!zvni) {
cd233079
CS
4308 if (use_json)
4309 vty_out(vty, "{}\n");
4310 else
4311 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4312 return;
4313 }
790f8dc5 4314 num_macs = num_valid_macs(zvni);
d62a17ae 4315 if (!num_macs)
4316 return;
cd233079
CS
4317
4318 if (use_json) {
4319 json = json_object_new_object();
4320 json_mac = json_object_new_object();
4321 }
4322
d62a17ae 4323 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4324 wctx.zvni = zvni;
4325 wctx.vty = vty;
4326 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4327 wctx.r_vtep_ip = vtep_ip;
cd233079 4328 wctx.json = json_mac;
d62a17ae 4329 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
4330
4331 if (use_json) {
4332 json_object_int_add(json, "numMacs", wctx.count);
4333 if (wctx.count)
4334 json_object_object_add(json, "macs", json_mac);
4335 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4336 json, JSON_C_TO_STRING_PRETTY));
4337 json_object_free(json);
4338 }
cec2e17d 4339}
4340
4341
4342/*
4343 * Display VNI information (VTY command handler).
4344 */
cd233079
CS
4345void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
4346 u_char use_json)
cec2e17d 4347{
d62a17ae 4348 zebra_vni_t *zvni;
cd233079
CS
4349 json_object *json = NULL;
4350 void *args[2];
cec2e17d 4351
2853fed6 4352 if (!is_evpn_enabled())
d62a17ae 4353 return;
2853fed6 4354 zvni = zvni_lookup(vni);
d62a17ae 4355 if (!zvni) {
cd233079
CS
4356 if (use_json)
4357 vty_out(vty, "{}\n");
4358 else
4359 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4360 return;
4361 }
cd233079
CS
4362 if (use_json)
4363 json = json_object_new_object();
4364 args[0] = vty;
4365 args[1] = json;
4366 zvni_print(zvni, (void *)args);
4367 if (use_json) {
4368 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4369 json, JSON_C_TO_STRING_PRETTY));
4370 json_object_free(json);
4371 }
cec2e17d 4372}
4373
4374/*
4375 * Display VNI hash table (VTY command handler).
4376 */
cd233079
CS
4377void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
4378 u_char use_json)
cec2e17d 4379{
d62a17ae 4380 u_int32_t num_vnis;
cd233079
CS
4381 json_object *json = NULL;
4382 void *args[2];
cec2e17d 4383
2853fed6 4384 if (!is_evpn_enabled())
d62a17ae 4385 return;
4386 num_vnis = hashcount(zvrf->vni_table);
cd233079
CS
4387 if (!num_vnis) {
4388 if (use_json)
4389 vty_out(vty, "{}\n");
d62a17ae 4390 return;
cd233079
CS
4391 }
4392 if (use_json) {
4393 json = json_object_new_object();
ddd16ed5
MK
4394 json_object_string_add(json, "advertiseGatewayMacip",
4395 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
4396 json_object_int_add(json, "numVnis", num_vnis);
4397 } else {
ddd16ed5
MK
4398 vty_out(vty, "Advertise gateway mac-ip: %s\n",
4399 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079 4400 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
b7cfce93 4401 vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s %-37s\n", "VNI",
cd233079 4402 "VxLAN IF", "VTEP IP", "# MACs", "# ARPs",
b7cfce93 4403 "# Remote VTEPs", "VRF");
cd233079
CS
4404 }
4405 args[0] = vty;
4406 args[1] = json;
4407
4408 hash_iterate(zvrf->vni_table,
4409 (void (*)(struct hash_backet *, void *))zvni_print_hash,
4410 args);
4411
4412 if (use_json) {
4413 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4414 json, JSON_C_TO_STRING_PRETTY));
4415 json_object_free(json);
4416 }
cec2e17d 4417}
4418
2232a77c 4419/*
4420 * Handle neighbor delete (on a VLAN device / L3 interface) from the
4421 * kernel. This may result in either the neighbor getting deleted from
4422 * our database or being re-added to the kernel (if it is a valid
4423 * remote neighbor).
4424 */
d62a17ae 4425int zebra_vxlan_local_neigh_del(struct interface *ifp,
4426 struct interface *link_if, struct ipaddr *ip)
4427{
b7cfce93
MK
4428 vni_t l3vni = 0;
4429 struct ethaddr rmac;
d62a17ae 4430 char buf[INET6_ADDRSTRLEN];
b7cfce93 4431 char buf1[INET6_ADDRSTRLEN];
b6938a74 4432 char buf2[ETHER_ADDR_STRLEN];
b7cfce93
MK
4433 zebra_neigh_t *n = NULL;
4434 zebra_vni_t *zvni = NULL;
4435 zebra_mac_t *zmac = NULL;
4436
4437 memset(&rmac, 0, sizeof(struct ethaddr));
d62a17ae 4438
4439 /* We are only interested in neighbors on an SVI that resides on top
4440 * of a VxLAN bridge.
4441 */
b7cfce93 4442 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 4443 if (!zvni)
4444 return 0;
4445 if (!zvni->vxlan_if) {
4446 zlog_err(
4447 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4448 zvni->vni, zvni);
4449 return -1;
4450 }
4451
b7cfce93
MK
4452 /* get the l3-vni */
4453 l3vni = zvni_get_l3vni(zvni);
4454
4455 /* get the rmac */
4456 zvni_get_rmac(zvni, &rmac);
4457
d62a17ae 4458 if (IS_ZEBRA_DEBUG_VXLAN)
b7cfce93 4459 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u L3-VNI %u RMAC %s",
2853fed6 4460 ipaddr2str(ip, buf, sizeof(buf)),
b7cfce93
MK
4461 ifp->name, ifp->ifindex, zvni->vni,
4462 l3vni, prefix_mac2str(&rmac, buf1, sizeof(buf1)));
d62a17ae 4463
4464 /* If entry doesn't exist, nothing to do. */
4465 n = zvni_neigh_lookup(zvni, ip);
4466 if (!n)
4467 return 0;
4468
b6938a74
MK
4469 zmac = zvni_mac_lookup(zvni, &n->emac);
4470 if (!zmac) {
4471 if (IS_ZEBRA_DEBUG_VXLAN)
4472 zlog_err(
2853fed6 4473 "Trying to del a neigh %s without a mac %s on VNI %u",
4474 ipaddr2str(ip, buf, sizeof(buf)),
b6938a74
MK
4475 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
4476 zvni->vni);
4477
4478 return 0;
4479 }
4480
d62a17ae 4481 /* If it is a remote entry, the kernel has aged this out or someone has
4482 * deleted it, it needs to be re-installed as Quagga is the owner.
4483 */
4484 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
4485 zvni_neigh_install(zvni, n);
4486 return 0;
4487 }
4488
d62a17ae 4489 /* Remove neighbor from BGP. */
b6938a74 4490 if (IS_ZEBRA_NEIGH_ACTIVE(n))
2853fed6 4491 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
b6938a74 4492 0);
d62a17ae 4493
4494 /* Delete this neighbor entry. */
4495 zvni_neigh_del(zvni, n);
4496
b6938a74
MK
4497 /* see if the AUTO mac needs to be deleted */
4498 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
f51d8a27 4499 && !listcount(zmac->neigh_list))
b6938a74
MK
4500 zvni_mac_del(zvni, zmac);
4501
d62a17ae 4502 return 0;
2232a77c 4503}
4504
4505/*
859b32c0
MK
4506 * Handle neighbor add or update (on a VLAN device / L3 interface)
4507 * from the kernel.
2232a77c 4508 */
d62a17ae 4509int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
4510 struct interface *link_if,
4511 struct ipaddr *ip,
4512 struct ethaddr *macaddr, u_int16_t state,
4513 u_char ext_learned)
4514{
b7cfce93
MK
4515 vni_t l3vni = 0;
4516 struct ethaddr rmac;
d62a17ae 4517 char buf[ETHER_ADDR_STRLEN];
b7cfce93 4518 char buf1[ETHER_ADDR_STRLEN];
d62a17ae 4519 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
4520 zebra_vni_t *zvni = NULL;
4521 zebra_neigh_t *n = NULL;
4522 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
4523
4524 memset(&rmac, 0, sizeof(struct ethaddr));
d62a17ae 4525
4526 /* We are only interested in neighbors on an SVI that resides on top
4527 * of a VxLAN bridge.
4528 */
b7cfce93 4529 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 4530 if (!zvni)
4531 return 0;
4532
b7cfce93
MK
4533 /* get the l3-vni */
4534 l3vni = zvni_get_l3vni(zvni);
4535
4536 /* get the rmac */
4537 zvni_get_rmac(zvni, &rmac);
4538
d62a17ae 4539 if (IS_ZEBRA_DEBUG_VXLAN)
4540 zlog_debug(
b7cfce93 4541 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u L3-VNI %u RMAC %s",
2853fed6 4542 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 4543 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
4544 ifp->ifindex, state, ext_learned ? "ext-learned " : "",
b7cfce93
MK
4545 zvni->vni, l3vni,
4546 prefix_mac2str(&rmac, buf1, sizeof(buf1)));
d62a17ae 4547
b6938a74
MK
4548 /* create a dummy MAC if the MAC is not already present */
4549 zmac = zvni_mac_lookup(zvni, macaddr);
4550 if (!zmac) {
4551 if (IS_ZEBRA_DEBUG_VXLAN)
4552 zlog_debug(
2853fed6 4553 "AUTO MAC %s created for neigh %s on VNI %u",
b6938a74
MK
4554 prefix_mac2str(macaddr, buf, sizeof(buf)),
4555 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
4556
4557 zmac = zvni_mac_add(zvni, macaddr);
4558 if (!zmac) {
2853fed6 4559 zlog_warn("Failed to add MAC %s VNI %u",
b6938a74
MK
4560 prefix_mac2str(macaddr, buf, sizeof(buf)),
4561 zvni->vni);
4562 return -1;
4563 }
4564
4565 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
4566 memset(&zmac->flags, 0, sizeof(u_int32_t));
4567 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
4568 }
4569
d62a17ae 4570 /* If same entry already exists, it might be a change or it might be a
4571 * move from remote to local.
4572 */
4573 n = zvni_neigh_lookup(zvni, ip);
4574 if (n) {
4575 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
4576 if (memcmp(n->emac.octet, macaddr->octet,
ff8b7eb8 4577 ETH_ALEN)
d62a17ae 4578 == 0) {
b682f6de 4579 /* Update any params and return - client doesn't
4580 * care about a purely local change.
4581 */
4582 n->ifindex = ifp->ifindex;
4583 return 0;
57f7feb6 4584 }
b682f6de 4585
57f7feb6
MK
4586 /* If the MAC has changed,
4587 * need to issue a delete first
4588 * as this means a different MACIP route.
4589 * Also, need to do some unlinking/relinking.
4590 */
2853fed6 4591 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
60466a63 4592 &n->emac, 0);
57f7feb6
MK
4593 old_zmac = zvni_mac_lookup(zvni, &n->emac);
4594 if (old_zmac) {
60466a63 4595 listnode_delete(old_zmac->neigh_list, n);
57f7feb6 4596 zvni_deref_ip2mac(zvni, old_zmac, 0);
b682f6de 4597 }
57f7feb6
MK
4598
4599 /* Set "local" forwarding info. */
4600 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4601 n->ifindex = ifp->ifindex;
4602 memcpy(&n->emac, macaddr, ETH_ALEN);
4603
4604 /* Link to new MAC */
4605 listnode_add_sort(zmac->neigh_list, n);
d62a17ae 4606 } else if (ext_learned)
4607 /* The neighbor is remote and that is the notification we got.
9d303b37 4608 */
d62a17ae 4609 {
859b32c0 4610 /* TODO: Evaluate if we need to do anything here. */
d62a17ae 4611 return 0;
4612 } else
4613 /* Neighbor has moved from remote to local. */
4614 {
4615 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
4616 n->r_vtep_ip.s_addr = 0;
b682f6de 4617 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4618 n->ifindex = ifp->ifindex;
d62a17ae 4619 }
4620 } else {
b6938a74 4621 n = zvni_neigh_add(zvni, ip, macaddr);
d62a17ae 4622 if (!n) {
4623 zlog_err(
2853fed6 4624 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
4625 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 4626 prefix_mac2str(macaddr, buf, sizeof(buf)),
4627 ifp->name, ifp->ifindex, zvni->vni);
4628 return -1;
4629 }
b682f6de 4630 /* Set "local" forwarding info. */
4631 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4632 n->ifindex = ifp->ifindex;
d62a17ae 4633 }
4634
b6938a74
MK
4635 /* Before we program this in BGP, we need to check if MAC is locally
4636 * learnt as well */
4637 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
4638 if (IS_ZEBRA_DEBUG_VXLAN)
4639 zlog_debug(
2853fed6 4640 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
4641 ipaddr2str(ip, buf2, sizeof(buf2)),
b6938a74
MK
4642 prefix_mac2str(macaddr, buf, sizeof(buf)),
4643 zvni->vni);
4644
4645 return 0;
4646 }
4647
b682f6de 4648 /* Inform BGP. */
4649 if (IS_ZEBRA_DEBUG_VXLAN)
b7cfce93 4650 zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u L3-VNI %u with RMAC %s",
2853fed6 4651 ipaddr2str(ip, buf2, sizeof(buf2)),
60466a63 4652 prefix_mac2str(macaddr, buf, sizeof(buf)),
b7cfce93
MK
4653 zvni->vni,
4654 l3vni,
4655 prefix_mac2str(&rmac, buf1, sizeof(buf1)));
d62a17ae 4656
b682f6de 4657 ZEBRA_NEIGH_SET_ACTIVE(n);
b7cfce93 4658
2853fed6 4659 return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
2232a77c 4660}
4661
b682f6de 4662
2232a77c 4663/*
4664 * Handle message from client to delete a remote MACIP for a VNI.
4665 */
e4bd522a 4666int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
d62a17ae 4667 struct zebra_vrf *zvrf)
4668{
4669 struct stream *s;
4670 vni_t vni;
4671 struct ethaddr macaddr;
4672 struct ipaddr ip;
4673 struct in_addr vtep_ip;
4674 zebra_vni_t *zvni;
4675 zebra_mac_t *mac;
4676 zebra_neigh_t *n;
4677 u_short l = 0, ipa_len;
4678 char buf[ETHER_ADDR_STRLEN];
4679 char buf1[INET6_ADDRSTRLEN];
b5ebdc9b 4680 struct interface *ifp = NULL;
4681 struct zebra_if *zif = NULL;
d62a17ae 4682
b7cfce93 4683 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
4684 memset(&ip, 0, sizeof(struct ipaddr));
4685 memset(&vtep_ip, 0, sizeof(struct in_addr));
4686
d62a17ae 4687 s = client->ibuf;
4688
4689 while (l < length) {
4690 /* Obtain each remote MACIP and process. */
4691 /* Message contains VNI, followed by MAC followed by IP (if any)
4692 * followed by remote VTEP IP.
4693 */
4694 mac = NULL;
4695 n = NULL;
4696 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
4697 STREAM_GETL(s, vni);
4698 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
4699 STREAM_GETL(s, ipa_len);
d62a17ae 4700 if (ipa_len) {
4701 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
4702 : IPADDR_V6;
ec93aa12 4703 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 4704 }
ff8b7eb8 4705 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 4706 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4707 l += IPV4_MAX_BYTELEN;
4708
4709 if (IS_ZEBRA_DEBUG_VXLAN)
4710 zlog_debug(
23a06e11 4711 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
d62a17ae 4712 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4713 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
4714 inet_ntoa(vtep_ip),
4715 zebra_route_string(client->proto));
4716
4717 /* Locate VNI hash entry - expected to exist. */
2853fed6 4718 zvni = zvni_lookup(vni);
d62a17ae 4719 if (!zvni) {
4720 if (IS_ZEBRA_DEBUG_VXLAN)
4721 zlog_debug(
4722 "Failed to locate VNI hash upon remote MACIP DEL, "
2853fed6 4723 "VNI %u",
4724 vni);
d62a17ae 4725 continue;
4726 }
b5ebdc9b 4727 ifp = zvni->vxlan_if;
af026ae4 4728 if (!ifp) {
d62a17ae 4729 zlog_err(
4730 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
4731 vni, zvni);
4732 continue;
4733 }
b5ebdc9b 4734 zif = ifp->info;
4735
4736 /* If down or not mapped to a bridge, we're done. */
b682f6de 4737 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 4738 continue;
d62a17ae 4739
4740 /* The remote VTEP specified is normally expected to exist, but
4741 * it is
4742 * possible that the peer may delete the VTEP before deleting
4743 * any MACs
4744 * referring to the VTEP, in which case the handler (see
4745 * remote_vtep_del)
4746 * would have already deleted the MACs.
4747 */
4748 if (!zvni_vtep_find(zvni, &vtep_ip))
4749 continue;
4750
d62a17ae 4751 mac = zvni_mac_lookup(zvni, &macaddr);
4752 if (ipa_len)
4753 n = zvni_neigh_lookup(zvni, &ip);
4754
4755 if (n && !mac) {
4756 zlog_err(
2853fed6 4757 "Failed to locate MAC %s for neigh %s VNI %u",
d62a17ae 4758 prefix_mac2str(&macaddr, buf, sizeof(buf)),
2853fed6 4759 ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
d62a17ae 4760 continue;
4761 }
4762
4763 /* If the remote mac or neighbor doesn't exist there is nothing
4764 * more
4765 * to do. Otherwise, uninstall the entry and then remove it.
4766 */
4767 if (!mac && !n)
4768 continue;
4769
4770 /* Uninstall remote neighbor or MAC. */
4771 if (n) {
4772 /* When the MAC changes for an IP, it is possible the
4773 * client may
4774 * update the new MAC before trying to delete the "old"
4775 * neighbor
4776 * (as these are two different MACIP routes). Do the
4777 * delete only
4778 * if the MAC matches.
4779 */
4780 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
4781 && (memcmp(n->emac.octet, macaddr.octet,
ff8b7eb8 4782 ETH_ALEN)
d62a17ae 4783 == 0)) {
4784 zvni_neigh_uninstall(zvni, n);
4785 zvni_neigh_del(zvni, n);
4786 zvni_deref_ip2mac(zvni, mac, 1);
4787 }
4788 } else {
4789 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
2853fed6 4790 zvni_process_neigh_on_remote_mac_del(zvni,
b6938a74
MK
4791 mac);
4792
0a97666d 4793 if (list_isempty(mac->neigh_list)) {
d62a17ae 4794 zvni_mac_uninstall(zvni, mac, 0);
4795 zvni_mac_del(zvni, mac);
4796 } else
4797 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
4798 }
4799 }
4800 }
4801
ec93aa12 4802stream_failure:
d62a17ae 4803 return 0;
2232a77c 4804}
4805
4806/*
4807 * Handle message from client to add a remote MACIP for a VNI. This
4808 * could be just the add of a MAC address or the add of a neighbor
4809 * (IP+MAC).
4810 */
e4bd522a 4811int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
d62a17ae 4812 struct zebra_vrf *zvrf)
4813{
4814 struct stream *s;
4815 vni_t vni;
4816 struct ethaddr macaddr;
4817 struct ipaddr ip;
4818 struct in_addr vtep_ip;
4819 zebra_vni_t *zvni;
4820 zebra_vtep_t *zvtep;
4821 zebra_mac_t *mac, *old_mac;
4822 zebra_neigh_t *n;
4823 u_short l = 0, ipa_len;
4824 int update_mac = 0, update_neigh = 0;
4825 char buf[ETHER_ADDR_STRLEN];
4826 char buf1[INET6_ADDRSTRLEN];
4827 u_char sticky;
b5ebdc9b 4828 struct interface *ifp = NULL;
4829 struct zebra_if *zif = NULL;
d62a17ae 4830
b7cfce93 4831 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
4832 memset(&ip, 0, sizeof(struct ipaddr));
4833 memset(&vtep_ip, 0, sizeof(struct in_addr));
4834
ec93aa12
DS
4835 if (!EVPN_ENABLED(zvrf)) {
4836 zlog_warn("%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
4837 __PRETTY_FUNCTION__);
4838 return -1;
4839 }
d62a17ae 4840
4841 s = client->ibuf;
4842
4843 while (l < length) {
4844 /* Obtain each remote MACIP and process. */
4845 /* Message contains VNI, followed by MAC followed by IP (if any)
4846 * followed by remote VTEP IP.
4847 */
4848 update_mac = update_neigh = 0;
4849 mac = NULL;
4850 n = NULL;
4851 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
4852 STREAM_GETL(s, vni);
4853 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
4854 STREAM_GETL(s, ipa_len);
d62a17ae 4855 if (ipa_len) {
4856 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
4857 : IPADDR_V6;
ec93aa12 4858 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 4859 }
ff8b7eb8 4860 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 4861 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4862 l += IPV4_MAX_BYTELEN;
4863
4864 /* Get 'sticky' flag. */
ec93aa12 4865 STREAM_GETC(s, sticky);
d62a17ae 4866 l++;
4867
4868 if (IS_ZEBRA_DEBUG_VXLAN)
4869 zlog_debug(
b80320d7 4870 "Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
2853fed6 4871 sticky ? "sticky " : "",
d62a17ae 4872 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4873 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
4874 inet_ntoa(vtep_ip),
4875 zebra_route_string(client->proto));
4876
4877 /* Locate VNI hash entry - expected to exist. */
2853fed6 4878 zvni = zvni_lookup(vni);
d62a17ae 4879 if (!zvni) {
4880 zlog_err(
2853fed6 4881 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
4882 vni);
d62a17ae 4883 continue;
4884 }
b5ebdc9b 4885 ifp = zvni->vxlan_if;
4886 if (!ifp) {
d62a17ae 4887 zlog_err(
4888 "VNI %u hash %p doesn't have intf upon remote MACIP add",
4889 vni, zvni);
4890 continue;
4891 }
b5ebdc9b 4892 zif = ifp->info;
4893
4894 /* If down or not mapped to a bridge, we're done. */
b682f6de 4895 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 4896 continue;
4897
4898 /* The remote VTEP specified should normally exist, but it is
4899 * possible
4900 * that when peering comes up, peer may advertise MACIP routes
4901 * before
4902 * advertising type-3 routes.
4903 */
4904 zvtep = zvni_vtep_find(zvni, &vtep_ip);
4905 if (!zvtep) {
4906 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
4907 zlog_err(
2853fed6 4908 "Failed to add remote VTEP, VNI %u zvni %p",
4909 vni, zvni);
d62a17ae 4910 continue;
4911 }
4912
4913 zvni_vtep_install(zvni, &vtep_ip);
4914 }
4915
4916 /* First, check if the remote MAC is unknown or has a change. If
4917 * so,
4918 * that needs to be updated first. Note that client could
4919 * install
4920 * MAC and MACIP separately or just install the latter.
4921 */
4922 mac = zvni_mac_lookup(zvni, &macaddr);
4923 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
4924 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
4925 != sticky
4926 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
4927 update_mac = 1;
4928
4929 if (update_mac) {
4930 if (!mac) {
4931 mac = zvni_mac_add(zvni, &macaddr);
4932 if (!mac) {
4933 zlog_warn(
2853fed6 4934 "Failed to add MAC %s VNI %u Remote VTEP %s",
d62a17ae 4935 prefix_mac2str(&macaddr, buf,
4936 sizeof(buf)),
4937 vni, inet_ntoa(vtep_ip));
4938 return -1;
4939 }
4940
4941 /* Is this MAC created for a MACIP? */
4942 if (ipa_len)
4943 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 4944 }
4945
4946 /* Set "auto" and "remote" forwarding info. */
4947 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
4948 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
4949 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
4950 mac->fwd_info.r_vtep_ip = vtep_ip;
4951
4952 if (sticky)
4953 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
4954 else
4955 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
4956
2853fed6 4957 zvni_process_neigh_on_remote_mac_add(zvni, mac);
b6938a74 4958
d62a17ae 4959 /* Install the entry. */
4960 zvni_mac_install(zvni, mac);
4961 }
4962
4963 /* If there is no IP, continue - after clearing AUTO flag of
4964 * MAC. */
4965 if (!ipa_len) {
4966 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
4967 continue;
4968 }
4969
4970 /* Check if the remote neighbor itself is unknown or has a
4971 * change.
4972 * If so, create or update and then install the entry.
4973 */
4974 n = zvni_neigh_lookup(zvni, &ip);
4975 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
4976 || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0)
4977 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip))
4978 update_neigh = 1;
4979
4980 if (update_neigh) {
4981 if (!n) {
b6938a74 4982 n = zvni_neigh_add(zvni, &ip, &macaddr);
d62a17ae 4983 if (!n) {
4984 zlog_warn(
2853fed6 4985 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
d62a17ae 4986 ipaddr2str(&ip, buf1,
4987 sizeof(buf1)),
4988 prefix_mac2str(&macaddr, buf,
4989 sizeof(buf)),
4990 vni, inet_ntoa(vtep_ip));
4991 return -1;
4992 }
4993
d62a17ae 4994 } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
4995 != 0) {
0a97666d
MK
4996 /* MAC change, update neigh list for old and new
4997 * mac */
d62a17ae 4998 old_mac = zvni_mac_lookup(zvni, &n->emac);
0a97666d
MK
4999 if (old_mac) {
5000 listnode_delete(old_mac->neigh_list, n);
d62a17ae 5001 zvni_deref_ip2mac(zvni, old_mac, 1);
0a97666d
MK
5002 }
5003 listnode_add_sort(mac->neigh_list, n);
b6938a74 5004 memcpy(&n->emac, &macaddr, ETH_ALEN);
d62a17ae 5005 }
5006
5007 /* Set "remote" forwarding info. */
5008 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
5009 /* TODO: Handle MAC change. */
d62a17ae 5010 n->r_vtep_ip = vtep_ip;
5011 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
5012
5013 /* Install the entry. */
5014 zvni_neigh_install(zvni, n);
5015 }
5016 }
5017
ec93aa12 5018stream_failure:
d62a17ae 5019 return 0;
13d60d35 5020}
5021
5022/*
2232a77c 5023 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5024 * us, this must involve a multihoming scenario. Treat this as implicit delete
5025 * of any prior local MAC.
13d60d35 5026 */
d62a17ae 5027int zebra_vxlan_check_del_local_mac(struct interface *ifp,
5028 struct interface *br_if,
5029 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5030{
d62a17ae 5031 struct zebra_if *zif;
d62a17ae 5032 struct zebra_l2info_vxlan *vxl;
5033 vni_t vni;
5034 zebra_vni_t *zvni;
5035 zebra_mac_t *mac;
5036 char buf[ETHER_ADDR_STRLEN];
5037 u_char sticky;
13d60d35 5038
d62a17ae 5039 zif = ifp->info;
5040 assert(zif);
5041 vxl = &zif->l2info.vxl;
5042 vni = vxl->vni;
13d60d35 5043
2853fed6 5044 /* Check if EVPN is enabled. */
5045 if (!is_evpn_enabled())
d62a17ae 5046 return 0;
13d60d35 5047
d62a17ae 5048 /* Locate hash entry; it is expected to exist. */
2853fed6 5049 zvni = zvni_lookup(vni);
d62a17ae 5050 if (!zvni)
5051 return 0;
13d60d35 5052
d62a17ae 5053 /* If entry doesn't exist, nothing to do. */
5054 mac = zvni_mac_lookup(zvni, macaddr);
5055 if (!mac)
5056 return 0;
13d60d35 5057
d62a17ae 5058 /* Is it a local entry? */
5059 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5060 return 0;
13d60d35 5061
d62a17ae 5062 if (IS_ZEBRA_DEBUG_VXLAN)
5063 zlog_debug(
2853fed6 5064 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5065 prefix_mac2str(macaddr, buf, sizeof(buf)),
d62a17ae 5066 ifp->name, ifp->ifindex, vni);
13d60d35 5067
d62a17ae 5068 /* Remove MAC from BGP. */
5069 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
2853fed6 5070 zvni_mac_send_del_to_client(zvni->vni, macaddr,
1a98c087 5071 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
13d60d35 5072
b6938a74
MK
5073 /*
5074 * If there are no neigh associated with the mac delete the mac
5075 * else mark it as AUTO for forward reference
5076 */
5077 if (!listcount(mac->neigh_list)) {
5078 zvni_mac_del(zvni, mac);
5079 } else {
5080 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5081 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5082 }
13d60d35 5083
d62a17ae 5084 return 0;
13d60d35 5085}
5086
5087/*
2232a77c 5088 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5089 * This can happen because the remote MAC entries are also added as "dynamic",
5090 * so the kernel can ageout the entry.
13d60d35 5091 */
d62a17ae 5092int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
5093 struct interface *br_if,
5094 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5095{
d62a17ae 5096 struct zebra_if *zif;
d62a17ae 5097 struct zebra_l2info_vxlan *vxl;
5098 vni_t vni;
5099 zebra_vni_t *zvni;
5100 zebra_mac_t *mac;
5101 char buf[ETHER_ADDR_STRLEN];
2232a77c 5102
d62a17ae 5103 zif = ifp->info;
5104 assert(zif);
5105 vxl = &zif->l2info.vxl;
5106 vni = vxl->vni;
2232a77c 5107
2853fed6 5108 /* Check if EVPN is enabled. */
5109 if (!is_evpn_enabled())
d62a17ae 5110 return 0;
2232a77c 5111
d62a17ae 5112 /* Locate hash entry; it is expected to exist. */
2853fed6 5113 zvni = zvni_lookup(vni);
d62a17ae 5114 if (!zvni)
5115 return 0;
13d60d35 5116
d62a17ae 5117 /* If entry doesn't exist, nothing to do. */
5118 mac = zvni_mac_lookup(zvni, macaddr);
5119 if (!mac)
5120 return 0;
2232a77c 5121
d62a17ae 5122 /* Is it a remote entry? */
5123 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
5124 return 0;
2232a77c 5125
d62a17ae 5126 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5127 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
d62a17ae 5128 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5129 ifp->ifindex, vni);
13d60d35 5130
d62a17ae 5131 zvni_mac_install(zvni, mac);
5132 return 0;
13d60d35 5133}
5134
5135/*
2232a77c 5136 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 5137 */
d62a17ae 5138int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
5139 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5140{
d62a17ae 5141 zebra_vni_t *zvni;
5142 zebra_mac_t *mac;
d62a17ae 5143 char buf[ETHER_ADDR_STRLEN];
5144 u_char sticky;
13d60d35 5145
d62a17ae 5146 /* We are interested in MACs only on ports or (port, VLAN) that
5147 * map to a VNI.
5148 */
5149 zvni = zvni_map_vlan(ifp, br_if, vid);
5150 if (!zvni)
5151 return 0;
5152 if (!zvni->vxlan_if) {
5153 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5154 zvni->vni, zvni);
5155 return -1;
5156 }
13d60d35 5157
d62a17ae 5158 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5159 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
d62a17ae 5160 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5161 ifp->ifindex, vid, zvni->vni);
2232a77c 5162
d62a17ae 5163 /* If entry doesn't exist, nothing to do. */
5164 mac = zvni_mac_lookup(zvni, macaddr);
5165 if (!mac)
5166 return 0;
2232a77c 5167
d62a17ae 5168 /* Is it a local entry? */
5169 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5170 return 0;
2232a77c 5171
d62a17ae 5172 /* Remove MAC from BGP. */
5173 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
2853fed6 5174 zvni_mac_send_del_to_client(zvni->vni, macaddr,
1a98c087 5175 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
2232a77c 5176
b6938a74 5177 /* Update all the neigh entries associated with this mac */
2853fed6 5178 zvni_process_neigh_on_local_mac_del(zvni, mac);
b6938a74
MK
5179
5180 /*
5181 * If there are no neigh associated with the mac delete the mac
5182 * else mark it as AUTO for forward reference
5183 */
5184 if (!listcount(mac->neigh_list)) {
5185 zvni_mac_del(zvni, mac);
5186 } else {
5187 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5188 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5189 }
2232a77c 5190
d62a17ae 5191 return 0;
13d60d35 5192}
5193
5194/*
2232a77c 5195 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 5196 */
d62a17ae 5197int zebra_vxlan_local_mac_add_update(struct interface *ifp,
5198 struct interface *br_if,
5199 struct ethaddr *macaddr, vlanid_t vid,
5200 u_char sticky)
5201{
5202 zebra_vni_t *zvni;
5203 zebra_mac_t *mac;
d62a17ae 5204 char buf[ETHER_ADDR_STRLEN];
5205 int add = 1;
5206 u_char mac_sticky;
5207
5208 /* We are interested in MACs only on ports or (port, VLAN) that
5209 * map to a VNI.
5210 */
5211 zvni = zvni_map_vlan(ifp, br_if, vid);
5212 if (!zvni) {
5213 if (IS_ZEBRA_DEBUG_VXLAN)
5214 zlog_debug(
2853fed6 5215 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5216 sticky ? "sticky " : "",
d62a17ae 5217 prefix_mac2str(macaddr, buf, sizeof(buf)),
5218 ifp->name, ifp->ifindex, vid);
5219 return 0;
5220 }
5221
5222 if (!zvni->vxlan_if) {
5223 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5224 zvni->vni, zvni);
5225 return -1;
5226 }
5227
5228 if (IS_ZEBRA_DEBUG_VXLAN)
5229 zlog_debug(
2853fed6 5230 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5231 sticky ? "sticky " : "",
d62a17ae 5232 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5233 ifp->ifindex, vid, zvni->vni);
5234
5235 /* If same entry already exists, nothing to do. */
5236 mac = zvni_mac_lookup(zvni, macaddr);
5237 if (mac) {
5238 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
5239 mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
5240 ? 1
5241 : 0;
5242
b6938a74 5243
b8ce75a5
MK
5244 /*
5245 * return if nothing has changed.
5246 * inform bgp if sticky flag has changed
5247 * update locally and do not inform bgp if local
5248 * parameters like interface has changed
5249 */
d62a17ae 5250 if (mac_sticky == sticky
5251 && mac->fwd_info.local.ifindex == ifp->ifindex
5252 && mac->fwd_info.local.vid == vid) {
5253 if (IS_ZEBRA_DEBUG_VXLAN)
5254 zlog_debug(
2853fed6 5255 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
d62a17ae 5256 "entry exists and has not changed ",
d62a17ae 5257 sticky ? "sticky " : "",
5258 prefix_mac2str(macaddr, buf,
5259 sizeof(buf)),
5260 ifp->name, ifp->ifindex, vid,
5261 zvni->vni);
5262 return 0;
b6938a74 5263 } else if (mac_sticky != sticky) {
b8ce75a5 5264 add = 1;
b6938a74 5265 } else {
b8ce75a5
MK
5266 add = 0; /* This is an update of local
5267 interface. */
b6938a74 5268 }
421bb26a
MK
5269 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5270 /*
5271 * If we have already learned the MAC as a remote sticky
5272 * MAC,
5273 * this is a operator error and we must log a warning
5274 */
8f4b98ee 5275 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
421bb26a
MK
5276 zlog_warn(
5277 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5278 prefix_mac2str(macaddr, buf,
5279 sizeof(buf)),
5280 inet_ntoa(mac->fwd_info.r_vtep_ip),
5281 zvni->vni);
8f4b98ee
MK
5282 return 0;
5283 }
d62a17ae 5284 }
5285 }
5286
d62a17ae 5287 if (!mac) {
5288 mac = zvni_mac_add(zvni, macaddr);
5289 if (!mac) {
2853fed6 5290 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
d62a17ae 5291 prefix_mac2str(macaddr, buf, sizeof(buf)),
5292 ifp->name, ifp->ifindex, vid);
5293 return -1;
5294 }
5295 }
5296
5297 /* Set "local" forwarding info. */
5298 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
b6938a74 5299 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 5300 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
b6938a74 5301 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
d62a17ae 5302 mac->fwd_info.local.ifindex = ifp->ifindex;
5303 mac->fwd_info.local.vid = vid;
5304
5305 if (sticky)
5306 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5307 else
5308 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5309
5310 /* Inform BGP if required. */
b6938a74 5311 if (add) {
2853fed6 5312 zvni_process_neigh_on_local_mac_add(zvni, mac);
5313 return zvni_mac_send_add_to_client(zvni->vni, macaddr,
b6938a74
MK
5314 sticky);
5315 }
d62a17ae 5316
5317 return 0;
2232a77c 5318}
13d60d35 5319
5320/*
5321 * Handle message from client to delete a remote VTEP for a VNI.
5322 */
e4bd522a 5323int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
d62a17ae 5324 struct zebra_vrf *zvrf)
5325{
5326 struct stream *s;
5327 u_short l = 0;
5328 vni_t vni;
5329 struct in_addr vtep_ip;
5330 zebra_vni_t *zvni;
5331 zebra_vtep_t *zvtep;
b5ebdc9b 5332 struct interface *ifp;
5333 struct zebra_if *zif;
d62a17ae 5334
ec93aa12
DS
5335 if (!is_evpn_enabled()) {
5336 zlog_warn("%s: EVPN is not enabled yet we have received a vtep del command",
5337 __PRETTY_FUNCTION__);
5338 return -1;
5339 }
5340
2853fed6 5341 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5342 zlog_err("Recv MACIP DEL for non-default VRF %u",
5343 zvrf_id(zvrf));
5344 return -1;
5345 }
5346
d62a17ae 5347 s = client->ibuf;
5348
5349 while (l < length) {
5350 /* Obtain each remote VTEP and process. */
ec93aa12 5351 STREAM_GETL(s, vni);
d62a17ae 5352 l += 4;
ec93aa12 5353 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5354 l += IPV4_MAX_BYTELEN;
5355
5356 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5357 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5358 inet_ntoa(vtep_ip), vni,
d62a17ae 5359 zebra_route_string(client->proto));
5360
5361 /* Locate VNI hash entry - expected to exist. */
2853fed6 5362 zvni = zvni_lookup(vni);
d62a17ae 5363 if (!zvni) {
5364 if (IS_ZEBRA_DEBUG_VXLAN)
5365 zlog_debug(
5366 "Failed to locate VNI hash upon remote VTEP DEL, "
2853fed6 5367 "VNI %u",
5368 vni);
d62a17ae 5369 continue;
5370 }
5371
b5ebdc9b 5372 ifp = zvni->vxlan_if;
5373 if (!ifp) {
60466a63
QY
5374 zlog_err(
5375 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5376 zvni->vni, zvni);
b682f6de 5377 continue;
b5ebdc9b 5378 }
5379 zif = ifp->info;
5380
5381 /* If down or not mapped to a bridge, we're done. */
b682f6de 5382 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 5383 continue;
5384
d62a17ae 5385 /* If the remote VTEP does not exist, there's nothing more to
5386 * do.
5387 * Otherwise, uninstall any remote MACs pointing to this VTEP
5388 * and
5389 * then, the VTEP entry itself and remove it.
5390 */
5391 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5392 if (!zvtep)
5393 continue;
5394
5395 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
5396 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
5397 zvni_vtep_uninstall(zvni, &vtep_ip);
5398 zvni_vtep_del(zvni, zvtep);
5399 }
5400
ec93aa12 5401stream_failure:
d62a17ae 5402 return 0;
13d60d35 5403}
5404
5405/*
5406 * Handle message from client to add a remote VTEP for a VNI.
5407 */
e4bd522a 5408int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
d62a17ae 5409 struct zebra_vrf *zvrf)
5410{
5411 struct stream *s;
5412 u_short l = 0;
5413 vni_t vni;
5414 struct in_addr vtep_ip;
5415 zebra_vni_t *zvni;
b5ebdc9b 5416 struct interface *ifp;
5417 struct zebra_if *zif;
d62a17ae 5418
ec93aa12
DS
5419 if (!is_evpn_enabled()) {
5420 zlog_warn("%s: EVPN not enabled yet we received a vtep_add zapi call",
5421 __PRETTY_FUNCTION__);
5422 return -1;
5423 }
5424
2853fed6 5425 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5426 zlog_err("Recv MACIP ADD for non-default VRF %u",
5427 zvrf_id(zvrf));
5428 return -1;
5429 }
d62a17ae 5430
5431 s = client->ibuf;
5432
5433 while (l < length) {
5434 /* Obtain each remote VTEP and process. */
ec93aa12 5435 STREAM_GETL(s, vni);
d62a17ae 5436 l += 4;
ec93aa12 5437 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5438 l += IPV4_MAX_BYTELEN;
5439
5440 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5441 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5442 inet_ntoa(vtep_ip), vni,
d62a17ae 5443 zebra_route_string(client->proto));
5444
5445 /* Locate VNI hash entry - expected to exist. */
2853fed6 5446 zvni = zvni_lookup(vni);
d62a17ae 5447 if (!zvni) {
5448 zlog_err(
2853fed6 5449 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5450 vni);
d62a17ae 5451 continue;
5452 }
b5ebdc9b 5453
5454 ifp = zvni->vxlan_if;
5455 if (!ifp) {
d62a17ae 5456 zlog_err(
5457 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5458 zvni->vni, zvni);
5459 continue;
5460 }
5461
b5ebdc9b 5462 zif = ifp->info;
d62a17ae 5463
b5ebdc9b 5464 /* If down or not mapped to a bridge, we're done. */
b682f6de 5465 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 5466 continue;
5467
b682f6de 5468 /* If the remote VTEP already exists,
5469 there's nothing more to do. */
b5ebdc9b 5470 if (zvni_vtep_find(zvni, &vtep_ip))
d62a17ae 5471 continue;
5472
5473 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5474 zlog_err(
2853fed6 5475 "Failed to add remote VTEP, VNI %u zvni %p",
5476 vni, zvni);
d62a17ae 5477 continue;
5478 }
5479
5480 zvni_vtep_install(zvni, &vtep_ip);
5481 }
5482
ec93aa12 5483stream_failure:
d62a17ae 5484 return 0;
13d60d35 5485}
5486
1a98c087
MK
5487/*
5488 * Add/Del gateway macip to evpn
5489 * g/w can be:
5490 * 1. SVI interface on a vlan aware bridge
5491 * 2. SVI interface on a vlan unaware bridge
5492 * 3. vrr interface (MACVLAN) associated to a SVI
5493 * We advertise macip routes for an interface if it is associated to VxLan vlan
5494 */
5495int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
5496 int add)
5497{
5498 struct ipaddr ip;
5499 struct ethaddr macaddr;
5500 zebra_vni_t *zvni = NULL;
1a98c087
MK
5501
5502 memset(&ip, 0, sizeof(struct ipaddr));
5503 memset(&macaddr, 0, sizeof(struct ethaddr));
5504
2853fed6 5505 /* Check if EVPN is enabled. */
5506 if (!is_evpn_enabled())
297a21b6
MK
5507 return 0;
5508
1a98c087
MK
5509 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
5510 struct interface *svi_if =
5511 NULL; /* SVI corresponding to the MACVLAN */
5512 struct zebra_if *ifp_zif =
5513 NULL; /* Zebra daemon specific info for MACVLAN */
5514 struct zebra_if *svi_if_zif =
5515 NULL; /* Zebra daemon specific info for SVI*/
5516
5517 ifp_zif = ifp->info;
5518 if (!ifp_zif)
5519 return -1;
5520
71349e03
MK
5521 /*
5522 * for a MACVLAN interface the link represents the svi_if
5523 */
5524 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
5525 ifp_zif->link_ifindex);
1a98c087 5526 if (!svi_if) {
2853fed6 5527 zlog_err("MACVLAN %s(%u) without link information",
5528 ifp->name, ifp->ifindex);
1a98c087
MK
5529 return -1;
5530 }
5531
5532 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
5533 /*
5534 * If it is a vlan aware bridge then the link gives the
5535 * bridge information
5536 */
5537 struct interface *svi_if_link = NULL;
5538
1a98c087 5539 svi_if_zif = svi_if->info;
71349e03
MK
5540 if (svi_if_zif) {
5541 svi_if_link = if_lookup_by_index_per_ns(
60466a63
QY
5542 zebra_ns_lookup(NS_DEFAULT),
5543 svi_if_zif->link_ifindex);
b7cfce93 5544 zvni = zvni_from_svi(svi_if, svi_if_link);
71349e03 5545 }
1a98c087 5546 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
5547 /*
5548 * If it is a vlan unaware bridge then svi is the bridge
5549 * itself
5550 */
b7cfce93 5551 zvni = zvni_from_svi(svi_if, svi_if);
1a98c087
MK
5552 }
5553 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
5554 struct zebra_if *svi_if_zif =
71349e03
MK
5555 NULL; /* Zebra daemon specific info for SVI */
5556 struct interface *svi_if_link =
5557 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
5558
5559 svi_if_zif = ifp->info;
60466a63
QY
5560 svi_if_link = if_lookup_by_index_per_ns(
5561 zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex);
71349e03 5562 if (svi_if_zif && svi_if_link)
b7cfce93 5563 zvni = zvni_from_svi(ifp, svi_if_link);
1a98c087 5564 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
b7cfce93 5565 zvni = zvni_from_svi(ifp, ifp);
1a98c087
MK
5566 }
5567
5568 if (!zvni)
5569 return 0;
5570
5571 if (!zvni->vxlan_if) {
5572 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5573 zvni->vni, zvni);
5574 return -1;
5575 }
5576
1a98c087
MK
5577
5578 /* check if we are advertising gw macip routes */
2853fed6 5579 if (!advertise_gw_macip_enabled(zvni))
1a98c087
MK
5580 return 0;
5581
5582 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
5583
5584 if (p->family == AF_INET) {
5585 ip.ipa_type = IPADDR_V4;
5586 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
5587 sizeof(struct in_addr));
5588 } else if (p->family == AF_INET6) {
5589 ip.ipa_type = IPADDR_V6;
5590 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
5591 sizeof(struct in6_addr));
5592 }
5593
5594
5595 if (add)
5596 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
5597 else
5598 zvni_gw_macip_del(ifp, zvni, &ip);
5599
5600 return 0;
5601}
5602
2232a77c 5603/*
b7cfce93
MK
5604 * Handle SVI interface going down.
5605 * SVI can be associated to either L3-VNI or L2-VNI.
5606 * For L2-VNI: At this point, this is a NOP since
5607 * the kernel deletes the neighbor entries on this SVI (if any).
5608 * We only need to update the vrf corresponding to zvni.
5609 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5610 * from bgp
2232a77c 5611 */
d62a17ae 5612int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 5613{
b7cfce93
MK
5614 zebra_l3vni_t *zl3vni = NULL;
5615
5616 zl3vni = zl3vni_from_svi(ifp, link_if);
5617 if (zl3vni) {
5618
5619 /* process l3-vni down */
5620 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5621
5622 /* remove association with svi-if */
5623 zl3vni->svi_if = NULL;
5624 } else {
5625 zebra_vni_t *zvni = NULL;
5626
5627 /* since we dont have svi corresponding to zvni, we associate it
5628 * to default vrf. Note: the corresponding neigh entries on the
5629 * SVI would have already been deleted */
5630 zvni = zvni_from_svi(ifp, link_if);
5631 if (zvni) {
5632 zvni->vrf_id = VRF_DEFAULT;
5633
5634 /* update the tenant vrf in BGP */
5635 zvni_send_add_to_client(zvni);
5636 }
5637 }
d62a17ae 5638 return 0;
2232a77c 5639}
5640
5641/*
b7cfce93
MK
5642 * Handle SVI interface coming up.
5643 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5644 * vxlan intf).
5645 * For L2-VNI: we need to install any remote neighbors entried (used for
5646 * apr-suppression)
5647 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
2232a77c 5648 */
d62a17ae 5649int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 5650{
b7cfce93
MK
5651 zebra_vni_t *zvni = NULL;
5652 zebra_l3vni_t *zl3vni = NULL;
2232a77c 5653
b7cfce93
MK
5654 zl3vni = zl3vni_from_svi(ifp, link_if);
5655 if (zl3vni) {
2232a77c 5656
b7cfce93
MK
5657 /* associate with svi */
5658 zl3vni->svi_if = ifp;
2232a77c 5659
b7cfce93
MK
5660 /* process oper-up */
5661 if (is_l3vni_oper_up(zl3vni))
5662 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5663 } else {
5664
5665 /* process SVI up for l2-vni */
5666 struct neigh_walk_ctx n_wctx;
5667
5668 zvni = zvni_from_svi(ifp, link_if);
5669 if (!zvni)
5670 return 0;
5671
5672 if (!zvni->vxlan_if) {
5673 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
5674 zvni->vni, zvni);
5675 return -1;
5676 }
5677
5678 if (IS_ZEBRA_DEBUG_VXLAN)
5679 zlog_debug("SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
5680 ifp->name, ifp->ifindex, zvni->vni,
5681 vrf_id_to_name(ifp->vrf_id));
2232a77c 5682
b7cfce93
MK
5683 /* update the vrf information for l2-vni and inform bgp */
5684 zvni->vrf_id = ifp->vrf_id;
5685 zvni_send_add_to_client(zvni);
5686
5687 /* Install any remote neighbors for this VNI. */
5688 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
5689 n_wctx.zvni = zvni;
5690 hash_iterate(zvni->neigh_table,
5691 zvni_install_neigh_hash,
5692 &n_wctx);
5693 }
2232a77c 5694
d62a17ae 5695 return 0;
2232a77c 5696}
5697
13d60d35 5698/*
b7cfce93 5699 * Handle VxLAN interface down
13d60d35 5700 */
d62a17ae 5701int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 5702{
d62a17ae 5703 vni_t vni;
b7cfce93
MK
5704 struct zebra_if *zif = NULL;
5705 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 5706
2853fed6 5707 /* Check if EVPN is enabled. */
5708 if (!is_evpn_enabled())
d62a17ae 5709 return 0;
13d60d35 5710
d62a17ae 5711 zif = ifp->info;
5712 assert(zif);
5713 vxl = &zif->l2info.vxl;
5714 vni = vxl->vni;
13d60d35 5715
13d60d35 5716
b7cfce93
MK
5717 if (is_vni_l3(vni)) {
5718
5719 /* process-if-down for l3-vni */
5720 zebra_l3vni_t *zl3vni = NULL;
5721
5722 if (IS_ZEBRA_DEBUG_VXLAN)
5723 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN",
5724 ifp->name, ifp->ifindex, vni);
5725
5726 zl3vni = zl3vni_lookup(vni);
5727 if (!zl3vni) {
5728 zlog_err(
5729 "Failed to locate L3-VNI hash at DOWN, IF %s(%u) VNI %u",
5730 ifp->name, ifp->ifindex, vni);
5731 return -1;
5732 }
5733
5734 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5735
5736 } else {
5737 /* process if-down for l2-vni */
5738 zebra_vni_t *zvni;
5739
5740 if (IS_ZEBRA_DEBUG_VXLAN)
5741 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN",
5742 ifp->name, ifp->ifindex, vni);
13d60d35 5743
b7cfce93
MK
5744 /* Locate hash entry; it is expected to exist. */
5745 zvni = zvni_lookup(vni);
5746 if (!zvni) {
5747 zlog_err(
5748 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
5749 ifp->name, ifp->ifindex, vni);
5750 return -1;
5751 }
13d60d35 5752
b7cfce93 5753 assert(zvni->vxlan_if == ifp);
13d60d35 5754
b7cfce93
MK
5755 /* Delete this VNI from BGP. */
5756 zvni_send_del_to_client(zvni->vni);
2232a77c 5757
b7cfce93
MK
5758 /* Free up all neighbors and MACs, if any. */
5759 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
5760 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
13d60d35 5761
b7cfce93
MK
5762 /* Free up all remote VTEPs, if any. */
5763 zvni_vtep_del_all(zvni, 1);
5764 }
d62a17ae 5765 return 0;
13d60d35 5766}
5767
5768/*
5769 * Handle VxLAN interface up - update BGP if required.
5770 */
d62a17ae 5771int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 5772{
d62a17ae 5773 vni_t vni;
b7cfce93
MK
5774 struct zebra_if *zif = NULL;
5775 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 5776
2853fed6 5777 /* Check if EVPN is enabled. */
5778 if (!is_evpn_enabled())
d62a17ae 5779 return 0;
13d60d35 5780
d62a17ae 5781 zif = ifp->info;
5782 assert(zif);
5783 vxl = &zif->l2info.vxl;
5784 vni = vxl->vni;
13d60d35 5785
b7cfce93 5786 if (is_vni_l3(vni)) {
13d60d35 5787
b7cfce93
MK
5788 /* Handle L3-VNI add */
5789 zebra_l3vni_t *zl3vni = NULL;
13d60d35 5790
b7cfce93
MK
5791 if (IS_ZEBRA_DEBUG_VXLAN)
5792 zlog_debug("Intf %s(%u) L3-VNI %u is UP",
5793 ifp->name, ifp->ifindex, vni);
13d60d35 5794
b7cfce93
MK
5795 zl3vni = zl3vni_lookup(vni);
5796 if (!zl3vni) {
5797 zlog_err(
5798 "Failed to locate L3-VNI hash at UP, IF %s(%u) VNI %u",
5799 ifp->name, ifp->ifindex, vni);
5800 return -1;
5801 }
5802
5803 /* we need to associate with SVI, if any, we can associate with
5804 * svi-if only after association with vxlan-intf is complete */
5805 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5806
5807 if (is_l3vni_oper_up(zl3vni))
5808 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5809 } else {
5810 /* Handle L2-VNI add */
5811
5812 zebra_vni_t *zvni = NULL;
5813 zebra_l3vni_t *zl3vni = NULL;
5814 struct interface *vlan_if = NULL;
5815
5816 if (IS_ZEBRA_DEBUG_VXLAN)
5817 zlog_debug("Intf %s(%u) L2-VNI %u is UP",
5818 ifp->name, ifp->ifindex, vni);
5819
5820 /* Locate hash entry; it is expected to exist. */
5821 zvni = zvni_lookup(vni);
5822 if (!zvni) {
5823 zlog_err(
5824 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
5825 ifp->name, ifp->ifindex, vni);
5826 return -1;
5827 }
5828
5829 assert(zvni->vxlan_if == ifp);
5830 vlan_if = zvni_map_to_svi(vxl->access_vlan,
5831 zif->brslave_info.br_if);
5832 if (vlan_if) {
5833 zvni->vrf_id = vlan_if->vrf_id;
5834 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
5835 if (zl3vni)
5836 listnode_add_sort(zl3vni->l2vnis, zvni);
5837 }
5838
5839 /* If part of a bridge, inform BGP about this VNI. */
5840 /* Also, read and populate local MACs and neighbors. */
5841 if (zif->brslave_info.br_if) {
5842 zvni_send_add_to_client(zvni);
5843 zvni_read_mac_neigh(zvni, ifp);
5844 }
d62a17ae 5845 }
13d60d35 5846
d62a17ae 5847 return 0;
13d60d35 5848}
5849
5850/*
5851 * Handle VxLAN interface delete. Locate and remove entry in hash table
5852 * and update BGP, if required.
5853 */
d62a17ae 5854int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 5855{
d62a17ae 5856 vni_t vni;
b7cfce93
MK
5857 struct zebra_if *zif = NULL;
5858 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 5859
2853fed6 5860 /* Check if EVPN is enabled. */
5861 if (!is_evpn_enabled())
d62a17ae 5862 return 0;
13d60d35 5863
d62a17ae 5864 zif = ifp->info;
5865 assert(zif);
5866 vxl = &zif->l2info.vxl;
5867 vni = vxl->vni;
13d60d35 5868
b7cfce93 5869 if (is_vni_l3(vni)) {
13d60d35 5870
b7cfce93
MK
5871 /* process if-del for l3-vni */
5872 zebra_l3vni_t *zl3vni = NULL;
5873
5874 if (IS_ZEBRA_DEBUG_VXLAN)
5875 zlog_debug("Del L3-VNI %u intf %s(%u)",
5876 vni, ifp->name, ifp->ifindex);
13d60d35 5877
b7cfce93
MK
5878 zl3vni = zl3vni_lookup(vni);
5879 if (!zl3vni) {
5880 zlog_err(
5881 "Failed to locate L3-VNI hash at del, IF %s(%u) VNI %u",
5882 ifp->name, ifp->ifindex, vni);
5883 return 0;
5884 }
13d60d35 5885
b7cfce93
MK
5886 /* process oper-down for l3-vni */
5887 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2232a77c 5888
b7cfce93
MK
5889 /* remove the association with vxlan_if */
5890 zl3vni->vxlan_if = NULL;
5891 } else {
13d60d35 5892
b7cfce93
MK
5893 /* process if-del for l2-vni*/
5894 zebra_vni_t *zvni = NULL;
5895 zebra_l3vni_t *zl3vni = NULL;
5896
5897 if (IS_ZEBRA_DEBUG_VXLAN)
5898 zlog_debug("Del L2-VNI %u intf %s(%u)",
5899 vni, ifp->name, ifp->ifindex);
5900
5901 /* Locate hash entry; it is expected to exist. */
5902 zvni = zvni_lookup(vni);
5903 if (!zvni) {
5904 zlog_err(
5905 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
5906 ifp->name, ifp->ifindex, vni);
5907 return 0;
5908 }
5909
5910 /* remove from l3-vni list */
5911 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
5912 if (zl3vni)
5913 listnode_delete(zl3vni->l2vnis, zvni);
5914
5915 /* Delete VNI from BGP. */
5916 zvni_send_del_to_client(zvni->vni);
5917
5918 /* Free up all neighbors and MAC, if any. */
5919 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
5920 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
5921
5922 /* Free up all remote VTEPs, if any. */
5923 zvni_vtep_del_all(zvni, 0);
5924
5925 /* Delete the hash entry. */
5926 if (zvni_del(zvni)) {
5927 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
5928 zvni, ifp->name, ifp->ifindex, zvni->vni);
5929 return -1;
5930 }
d62a17ae 5931 }
13d60d35 5932
d62a17ae 5933 return 0;
13d60d35 5934}
5935
5936/*
5937 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
5938 */
d62a17ae 5939int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
5940{
d62a17ae 5941 vni_t vni;
b7cfce93
MK
5942 struct zebra_if *zif = NULL;
5943 struct zebra_l2info_vxlan *vxl = NULL;
d62a17ae 5944
2853fed6 5945 /* Check if EVPN is enabled. */
5946 if (!is_evpn_enabled())
d62a17ae 5947 return 0;
5948
5949 zif = ifp->info;
5950 assert(zif);
5951 vxl = &zif->l2info.vxl;
5952 vni = vxl->vni;
5953
b7cfce93
MK
5954 if (is_vni_l3(vni)) {
5955 zebra_l3vni_t *zl3vni = NULL;
d62a17ae 5956
b7cfce93
MK
5957 zl3vni = zl3vni_lookup(vni);
5958 if (!zl3vni) {
5959 zlog_err(
5960 "Failed to find L3-VNI hash on update, IF %s(%u) VNI %u",
5961 ifp->name, ifp->ifindex, vni);
5962 return -1;
5963 }
af026ae4 5964
b7cfce93
MK
5965 if (IS_ZEBRA_DEBUG_VXLAN)
5966 zlog_debug(
5967 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
5968 vni, ifp->name, ifp->ifindex,
5969 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
5970 zif->brslave_info.bridge_ifindex, chgflags);
5971
5972 /* Removed from bridge? Cleanup and return */
5973 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
5974 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
5975 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5976 return 0;
5977 }
5978
5979 /* access-vlan change - process oper down, associate with new
5980 * svi_if and then process oper up again */
5981 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5982 if (if_is_operative(ifp)) {
5983 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5984 zl3vni->svi_if = NULL;
5985 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5986 if (is_l3vni_oper_up(zl3vni))
5987 zebra_vxlan_process_l3vni_oper_up(
5988 zl3vni);
5989 }
5990 }
d62a17ae 5991
b7cfce93
MK
5992 /* if we have a valid new master, process l3-vni oper up */
5993 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
5994 if (is_l3vni_oper_up(zl3vni))
5995 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5996 }
5997 } else {
5998 zebra_vni_t *zvni = NULL;
d62a17ae 5999
b7cfce93
MK
6000 /* Update VNI hash. */
6001 zvni = zvni_lookup(vni);
6002 if (!zvni) {
6003 zlog_err(
6004 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6005 ifp->name, ifp->ifindex, vni);
6006 return -1;
6007 }
d62a17ae 6008
b7cfce93
MK
6009 if (IS_ZEBRA_DEBUG_VXLAN)
6010 zlog_debug(
6011 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6012 vni, ifp->name, ifp->ifindex,
6013 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6014 zif->brslave_info.bridge_ifindex, chgflags);
6015
6016 /* Removed from bridge? Cleanup and return */
6017 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6018 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6019 /* Delete from client, remove all remote VTEPs */
6020 /* Also, free up all MACs and neighbors. */
6021 zvni_send_del_to_client(zvni->vni);
6022 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
6023 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
6024 zvni_vtep_del_all(zvni, 1);
6025 return 0;
6026 }
d62a17ae 6027
b7cfce93
MK
6028 /* Handle other changes. */
6029 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6030 /* Remove all existing local neigh and MACs for this VNI
6031 * (including from BGP)
6032 */
6033 zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6034 zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6035 }
d62a17ae 6036
b7cfce93
MK
6037 zvni->local_vtep_ip = vxl->vtep_ip;
6038 zvni->vxlan_if = ifp;
d62a17ae 6039
b7cfce93
MK
6040 /* Take further actions needed.
6041 * Note that if we are here, there is a change of interest.
6042 */
6043 /* If down or not mapped to a bridge, we're done. */
6044 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6045 return 0;
d62a17ae 6046
b7cfce93
MK
6047 /* Inform BGP, if there is a change of interest. */
6048 if (chgflags
6049 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
6050 zvni_send_add_to_client(zvni);
6051
6052 /* If there is a valid new master or a VLAN mapping change,
6053 * read and populate local MACs and neighbors.
6054 * Also, reinstall any remote MACs and neighbors
6055 * for this VNI (based on new VLAN).
6056 */
6057 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6058 zvni_read_mac_neigh(zvni, ifp);
6059 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6060 struct mac_walk_ctx m_wctx;
6061 struct neigh_walk_ctx n_wctx;
6062
6063 zvni_read_mac_neigh(zvni, ifp);
6064
6065 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6066 m_wctx.zvni = zvni;
6067 hash_iterate(zvni->mac_table,
6068 zvni_install_mac_hash,
6069 &m_wctx);
6070
6071 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6072 n_wctx.zvni = zvni;
6073 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
6074 &n_wctx);
6075 }
d62a17ae 6076 }
6077
6078 return 0;
13d60d35 6079}
6080
6081/*
6082 * Handle VxLAN interface add.
6083 */
d62a17ae 6084int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 6085{
d62a17ae 6086 vni_t vni;
b7cfce93
MK
6087 struct zebra_if *zif = NULL;
6088 struct zebra_l2info_vxlan *vxl = NULL;
13d60d35 6089
2853fed6 6090 /* Check if EVPN is enabled. */
6091 if (!is_evpn_enabled())
d62a17ae 6092 return 0;
13d60d35 6093
d62a17ae 6094 zif = ifp->info;
6095 assert(zif);
6096 vxl = &zif->l2info.vxl;
6097 vni = vxl->vni;
13d60d35 6098
b7cfce93 6099 if (is_vni_l3(vni)) {
13d60d35 6100
b7cfce93
MK
6101 /* process if-add for l3-vni*/
6102 zebra_l3vni_t *zl3vni = NULL;
6103
6104 if (IS_ZEBRA_DEBUG_VXLAN)
6105 zlog_debug(
6106 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6107 vni, ifp->name, ifp->ifindex,
6108 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6109 zif->brslave_info.bridge_ifindex);
6110
6111 /*
6112 * we expect the l3-vni has entry to be present here.
6113 * The only place l3-vni is created in zebra is vrf-vni mapping
6114 * command. This might change when we have the switchd support
6115 * for l3-vxlan interface.
6116 */
6117 zl3vni = zl3vni_lookup(vni);
6118 if (!zl3vni) {
d62a17ae 6119 zlog_err(
b7cfce93 6120 "Failed to locate L3-VNI hash at del, IF %s(%u) VNI %u",
2853fed6 6121 ifp->name, ifp->ifindex, vni);
b7cfce93
MK
6122 return 0;
6123 }
6124
6125 /* associate with vxlan_if */
6126 zl3vni->vxlan_if = ifp;
6127
6128 /* Associate with SVI, if any. We can associate with svi-if only
6129 * after association with vxlan_if is complete */
6130 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6131
6132 if (is_l3vni_oper_up(zl3vni))
6133 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6134 } else {
6135
6136 /* process if-add for l2-vni */
6137 zebra_vni_t *zvni = NULL;
6138 zebra_l3vni_t *zl3vni = NULL;
6139 struct interface *vlan_if = NULL;
6140
6141 /* Create or update VNI hash. */
6142 zvni = zvni_lookup(vni);
6143 if (!zvni) {
6144 zvni = zvni_add(vni);
6145 if (!zvni) {
6146 zlog_err(
6147 "Failed to add VNI hash, IF %s(%u) VNI %u",
6148 ifp->name, ifp->ifindex, vni);
6149 return -1;
6150 }
6151 }
6152
6153 zvni->local_vtep_ip = vxl->vtep_ip;
6154 zvni->vxlan_if = ifp;
6155 vlan_if = zvni_map_to_svi(vxl->access_vlan,
6156 zif->brslave_info.br_if);
6157 if (vlan_if) {
6158 zvni->vrf_id = vlan_if->vrf_id;
6159 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
6160 if (zl3vni)
6161 listnode_add_sort(zl3vni->l2vnis, zvni);
6162 }
6163
6164 if (IS_ZEBRA_DEBUG_VXLAN)
6165 zlog_debug(
6166 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6167 vni,
6168 vlan_if ? vrf_id_to_name(vlan_if->vrf_id) :
6169 "Default",
6170 ifp->name, ifp->ifindex,
6171 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
6172 zif->brslave_info.bridge_ifindex);
6173
6174 /* If down or not mapped to a bridge, we're done. */
6175 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6176 return 0;
6177
6178 /* Inform BGP */
6179 zvni_send_add_to_client(zvni);
6180
6181 /* Read and populate local MACs and neighbors */
6182 zvni_read_mac_neigh(zvni, ifp);
6183 }
6184
6185 return 0;
6186}
6187
6188int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf,
6189 vni_t vni, char *err,
6190 int add)
6191{
6192 zebra_l3vni_t *zl3vni = NULL;
6193 struct zebra_vrf *zvrf_default = NULL;
6194
6195 zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
6196 if (!zvrf_default)
6197 return -1;
6198
6199 if (IS_ZEBRA_DEBUG_VXLAN)
6200 zlog_debug("vrf %s vni %u %s",
6201 zvrf_name(zvrf),
6202 vni,
6203 add ? "ADD" : "DEL");
6204
6205 if (add) {
6206
6207 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
6208
6209 /* check if the vni is already present under zvrf */
6210 if (zvrf->l3vni) {
6211 snprintf(err, ERR_STR_SZ,
6212 "VNI is already configured under the vrf");
6213 return -1;
6214 }
6215
6216 /* check if this VNI is already present in the system */
6217 zl3vni = zl3vni_lookup(vni);
6218 if (zl3vni) {
6219 snprintf(err, ERR_STR_SZ,
6220 "VNI is already configured as L3-VNI");
6221 return -1;
6222 }
6223
6224 /* add the L3-VNI to the global table */
6225 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
6226 if (!zl3vni) {
6227 snprintf(err, ERR_STR_SZ,
6228 "Could not add L3-VNI");
6229 return -1;
6230 }
6231
6232 /* associate the vrf with vni */
6233 zvrf->l3vni = vni;
6234
6235 /* associate with vxlan-intf;
6236 * we need to associate with the vxlan-intf first */
6237 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
6238
6239 /* associate with corresponding SVI interface, we can associate
6240 * with svi-if only after vxlan interface association is
6241 * complete */
6242 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6243
6244 /* formulate l2vni list */
6245 hash_iterate(zvrf_default->vni_table,
6246 zvni_add_to_l3vni_list, zl3vni);
6247
6248 if (is_l3vni_oper_up(zl3vni))
6249 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6250
6251 } else {
6252 zl3vni = zl3vni_lookup(vni);
6253 if (!zl3vni) {
6254 snprintf(err, ERR_STR_SZ, "VNI doesn't exist");
d62a17ae 6255 return -1;
6256 }
b7cfce93
MK
6257
6258 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6259
6260 zvrf->l3vni = 0;
6261 zl3vni_del(zl3vni);
6262
6263 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
d62a17ae 6264 }
b7cfce93
MK
6265 return 0;
6266}
13d60d35 6267
b7cfce93
MK
6268int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
6269{
6270 zebra_l3vni_t *zl3vni = NULL;
13d60d35 6271
b7cfce93
MK
6272 zl3vni = zl3vni_from_vrf(zvrf_id(zvrf));
6273 if (!zl3vni)
d62a17ae 6274 return 0;
13d60d35 6275
b7cfce93
MK
6276 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6277 zl3vni_del(zl3vni);
6278 zebra_vxlan_handle_vni_transition(zvrf, zl3vni->vni, 0);
2232a77c 6279
d62a17ae 6280 return 0;
13d60d35 6281}
6282
1a98c087
MK
6283/*
6284 * Handle message from client to enable/disable advertisement of g/w macip
6285 * routes
6286 */
e4bd522a
DS
6287int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
6288 struct zebra_vrf *zvrf)
1a98c087
MK
6289{
6290 struct stream *s;
6291 int advertise;
6292 vni_t vni = 0;
6293 zebra_vni_t *zvni = NULL;
b5ebdc9b 6294 struct interface *ifp = NULL;
1a98c087 6295
2853fed6 6296 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6297 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6298 zvrf_id(zvrf));
6299 return -1;
6300 }
6301
1a98c087 6302 s = client->ibuf;
ec93aa12
DS
6303 STREAM_GETC(s, advertise);
6304 STREAM_GET(&vni, s, 3);
1a98c087
MK
6305
6306 if (!vni) {
6307 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 6308 zlog_debug("EVPN gateway macip Adv %s, currently %s",
1a98c087 6309 advertise ? "enabled" : "disabled",
2853fed6 6310 advertise_gw_macip_enabled(NULL)
1a98c087
MK
6311 ? "enabled"
6312 : "disabled");
6313
6314 if (zvrf->advertise_gw_macip == advertise)
6315 return 0;
6316
6317 zvrf->advertise_gw_macip = advertise;
6318
2853fed6 6319 if (advertise_gw_macip_enabled(zvni))
1a98c087 6320 hash_iterate(zvrf->vni_table,
2853fed6 6321 zvni_gw_macip_add_for_vni_hash, NULL);
1a98c087
MK
6322 else
6323 hash_iterate(zvrf->vni_table,
2853fed6 6324 zvni_gw_macip_del_for_vni_hash, NULL);
1a98c087
MK
6325
6326 } else {
6327 struct zebra_if *zif = NULL;
6328 struct zebra_l2info_vxlan zl2_info;
6329 struct interface *vlan_if = NULL;
6330 struct interface *vrr_if = NULL;
6331
6332 if (IS_ZEBRA_DEBUG_VXLAN)
6333 zlog_debug(
2853fed6 6334 "EVPN gateway macip Adv %s on VNI %d , currently %s",
1a98c087 6335 advertise ? "enabled" : "disabled", vni,
2853fed6 6336 advertise_gw_macip_enabled(zvni)
1a98c087
MK
6337 ? "enabled"
6338 : "disabled");
6339
2853fed6 6340 zvni = zvni_lookup(vni);
1a98c087
MK
6341 if (!zvni)
6342 return 0;
6343
6344 if (zvni->advertise_gw_macip == advertise)
6345 return 0;
6346
6347 zvni->advertise_gw_macip = advertise;
6348
b5ebdc9b 6349 ifp = zvni->vxlan_if;
6350 if (!ifp)
6351 return 0;
6352
6353 zif = ifp->info;
6354
6355 /* If down or not mapped to a bridge, we're done. */
b682f6de 6356 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 6357 return 0;
6358
1a98c087
MK
6359 zl2_info = zif->l2info.vxl;
6360
2853fed6 6361 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
1a98c087
MK
6362 zif->brslave_info.br_if);
6363 if (!vlan_if)
6364 return 0;
6365
2853fed6 6366 if (advertise_gw_macip_enabled(zvni)) {
1a98c087
MK
6367 /* Add primary SVI MAC-IP */
6368 zvni_add_macip_for_intf(vlan_if, zvni);
6369
6370 /* Add VRR MAC-IP - if any*/
6371 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6372 if (vrr_if)
6373 zvni_add_macip_for_intf(vrr_if, zvni);
6374 } else {
6375 /* Del primary MAC-IP */
6376 zvni_del_macip_for_intf(vlan_if, zvni);
6377
6378 /* Del VRR MAC-IP - if any*/
6379 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6380 if (vrr_if)
6381 zvni_del_macip_for_intf(vrr_if, zvni);
6382 }
6383 }
6384
ec93aa12 6385stream_failure:
1a98c087
MK
6386 return 0;
6387}
6388
6389
13d60d35 6390/*
6391 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6392 * When enabled, the VNI hash table will be built and MAC FDB table read;
6393 * when disabled, the entries should be deleted and remote VTEPs and MACs
6394 * uninstalled from the kernel.
6395 */
e4bd522a 6396int zebra_vxlan_advertise_all_vni(struct zserv *client,
d62a17ae 6397 u_short length, struct zebra_vrf *zvrf)
13d60d35 6398{
d62a17ae 6399 struct stream *s;
6400 int advertise;
13d60d35 6401
2853fed6 6402 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6403 zlog_err("EVPN VNI Adv for non-default VRF %u",
6404 zvrf_id(zvrf));
6405 return -1;
6406 }
6407
d62a17ae 6408 s = client->ibuf;
ec93aa12 6409 STREAM_GETC(s, advertise);
13d60d35 6410
d62a17ae 6411 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 6412 zlog_debug("EVPN VNI Adv %s, currently %s",
d62a17ae 6413 advertise ? "enabled" : "disabled",
2853fed6 6414 is_evpn_enabled() ? "enabled" : "disabled");
13d60d35 6415
d62a17ae 6416 if (zvrf->advertise_all_vni == advertise)
6417 return 0;
13d60d35 6418
d62a17ae 6419 zvrf->advertise_all_vni = advertise;
2853fed6 6420 if (is_evpn_enabled()) {
d62a17ae 6421 /* Build VNI hash table and inform BGP. */
2853fed6 6422 zvni_build_hash_table();
2232a77c 6423
1a98c087
MK
6424 /* Add all SVI (L3 GW) MACs to BGP*/
6425 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
2853fed6 6426 NULL);
1a98c087 6427
d62a17ae 6428 /* Read the MAC FDB */
6429 macfdb_read(zvrf->zns);
2232a77c 6430
d62a17ae 6431 /* Read neighbors */
6432 neigh_read(zvrf->zns);
6433 } else {
6434 /* Cleanup VTEPs for all VNIs - uninstall from
6435 * kernel and free entries.
6436 */
6437 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
6438 }
13d60d35 6439
ec93aa12 6440stream_failure:
d62a17ae 6441 return 0;
13d60d35 6442}
6443
6444/*
6445 * Allocate VNI hash table for this VRF and do other initialization.
6446 * NOTE: Currently supported only for default VRF.
6447 */
d62a17ae 6448void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 6449{
d62a17ae 6450 if (!zvrf)
6451 return;
6452 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
6453 "Zebra VRF VNI Table");
13d60d35 6454}
6455
6456/* Close all VNI handling */
d62a17ae 6457void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 6458{
2853fed6 6459 if (!zvrf)
6460 return;
d62a17ae 6461 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9b67b514 6462 hash_free(zvrf->vni_table);
13d60d35 6463}
b7cfce93
MK
6464
6465/* init the l3vni table */
6466void zebra_vxlan_ns_init(struct zebra_ns *zns)
6467{
6468 zns->l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
6469 "Zebra VRF L3 VNI table");
6470}
6471
6472/* free l3vni table */
6473void zebra_vxlan_ns_disable(struct zebra_ns *zns)
6474{
6475 hash_free(zns->l3vni_table);
6476}
d3135ba3 6477
6478/* get the l3vni svi ifindex */
6479ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
6480{
6481 zebra_l3vni_t *zl3vni = NULL;
6482
6483 zl3vni = zl3vni_from_vrf(vrf_id);
6484 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
6485 return 0;
6486
6487 return zl3vni->svi_if->ifindex;
6488}