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