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