]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
Merge pull request #2050 from chipitsine/master
[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
2232a77c 1933/*
1934 * Make hash key for MAC.
1935 */
d62a17ae 1936static unsigned int mac_hash_keymake(void *p)
2232a77c 1937{
d62a17ae 1938 zebra_mac_t *pmac = p;
25331def
DS
1939 const void *pnt = (void *)pmac->macaddr.octet;
1940
ff8b7eb8 1941 return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
2232a77c 1942}
13d60d35 1943
2232a77c 1944/*
1945 * Compare two MAC addresses.
1946 */
d62a17ae 1947static int mac_cmp(const void *p1, const void *p2)
2232a77c 1948{
d62a17ae 1949 const zebra_mac_t *pmac1 = p1;
1950 const zebra_mac_t *pmac2 = p2;
2232a77c 1951
d62a17ae 1952 if (pmac1 == NULL && pmac2 == NULL)
1953 return 1;
2232a77c 1954
d62a17ae 1955 if (pmac1 == NULL || pmac2 == NULL)
1956 return 0;
2232a77c 1957
996c9314 1958 return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
d62a17ae 1959 == 0);
2232a77c 1960}
1961
1962/*
1963 * Callback to allocate MAC hash entry.
1964 */
d62a17ae 1965static void *zvni_mac_alloc(void *p)
2232a77c 1966{
d62a17ae 1967 const zebra_mac_t *tmp_mac = p;
1968 zebra_mac_t *mac;
2232a77c 1969
d62a17ae 1970 mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
1971 *mac = *tmp_mac;
2232a77c 1972
d62a17ae 1973 return ((void *)mac);
2232a77c 1974}
1975
1976/*
1977 * Add MAC entry.
1978 */
d62a17ae 1979static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
2232a77c 1980{
d62a17ae 1981 zebra_mac_t tmp_mac;
1982 zebra_mac_t *mac = NULL;
2232a77c 1983
d62a17ae 1984 memset(&tmp_mac, 0, sizeof(zebra_mac_t));
ff8b7eb8 1985 memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
d62a17ae 1986 mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
1987 assert(mac);
2232a77c 1988
b6938a74
MK
1989 mac->neigh_list = list_new();
1990 mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp;
1991
d62a17ae 1992 return mac;
2232a77c 1993}
1994
1995/*
1996 * Delete MAC entry.
1997 */
d62a17ae 1998static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 1999{
d62a17ae 2000 zebra_mac_t *tmp_mac;
2232a77c 2001
affe9e99 2002 list_delete_and_null(&mac->neigh_list);
b6938a74 2003
d62a17ae 2004 /* Free the VNI hash entry and allocated memory. */
2005 tmp_mac = hash_release(zvni->mac_table, mac);
2006 if (tmp_mac)
2007 XFREE(MTYPE_MAC, tmp_mac);
2232a77c 2008
d62a17ae 2009 return 0;
2232a77c 2010}
2011
2012/*
2013 * Free MAC hash entry (callback)
2014 */
d62a17ae 2015static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
2232a77c 2016{
d62a17ae 2017 struct mac_walk_ctx *wctx = arg;
2018 zebra_mac_t *mac = backet->data;
2232a77c 2019
d62a17ae 2020 if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
2021 || ((wctx->flags & DEL_REMOTE_MAC)
2022 && (mac->flags & ZEBRA_MAC_REMOTE))
2023 || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
2024 && (mac->flags & ZEBRA_MAC_REMOTE)
2025 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
2026 &wctx->r_vtep_ip))) {
2027 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
996c9314
LB
2028 zvni_mac_send_del_to_client(wctx->zvni->vni,
2029 &mac->macaddr, mac->flags);
d62a17ae 2030 }
2232a77c 2031
d62a17ae 2032 if (wctx->uninstall)
2033 zvni_mac_uninstall(wctx->zvni, mac, 0);
2232a77c 2034
d62a17ae 2035 return zvni_mac_del(wctx->zvni, mac);
2036 }
2232a77c 2037
d62a17ae 2038 return 0;
2232a77c 2039}
2040
2041/*
2042 * Delete all MAC entries from specific VTEP for a particular VNI.
2043 */
d62a17ae 2044static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
2045 struct in_addr *r_vtep_ip)
2232a77c 2046{
d62a17ae 2047 struct mac_walk_ctx wctx;
2232a77c 2048
d62a17ae 2049 if (!zvni->mac_table)
2050 return;
2232a77c 2051
d62a17ae 2052 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2053 wctx.zvni = zvni;
2054 wctx.uninstall = uninstall;
2055 wctx.flags = DEL_REMOTE_MAC_FROM_VTEP;
2056 wctx.r_vtep_ip = *r_vtep_ip;
2232a77c 2057
9d303b37
DL
2058 hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *,
2059 void *))zvni_mac_del_hash_entry,
2060 &wctx);
2232a77c 2061}
2062
2063/*
2064 * Delete all MAC entries for this VNI.
2065 */
996c9314 2066static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
d7c0a89a 2067 uint32_t flags)
2232a77c 2068{
d62a17ae 2069 struct mac_walk_ctx wctx;
2232a77c 2070
d62a17ae 2071 if (!zvni->mac_table)
2072 return;
2232a77c 2073
d62a17ae 2074 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2075 wctx.zvni = zvni;
d62a17ae 2076 wctx.uninstall = uninstall;
2077 wctx.upd_client = upd_client;
2078 wctx.flags = flags;
2232a77c 2079
9d303b37
DL
2080 hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *,
2081 void *))zvni_mac_del_hash_entry,
2082 &wctx);
2232a77c 2083}
2084
2085/*
2086 * Look up MAC hash entry.
2087 */
d62a17ae 2088static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
2232a77c 2089{
d62a17ae 2090 zebra_mac_t tmp;
2091 zebra_mac_t *pmac;
2232a77c 2092
d62a17ae 2093 memset(&tmp, 0, sizeof(tmp));
ff8b7eb8 2094 memcpy(&tmp.macaddr, mac, ETH_ALEN);
d62a17ae 2095 pmac = hash_lookup(zvni->mac_table, &tmp);
2232a77c 2096
d62a17ae 2097 return pmac;
2232a77c 2098}
2099
2100/*
2101 * Inform BGP about local MAC addition.
2102 */
996c9314 2103static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
d7c0a89a 2104 uint8_t mac_flags)
2232a77c 2105{
d7c0a89a 2106 uint8_t flags = 0;
ead40654
MK
2107
2108 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
2109 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
2110 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
2111 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2112
2853fed6 2113 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
d62a17ae 2114 ZEBRA_MACIP_ADD);
2232a77c 2115}
2116
2117/*
2118 * Inform BGP about local MAC deletion.
2119 */
996c9314 2120static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
d7c0a89a 2121 uint8_t mac_flags)
2232a77c 2122{
d7c0a89a 2123 uint8_t flags = 0;
ead40654
MK
2124
2125 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
2126 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
2127 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
2128 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2129
2853fed6 2130 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
d62a17ae 2131 ZEBRA_MACIP_DEL);
2232a77c 2132}
2133
2134/*
2135 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2853fed6 2136 * notifications, to see if they are of interest.
2232a77c 2137 */
d62a17ae 2138static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
2139 struct interface *br_if, vlanid_t vid)
2232a77c 2140{
2853fed6 2141 struct zebra_ns *zns;
2142 struct route_node *rn;
2143 struct interface *tmp_if = NULL;
d62a17ae 2144 struct zebra_if *zif;
2145 struct zebra_l2info_bridge *br;
2853fed6 2146 struct zebra_l2info_vxlan *vxl = NULL;
d7c0a89a 2147 uint8_t bridge_vlan_aware;
d62a17ae 2148 zebra_vni_t *zvni;
2853fed6 2149 int found = 0;
2232a77c 2150
d62a17ae 2151 /* Determine if bridge is VLAN-aware or not */
2152 zif = br_if->info;
2153 assert(zif);
2154 br = &zif->l2info.br;
2155 bridge_vlan_aware = br->vlan_aware;
2232a77c 2156
d62a17ae 2157 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2158 /* TODO: Optimize with a hash. */
2853fed6 2159 zns = zebra_ns_lookup(NS_DEFAULT);
2160 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2161 tmp_if = (struct interface *)rn->info;
2162 if (!tmp_if)
2163 continue;
d62a17ae 2164 zif = tmp_if->info;
2165 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2166 continue;
2167 if (!if_is_operative(tmp_if))
2168 continue;
2169 vxl = &zif->l2info.vxl;
2232a77c 2170
d62a17ae 2171 if (zif->brslave_info.br_if != br_if)
2172 continue;
2232a77c 2173
2853fed6 2174 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
2175 found = 1;
d62a17ae 2176 break;
2853fed6 2177 }
d62a17ae 2178 }
2232a77c 2179
2853fed6 2180 if (!found)
d62a17ae 2181 return NULL;
2232a77c 2182
2853fed6 2183 zvni = zvni_lookup(vxl->vni);
d62a17ae 2184 return zvni;
2232a77c 2185}
2186
2187/*
2188 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2189 * neighbor notifications, to see if they are of interest.
2232a77c 2190 */
b7cfce93
MK
2191static zebra_vni_t *zvni_from_svi(struct interface *ifp,
2192 struct interface *br_if)
d62a17ae 2193{
2853fed6 2194 struct zebra_ns *zns;
2195 struct route_node *rn;
2196 struct interface *tmp_if = NULL;
d62a17ae 2197 struct zebra_if *zif;
2198 struct zebra_l2info_bridge *br;
2853fed6 2199 struct zebra_l2info_vxlan *vxl = NULL;
d7c0a89a 2200 uint8_t bridge_vlan_aware;
d62a17ae 2201 vlanid_t vid = 0;
2202 zebra_vni_t *zvni;
2853fed6 2203 int found = 0;
d62a17ae 2204
71349e03
MK
2205 if (!br_if)
2206 return NULL;
2207
d62a17ae 2208 /* Make sure the linked interface is a bridge. */
2209 if (!IS_ZEBRA_IF_BRIDGE(br_if))
2210 return NULL;
2211
d62a17ae 2212 /* Determine if bridge is VLAN-aware or not */
2213 zif = br_if->info;
2214 assert(zif);
2215 br = &zif->l2info.br;
2216 bridge_vlan_aware = br->vlan_aware;
2217 if (bridge_vlan_aware) {
2218 struct zebra_l2info_vlan *vl;
2219
2220 if (!IS_ZEBRA_IF_VLAN(ifp))
2221 return NULL;
2222
2223 zif = ifp->info;
2224 assert(zif);
2225 vl = &zif->l2info.vl;
2226 vid = vl->vid;
2227 }
2228
2229 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2230 /* TODO: Optimize with a hash. */
2853fed6 2231 zns = zebra_ns_lookup(NS_DEFAULT);
2232 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2233 tmp_if = (struct interface *)rn->info;
2234 if (!tmp_if)
2235 continue;
d62a17ae 2236 zif = tmp_if->info;
2237 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2238 continue;
2239 if (!if_is_operative(tmp_if))
2240 continue;
2241 vxl = &zif->l2info.vxl;
2242
2243 if (zif->brslave_info.br_if != br_if)
2244 continue;
2245
2853fed6 2246 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
2247 found = 1;
d62a17ae 2248 break;
2853fed6 2249 }
d62a17ae 2250 }
2251
2853fed6 2252 if (!found)
d62a17ae 2253 return NULL;
2254
2853fed6 2255 zvni = zvni_lookup(vxl->vni);
d62a17ae 2256 return zvni;
2232a77c 2257}
2258
2259/* Map to SVI on bridge corresponding to specified VLAN. This can be one
2260 * of two cases:
2261 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2262 * linked to the bridge
2263 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2264 * itself
2265 */
2853fed6 2266static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
d62a17ae 2267{
2853fed6 2268 struct zebra_ns *zns;
2269 struct route_node *rn;
2270 struct interface *tmp_if = NULL;
d62a17ae 2271 struct zebra_if *zif;
2272 struct zebra_l2info_bridge *br;
2273 struct zebra_l2info_vlan *vl;
d7c0a89a 2274 uint8_t bridge_vlan_aware;
2853fed6 2275 int found = 0;
d62a17ae 2276
b5ebdc9b 2277 /* Defensive check, caller expected to invoke only with valid bridge. */
2278 if (!br_if)
2279 return NULL;
2280
d62a17ae 2281 /* Determine if bridge is VLAN-aware or not */
2282 zif = br_if->info;
2283 assert(zif);
2284 br = &zif->l2info.br;
2285 bridge_vlan_aware = br->vlan_aware;
2286
2287 /* Check oper status of the SVI. */
2288 if (!bridge_vlan_aware)
2289 return if_is_operative(br_if) ? br_if : NULL;
2290
2291 /* Identify corresponding VLAN interface. */
2292 /* TODO: Optimize with a hash. */
2853fed6 2293 zns = zebra_ns_lookup(NS_DEFAULT);
2294 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2295 tmp_if = (struct interface *)rn->info;
d62a17ae 2296 /* Check oper status of the SVI. */
2853fed6 2297 if (!tmp_if || !if_is_operative(tmp_if))
d62a17ae 2298 continue;
2299 zif = tmp_if->info;
2300 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
2301 || zif->link != br_if)
2302 continue;
2303 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
2304
2853fed6 2305 if (vl->vid == vid) {
2306 found = 1;
d62a17ae 2307 break;
2853fed6 2308 }
d62a17ae 2309 }
2310
2853fed6 2311 return found ? tmp_if : NULL;
2232a77c 2312}
2313
2314/*
2315 * Install remote MAC into the kernel.
2316 */
d62a17ae 2317static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 2318{
d62a17ae 2319 struct zebra_if *zif;
2320 struct zebra_l2info_vxlan *vxl;
d7c0a89a 2321 uint8_t sticky;
2232a77c 2322
d62a17ae 2323 if (!(mac->flags & ZEBRA_MAC_REMOTE))
2324 return 0;
2232a77c 2325
d62a17ae 2326 zif = zvni->vxlan_if->info;
2327 if (!zif)
2328 return -1;
2329 vxl = &zif->l2info.vxl;
2232a77c 2330
d62a17ae 2331 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
c85c03c7 2332
d62a17ae 2333 return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
2334 mac->fwd_info.r_vtep_ip, sticky);
2232a77c 2335}
2336
2337/*
2338 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2339 * moves to remote, we have to uninstall any existing local entry first.
2340 */
d62a17ae 2341static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local)
2232a77c 2342{
d62a17ae 2343 struct zebra_if *zif;
2344 struct zebra_l2info_vxlan *vxl;
2345 struct in_addr vtep_ip = {.s_addr = 0};
2346 struct zebra_ns *zns;
2347 struct interface *ifp;
2232a77c 2348
d62a17ae 2349 if (!local && !(mac->flags & ZEBRA_MAC_REMOTE))
2350 return 0;
2232a77c 2351
d62a17ae 2352 if (!zvni->vxlan_if) {
2353 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2354 zvni->vni, zvni);
2355 return -1;
2356 }
2232a77c 2357
d62a17ae 2358 zif = zvni->vxlan_if->info;
2359 if (!zif)
2360 return -1;
2361 vxl = &zif->l2info.vxl;
2232a77c 2362
d62a17ae 2363 if (local) {
2364 zns = zebra_ns_lookup(NS_DEFAULT);
2365 ifp = if_lookup_by_index_per_ns(zns,
2366 mac->fwd_info.local.ifindex);
2367 if (!ifp) // unexpected
2368 return -1;
2369 } else {
2370 ifp = zvni->vxlan_if;
2371 vtep_ip = mac->fwd_info.r_vtep_ip;
2372 }
2232a77c 2373
d62a17ae 2374 return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip,
2375 local);
2232a77c 2376}
2377
2378/*
2379 * Install MAC hash entry - called upon access VLAN change.
2380 */
d62a17ae 2381static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
2232a77c 2382{
d62a17ae 2383 zebra_mac_t *mac;
2384 struct mac_walk_ctx *wctx = ctxt;
2232a77c 2385
d62a17ae 2386 mac = (zebra_mac_t *)backet->data;
2387 if (!mac)
2388 return;
2232a77c 2389
d62a17ae 2390 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
2391 zvni_mac_install(wctx->zvni, mac);
2232a77c 2392}
2393
2394/*
2395 * Decrement neighbor refcount of MAC; uninstall and free it if
2396 * appropriate.
2397 */
d62a17ae 2398static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
2399 int uninstall)
2232a77c 2400{
60466a63
QY
2401 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)
2402 || !list_isempty(mac->neigh_list))
d62a17ae 2403 return;
2232a77c 2404
d62a17ae 2405 if (uninstall)
2406 zvni_mac_uninstall(zvni, mac, 0);
2232a77c 2407
d62a17ae 2408 zvni_mac_del(zvni, mac);
2232a77c 2409}
2410
2411/*
2412 * Read and populate local MACs and neighbors corresponding to this VNI.
2413 */
996c9314 2414static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
2232a77c 2415{
2853fed6 2416 struct zebra_ns *zns;
d62a17ae 2417 struct zebra_if *zif;
2418 struct interface *vlan_if;
2419 struct zebra_l2info_vxlan *vxl;
1a98c087 2420 struct interface *vrr_if;
2232a77c 2421
d62a17ae 2422 zif = ifp->info;
2423 vxl = &zif->l2info.vxl;
2853fed6 2424 zns = zebra_ns_lookup(NS_DEFAULT);
2232a77c 2425
d62a17ae 2426 if (IS_ZEBRA_DEBUG_VXLAN)
2427 zlog_debug(
2853fed6 2428 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2429 ifp->name, ifp->ifindex, zvni->vni,
d62a17ae 2430 zif->brslave_info.bridge_ifindex);
2232a77c 2431
2853fed6 2432 macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if);
2433 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
1a98c087
MK
2434 if (vlan_if) {
2435
ead40654
MK
2436 /* Add SVI MAC-IP */
2437 zvni_add_macip_for_intf(vlan_if, zvni);
1a98c087 2438
ead40654
MK
2439 /* Add VRR MAC-IP - if any*/
2440 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2441 if (vrr_if)
2442 zvni_add_macip_for_intf(vrr_if, zvni);
1a98c087 2443
2853fed6 2444 neigh_read_for_vlan(zns, vlan_if);
1a98c087 2445 }
2232a77c 2446}
2447
2448/*
2449 * Hash function for VNI.
2450 */
d62a17ae 2451static unsigned int vni_hash_keymake(void *p)
2232a77c 2452{
d62a17ae 2453 const zebra_vni_t *zvni = p;
2232a77c 2454
d62a17ae 2455 return (jhash_1word(zvni->vni, 0));
2232a77c 2456}
2457
2458/*
2459 * Compare 2 VNI hash entries.
2460 */
d62a17ae 2461static int vni_hash_cmp(const void *p1, const void *p2)
2232a77c 2462{
d62a17ae 2463 const zebra_vni_t *zvni1 = p1;
2464 const zebra_vni_t *zvni2 = p2;
2232a77c 2465
d62a17ae 2466 return (zvni1->vni == zvni2->vni);
2232a77c 2467}
2468
2469/*
2470 * Callback to allocate VNI hash entry.
2471 */
d62a17ae 2472static void *zvni_alloc(void *p)
2232a77c 2473{
d62a17ae 2474 const zebra_vni_t *tmp_vni = p;
2475 zebra_vni_t *zvni;
2232a77c 2476
d62a17ae 2477 zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t));
2478 zvni->vni = tmp_vni->vni;
2479 return ((void *)zvni);
2232a77c 2480}
2481
2482/*
2483 * Look up VNI hash entry.
2484 */
2853fed6 2485static zebra_vni_t *zvni_lookup(vni_t vni)
2232a77c 2486{
2853fed6 2487 struct zebra_vrf *zvrf;
d62a17ae 2488 zebra_vni_t tmp_vni;
2489 zebra_vni_t *zvni = NULL;
2232a77c 2490
2853fed6 2491 zvrf = vrf_info_lookup(VRF_DEFAULT);
2492 assert(zvrf);
d62a17ae 2493 memset(&tmp_vni, 0, sizeof(zebra_vni_t));
2494 tmp_vni.vni = vni;
2495 zvni = hash_lookup(zvrf->vni_table, &tmp_vni);
2232a77c 2496
d62a17ae 2497 return zvni;
2232a77c 2498}
2499
2500/*
2501 * Add VNI hash entry.
2502 */
2853fed6 2503static zebra_vni_t *zvni_add(vni_t vni)
2232a77c 2504{
2853fed6 2505 struct zebra_vrf *zvrf;
d62a17ae 2506 zebra_vni_t tmp_zvni;
2507 zebra_vni_t *zvni = NULL;
2232a77c 2508
2853fed6 2509 zvrf = vrf_info_lookup(VRF_DEFAULT);
2510 assert(zvrf);
d62a17ae 2511 memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
2512 tmp_zvni.vni = vni;
2513 zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc);
2514 assert(zvni);
2232a77c 2515
d62a17ae 2516 /* Create hash table for MAC */
2517 zvni->mac_table =
2518 hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table");
2232a77c 2519
d62a17ae 2520 /* Create hash table for neighbors */
2521 zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp,
2522 "Zebra VNI Neighbor Table");
2232a77c 2523
d62a17ae 2524 return zvni;
2232a77c 2525}
2526
2527/*
2528 * Delete VNI hash entry.
2529 */
2853fed6 2530static int zvni_del(zebra_vni_t *zvni)
2232a77c 2531{
2853fed6 2532 struct zebra_vrf *zvrf;
d62a17ae 2533 zebra_vni_t *tmp_zvni;
2232a77c 2534
2853fed6 2535 zvrf = vrf_info_lookup(VRF_DEFAULT);
2536 assert(zvrf);
2537
d62a17ae 2538 zvni->vxlan_if = NULL;
2232a77c 2539
d62a17ae 2540 /* Free the neighbor hash table. */
2541 hash_free(zvni->neigh_table);
2542 zvni->neigh_table = NULL;
2232a77c 2543
d62a17ae 2544 /* Free the MAC hash table. */
2545 hash_free(zvni->mac_table);
2546 zvni->mac_table = NULL;
2232a77c 2547
d62a17ae 2548 /* Free the VNI hash entry and allocated memory. */
2549 tmp_zvni = hash_release(zvrf->vni_table, zvni);
2550 if (tmp_zvni)
2551 XFREE(MTYPE_ZVNI, tmp_zvni);
2232a77c 2552
d62a17ae 2553 return 0;
2232a77c 2554}
2555
2556/*
2557 * Inform BGP about local VNI addition.
2558 */
2853fed6 2559static int zvni_send_add_to_client(zebra_vni_t *zvni)
2232a77c 2560{
d62a17ae 2561 struct zserv *client;
2562 struct stream *s;
2232a77c 2563
019a82cb 2564 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
d62a17ae 2565 /* BGP may not be running. */
2566 if (!client)
2567 return 0;
2232a77c 2568
1002497a 2569 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2232a77c 2570
7cf15b25 2571 zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
d62a17ae 2572 stream_putl(s, zvni->vni);
2573 stream_put_in_addr(s, &zvni->local_vtep_ip);
b7cfce93 2574 stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
2232a77c 2575
d62a17ae 2576 /* Write packet size. */
2577 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 2578
d62a17ae 2579 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
2580 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni->vni,
2581 inet_ntoa(zvni->local_vtep_ip),
b7cfce93 2582 vrf_id_to_name(zvni->vrf_id),
d62a17ae 2583 zebra_route_string(client->proto));
2232a77c 2584
d62a17ae 2585 client->vniadd_cnt++;
1002497a 2586 return zebra_server_send_message(client, s);
2232a77c 2587}
2588
2589/*
2590 * Inform BGP about local VNI deletion.
2591 */
2853fed6 2592static int zvni_send_del_to_client(vni_t vni)
2232a77c 2593{
d62a17ae 2594 struct zserv *client;
2595 struct stream *s;
2232a77c 2596
019a82cb 2597 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
d62a17ae 2598 /* BGP may not be running. */
2599 if (!client)
2600 return 0;
2232a77c 2601
1002497a 2602 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
d62a17ae 2603 stream_reset(s);
2232a77c 2604
7cf15b25 2605 zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
d62a17ae 2606 stream_putl(s, vni);
2232a77c 2607
d62a17ae 2608 /* Write packet size. */
2609 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 2610
d62a17ae 2611 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 2612 zlog_debug("Send VNI_DEL %u to %s", vni,
d62a17ae 2613 zebra_route_string(client->proto));
2232a77c 2614
d62a17ae 2615 client->vnidel_cnt++;
1002497a 2616 return zebra_server_send_message(client, s);
2232a77c 2617}
2618
2619/*
2620 * Build the VNI hash table by going over the VxLAN interfaces. This
2621 * is called when EVPN (advertise-all-vni) is enabled.
2622 */
2853fed6 2623static void zvni_build_hash_table()
2232a77c 2624{
2853fed6 2625 struct zebra_ns *zns;
2626 struct route_node *rn;
d62a17ae 2627 struct interface *ifp;
2232a77c 2628
d62a17ae 2629 /* Walk VxLAN interfaces and create VNI hash. */
2853fed6 2630 zns = zebra_ns_lookup(NS_DEFAULT);
2631 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
b7cfce93 2632 vni_t vni;
643215ce 2633 zebra_vni_t *zvni = NULL;
2634 zebra_l3vni_t *zl3vni = NULL;
d62a17ae 2635 struct zebra_if *zif;
2636 struct zebra_l2info_vxlan *vxl;
2232a77c 2637
2853fed6 2638 ifp = (struct interface *)rn->info;
2639 if (!ifp)
2640 continue;
d62a17ae 2641 zif = ifp->info;
2642 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2643 continue;
2232a77c 2644
b7cfce93 2645 vxl = &zif->l2info.vxl;
d62a17ae 2646 vni = vxl->vni;
2232a77c 2647
643215ce 2648 /* L3-VNI and L2-VNI are handled seperately */
2649 zl3vni = zl3vni_lookup(vni);
2650 if (zl3vni) {
2232a77c 2651
b7cfce93 2652 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
2653 zlog_debug(
2654 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2655 ifp->name, ifp->ifindex, vni);
2232a77c 2656
b7cfce93 2657 /* associate with vxlan_if */
b67a60d2 2658 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 2659 zl3vni->vxlan_if = ifp;
2232a77c 2660
523cafc4 2661 /*
2662 * we need to associate with SVI.
b7cfce93 2663 * we can associate with svi-if only after association
523cafc4 2664 * with vxlan-intf is complete
2665 */
b7cfce93
MK
2666 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
2667
2668 if (is_l3vni_oper_up(zl3vni))
2669 zebra_vxlan_process_l3vni_oper_up(zl3vni);
2670
2671 } else {
b7cfce93
MK
2672 struct interface *vlan_if = NULL;
2673
2674 if (IS_ZEBRA_DEBUG_VXLAN)
2675 zlog_debug(
2676 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2677 ifp->name, ifp->ifindex, vni,
2678 inet_ntoa(vxl->vtep_ip));
2679
2680 /* VNI hash entry is not expected to exist. */
2681 zvni = zvni_lookup(vni);
2682 if (zvni) {
2683 zlog_err(
2684 "VNI hash already present for IF %s(%u) L2-VNI %u",
2685 ifp->name, ifp->ifindex, vni);
2686 continue;
2687 }
2688
2689 zvni = zvni_add(vni);
2690 if (!zvni) {
2691 zlog_err(
2692 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2693 ifp->name, ifp->ifindex, vni);
2694 return;
2695 }
2696
2697 zvni->local_vtep_ip = vxl->vtep_ip;
2698 zvni->vxlan_if = ifp;
2699 vlan_if = zvni_map_to_svi(vxl->access_vlan,
2700 zif->brslave_info.br_if);
2701 if (vlan_if) {
2702 zvni->vrf_id = vlan_if->vrf_id;
2703 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
2704 if (zl3vni)
2705 listnode_add_sort(zl3vni->l2vnis, zvni);
2706 }
2707
2708
2709 /* Inform BGP if intf is up and mapped to bridge. */
2710 if (if_is_operative(ifp) && zif->brslave_info.br_if)
2711 zvni_send_add_to_client(zvni);
2712 }
d62a17ae 2713 }
2232a77c 2714}
2715
2716/*
2717 * See if remote VTEP matches with prefix.
2718 */
d62a17ae 2719static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
2232a77c 2720{
d62a17ae 2721 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
2232a77c 2722}
2723
2724/*
2725 * Locate remote VTEP in VNI hash table.
2726 */
d62a17ae 2727static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2728{
d62a17ae 2729 zebra_vtep_t *zvtep;
2232a77c 2730
d62a17ae 2731 if (!zvni)
2732 return NULL;
2232a77c 2733
d62a17ae 2734 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2735 if (zvni_vtep_match(vtep_ip, zvtep))
2736 break;
2737 }
2232a77c 2738
d62a17ae 2739 return zvtep;
2232a77c 2740}
2741
2742/*
2743 * Add remote VTEP to VNI hash table.
2744 */
d62a17ae 2745static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2746{
d62a17ae 2747 zebra_vtep_t *zvtep;
2232a77c 2748
d62a17ae 2749 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
2750 if (!zvtep) {
2751 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni->vni);
2752 return NULL;
2753 }
2232a77c 2754
d62a17ae 2755 zvtep->vtep_ip = *vtep_ip;
2232a77c 2756
d62a17ae 2757 if (zvni->vteps)
2758 zvni->vteps->prev = zvtep;
2759 zvtep->next = zvni->vteps;
2760 zvni->vteps = zvtep;
2232a77c 2761
d62a17ae 2762 return zvtep;
2232a77c 2763}
2764
2765/*
2766 * Remove remote VTEP from VNI hash table.
2767 */
d62a17ae 2768static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
2232a77c 2769{
d62a17ae 2770 if (zvtep->next)
2771 zvtep->next->prev = zvtep->prev;
2772 if (zvtep->prev)
2773 zvtep->prev->next = zvtep->next;
2774 else
2775 zvni->vteps = zvtep->next;
2232a77c 2776
d62a17ae 2777 zvtep->prev = zvtep->next = NULL;
2778 XFREE(MTYPE_ZVNI_VTEP, zvtep);
2232a77c 2779
d62a17ae 2780 return 0;
2232a77c 2781}
2782
2783/*
2784 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2785 * uninstall from kernel if asked to.
2786 */
d62a17ae 2787static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
2232a77c 2788{
d62a17ae 2789 zebra_vtep_t *zvtep, *zvtep_next;
2232a77c 2790
d62a17ae 2791 if (!zvni)
2792 return -1;
2232a77c 2793
d62a17ae 2794 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
2795 zvtep_next = zvtep->next;
2796 if (uninstall)
2797 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
2798 zvni_vtep_del(zvni, zvtep);
2799 }
2232a77c 2800
d62a17ae 2801 return 0;
2232a77c 2802}
2803
2804/*
2805 * Install remote VTEP into the kernel.
2806 */
d62a17ae 2807static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2808{
d62a17ae 2809 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2810}
2811
2812/*
2813 * Uninstall remote VTEP from the kernel.
2814 */
d62a17ae 2815static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2816{
d62a17ae 2817 if (!zvni->vxlan_if) {
2818 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2819 zvni->vni, zvni);
2820 return -1;
2821 }
2232a77c 2822
d62a17ae 2823 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2824}
2825
2826/*
2827 * Cleanup VNI/VTEP and update kernel
2828 */
84915b0a 2829static void zvni_cleanup_all(struct hash_backet *backet, void *arg)
2232a77c 2830{
b7cfce93
MK
2831 zebra_vni_t *zvni = NULL;
2832 zebra_l3vni_t *zl3vni = NULL;
84915b0a 2833 struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;
2232a77c 2834
d62a17ae 2835 zvni = (zebra_vni_t *)backet->data;
2836 if (!zvni)
2837 return;
2232a77c 2838
b7cfce93 2839 /* remove from l3-vni list */
84915b0a 2840 if (zvrf->l3vni)
2841 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93
MK
2842 if (zl3vni)
2843 listnode_delete(zl3vni->l2vnis, zvni);
2844
d62a17ae 2845 /* Free up all neighbors and MACs, if any. */
2853fed6 2846 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
2847 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
2232a77c 2848
d62a17ae 2849 /* Free up all remote VTEPs, if any. */
2850 zvni_vtep_del_all(zvni, 1);
2232a77c 2851
d62a17ae 2852 /* Delete the hash entry. */
2853fed6 2853 zvni_del(zvni);
2232a77c 2854}
2855
655b04d1 2856/* cleanup L3VNI */
996c9314 2857static void zl3vni_cleanup_all(struct hash_backet *backet, void *args)
655b04d1
MK
2858{
2859 zebra_l3vni_t *zl3vni = NULL;
2860
2861 zl3vni = (zebra_l3vni_t *)backet->data;
2862 if (!zl3vni)
2863 return;
2864
2865 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2866}
2867
996c9314 2868static int is_host_present_in_host_list(struct list *list, struct prefix *host)
6134fd82 2869{
2870 struct listnode *node = NULL;
2871 struct prefix *p = NULL;
2872
2873 for (ALL_LIST_ELEMENTS_RO(list, node, p)) {
2874 if (prefix_same(p, host))
2875 return 1;
2876 }
2877 return 0;
2878}
2879
996c9314 2880static void host_list_add_host(struct list *list, struct prefix *host)
6134fd82 2881{
2882 struct prefix *p = NULL;
2883
2884 p = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct prefix));
2885 memcpy(p, host, sizeof(struct prefix));
2886
2887 listnode_add_sort(list, p);
2888}
2889
996c9314 2890static void host_list_delete_host(struct list *list, struct prefix *host)
6134fd82 2891{
2892 struct listnode *node = NULL, *nnode = NULL, *node_to_del = NULL;
2893 struct prefix *p = NULL;
2894
2895 for (ALL_LIST_ELEMENTS(list, node, nnode, p)) {
2896 if (prefix_same(p, host)) {
2897 XFREE(MTYPE_HOST_PREFIX, p);
2898 node_to_del = node;
2899 }
2900 }
2901
2902 if (node_to_del)
2903 list_delete_node(list, node_to_del);
2904}
2905
b7cfce93
MK
2906/*
2907 * Look up MAC hash entry.
2908 */
2dbad57f 2909static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
b7cfce93
MK
2910 struct ethaddr *rmac)
2911{
2912 zebra_mac_t tmp;
2913 zebra_mac_t *pmac;
2914
2915 memset(&tmp, 0, sizeof(tmp));
2916 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
2917 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
2232a77c 2918
b7cfce93 2919 return pmac;
2dbad57f 2920}
2232a77c 2921
cec2e17d 2922/*
b7cfce93 2923 * Callback to allocate RMAC hash entry.
cec2e17d 2924 */
2dbad57f 2925static void *zl3vni_rmac_alloc(void *p)
d62a17ae 2926{
b7cfce93
MK
2927 const zebra_mac_t *tmp_rmac = p;
2928 zebra_mac_t *zrmac;
d62a17ae 2929
b7cfce93
MK
2930 zrmac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
2931 *zrmac = *tmp_rmac;
d62a17ae 2932
b7cfce93 2933 return ((void *)zrmac);
2dbad57f 2934}
cd233079 2935
b7cfce93
MK
2936/*
2937 * Add RMAC entry to l3-vni
2938 */
996c9314 2939static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac)
b7cfce93
MK
2940{
2941 zebra_mac_t tmp_rmac;
2942 zebra_mac_t *zrmac = NULL;
d62a17ae 2943
b7cfce93
MK
2944 memset(&tmp_rmac, 0, sizeof(zebra_mac_t));
2945 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
2946 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
2947 assert(zrmac);
d62a17ae 2948
6134fd82 2949 zrmac->host_list = list_new();
2950 zrmac->host_list->cmp = (int (*)(void *, void *))prefix_cmp;
b7cfce93 2951
2dbad57f 2952 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
2953 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
2954
b7cfce93 2955 return zrmac;
2dbad57f 2956}
cec2e17d 2957
2958/*
b7cfce93 2959 * Delete MAC entry.
cec2e17d 2960 */
996c9314 2961static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
cec2e17d 2962{
b7cfce93 2963 zebra_mac_t *tmp_rmac;
cd233079 2964
55aabf6f 2965 if (zrmac->host_list)
bb7a24ab 2966 list_delete_and_null(&zrmac->host_list);
55aabf6f 2967 zrmac->host_list = NULL;
cd233079 2968
b7cfce93
MK
2969 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
2970 if (tmp_rmac)
2971 XFREE(MTYPE_MAC, tmp_rmac);
cd233079 2972
b7cfce93 2973 return 0;
2dbad57f 2974}
cec2e17d 2975
2976/*
b7cfce93 2977 * Install remote RMAC into the kernel.
cec2e17d 2978 */
996c9314 2979static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
cec2e17d 2980{
b7cfce93
MK
2981 struct zebra_if *zif = NULL;
2982 struct zebra_l2info_vxlan *vxl = NULL;
cec2e17d 2983
996c9314
LB
2984 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
2985 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
2986 return 0;
2987
2988 zif = zl3vni->vxlan_if->info;
2989 if (!zif)
2990 return -1;
2991
2992 vxl = &zif->l2info.vxl;
2993
2994 return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
996c9314 2995 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
2dbad57f 2996}
b7cfce93
MK
2997
2998/*
2999 * Uninstall remote RMAC from the kernel.
3000 */
996c9314 3001static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
b7cfce93
MK
3002{
3003 char buf[ETHER_ADDR_STRLEN];
3004 struct zebra_if *zif = NULL;
3005 struct zebra_l2info_vxlan *vxl = NULL;
3006
996c9314
LB
3007 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
3008 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
3009 return 0;
3010
3011 if (!zl3vni->vxlan_if) {
523cafc4 3012 zlog_err(
996c9314
LB
3013 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3014 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
3015 zl3vni->vni, zl3vni);
b7cfce93
MK
3016 return -1;
3017 }
3018
3019 zif = zl3vni->vxlan_if->info;
3020 if (!zif)
3021 return -1;
3022
3023 vxl = &zif->l2info.vxl;
3024
3025 return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
3026 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
2dbad57f 3027}
3028
3029/* handle rmac add */
996c9314 3030static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
6134fd82 3031 struct ipaddr *vtep_ip,
3032 struct prefix *host_prefix)
2dbad57f 3033{
3034 char buf[ETHER_ADDR_STRLEN];
3035 char buf1[INET6_ADDRSTRLEN];
3036 zebra_mac_t *zrmac = NULL;
3037
3038 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3039 if (!zrmac) {
3040
3041 zrmac = zl3vni_rmac_add(zl3vni, rmac);
3042 if (!zrmac) {
3043 zlog_warn(
3044 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
996c9314
LB
3045 prefix_mac2str(rmac, buf, sizeof(buf)),
3046 zl3vni->vni,
3047 ipaddr2str(vtep_ip, buf1, sizeof(buf1)));
2dbad57f 3048 return -1;
3049 }
3050 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
3051 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
3052
3053 /* install rmac in kernel */
3054 zl3vni_rmac_install(zl3vni, zrmac);
3055 }
6134fd82 3056
3057 if (!is_host_present_in_host_list(zrmac->host_list, host_prefix))
3058 host_list_add_host(zrmac->host_list, host_prefix);
2dbad57f 3059 return 0;
3060}
3061
3062
3063/* handle rmac delete */
996c9314 3064static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
6134fd82 3065 struct prefix *host_prefix)
2dbad57f 3066{
3067 zebra_mac_t *zrmac = NULL;
3068
3069 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3070 if (!zrmac)
3071 return -1;
3072
6134fd82 3073 host_list_delete_host(zrmac->host_list, host_prefix);
3074 if (list_isempty(zrmac->host_list)) {
2dbad57f 3075
3076 /* uninstall from kernel */
3077 zl3vni_rmac_uninstall(zl3vni, zrmac);
3078
3079 /* del the rmac entry */
3080 zl3vni_rmac_del(zl3vni, zrmac);
3081 }
3082 return 0;
3083}
b7cfce93
MK
3084
3085/*
3086 * Look up nh hash entry on a l3-vni.
3087 */
996c9314 3088static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
b7cfce93
MK
3089{
3090 zebra_neigh_t tmp;
3091 zebra_neigh_t *n;
3092
3093 memset(&tmp, 0, sizeof(tmp));
3094 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
3095 n = hash_lookup(zl3vni->nh_table, &tmp);
3096
3097 return n;
2dbad57f 3098}
b7cfce93
MK
3099
3100
3101/*
3102 * Callback to allocate NH hash entry on L3-VNI.
3103 */
2dbad57f 3104static void *zl3vni_nh_alloc(void *p)
b7cfce93
MK
3105{
3106 const zebra_neigh_t *tmp_n = p;
3107 zebra_neigh_t *n;
3108
3109 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
3110 *n = *tmp_n;
3111
3112 return ((void *)n);
2dbad57f 3113}
b7cfce93
MK
3114
3115/*
3116 * Add neighbor entry.
3117 */
996c9314 3118static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
b7cfce93
MK
3119 struct ethaddr *mac)
3120{
3121 zebra_neigh_t tmp_n;
3122 zebra_neigh_t *n = NULL;
3123
3124 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
3125 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
3126 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
3127 assert(n);
3128
6134fd82 3129 n->host_list = list_new();
3130 n->host_list->cmp = (int (*)(void *, void *))prefix_cmp;
3131
b7cfce93 3132 memcpy(&n->emac, mac, ETH_ALEN);
2dbad57f 3133 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3134 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
b7cfce93
MK
3135
3136 return n;
2dbad57f 3137}
b7cfce93
MK
3138
3139/*
3140 * Delete neighbor entry.
3141 */
996c9314 3142static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
b7cfce93
MK
3143{
3144 zebra_neigh_t *tmp_n;
3145
55aabf6f 3146 if (n->host_list)
bb7a24ab 3147 list_delete_and_null(&n->host_list);
55aabf6f
MK
3148 n->host_list = NULL;
3149
b7cfce93
MK
3150 tmp_n = hash_release(zl3vni->nh_table, n);
3151 if (tmp_n)
3152 XFREE(MTYPE_NEIGH, tmp_n);
3153
3154 return 0;
2dbad57f 3155}
b7cfce93
MK
3156
3157/*
3158 * Install remote nh as neigh into the kernel.
3159 */
996c9314 3160static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
b7cfce93
MK
3161{
3162 if (!is_l3vni_oper_up(zl3vni))
3163 return -1;
3164
996c9314
LB
3165 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
3166 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93
MK
3167 return 0;
3168
3169 return kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac);
2dbad57f 3170}
b7cfce93
MK
3171
3172/*
3173 * Uninstall remote nh from the kernel.
3174 */
996c9314 3175static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
b7cfce93 3176{
996c9314
LB
3177 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
3178 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93
MK
3179 return 0;
3180
fa409e1e 3181 if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
3182 return 0;
3183
b7cfce93 3184 return kernel_del_neigh(zl3vni->svi_if, &n->ip);
2dbad57f 3185}
3186
3187/* add remote vtep as a neigh entry */
996c9314 3188static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
6134fd82 3189 struct ethaddr *rmac,
3190 struct prefix *host_prefix)
2dbad57f 3191{
3192 char buf[ETHER_ADDR_STRLEN];
3193 char buf1[INET6_ADDRSTRLEN];
3194 zebra_neigh_t *nh = NULL;
3195
3196 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
3197 if (!nh) {
3198 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
3199 if (!nh) {
3200
3201 zlog_warn(
3202 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
996c9314
LB
3203 ipaddr2str(vtep_ip, buf1, sizeof(buf1)),
3204 prefix_mac2str(rmac, buf, sizeof(buf)),
2dbad57f 3205 zl3vni->vni);
3206 return -1;
3207 }
3208
3209 /* install the nh neigh in kernel */
3210 zl3vni_nh_install(zl3vni, nh);
3211 }
6134fd82 3212
3213 if (!is_host_present_in_host_list(nh->host_list, host_prefix))
3214 host_list_add_host(nh->host_list, host_prefix);
3215
2dbad57f 3216 return 0;
3217}
3218
3219/* handle nh neigh delete */
996c9314 3220static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
6134fd82 3221 struct prefix *host_prefix)
2dbad57f 3222{
3223 zebra_neigh_t *nh = NULL;
3224
3225 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
3226 if (!nh)
3227 return -1;
3228
6134fd82 3229 host_list_delete_host(nh->host_list, host_prefix);
3230 if (list_isempty(nh->host_list)) {
2dbad57f 3231
3232 /* uninstall from kernel */
3233 zl3vni_nh_uninstall(zl3vni, nh);
3234
3235 /* delete the nh entry */
3236 zl3vni_nh_del(zl3vni, nh);
3237 }
3238
3239 return 0;
3240}
b7cfce93 3241
3bcbba10 3242/* handle neigh update from kernel - the only thing of interest is to
3243 * readd stale entries.
3244 */
996c9314 3245static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
d7c0a89a 3246 uint16_t state)
3bcbba10 3247{
c05a738b 3248#ifdef GNU_LINUX
3bcbba10 3249 zebra_neigh_t *n = NULL;
3250
3251 n = zl3vni_nh_lookup(zl3vni, ip);
3252 if (!n)
3253 return 0;
3254
3255 /* all next hop neigh are remote and installed by frr.
3256 * If the kernel has aged this entry, re-install.
3257 */
3258 if (state & NUD_STALE)
3259 zl3vni_nh_install(zl3vni, n);
c05a738b 3260#endif
3bcbba10 3261 return 0;
3262}
3263
8c9b80b9 3264/* handle neigh delete from kernel */
996c9314 3265static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
8c9b80b9
MK
3266{
3267 zebra_neigh_t *n = NULL;
3268
3269 n = zl3vni_nh_lookup(zl3vni, ip);
3270 if (!n)
3271 return 0;
3272
3273 /* all next hop neigh are remote and installed by frr.
3274 * If we get an age out notification for these neigh entries, we have to
523cafc4 3275 * install it back
3276 */
8c9b80b9
MK
3277 zl3vni_nh_install(zl3vni, n);
3278
3279 return 0;
3280}
3281
b7cfce93
MK
3282/*
3283 * Hash function for L3 VNI.
3284 */
3285static unsigned int l3vni_hash_keymake(void *p)
3286{
3287 const zebra_l3vni_t *zl3vni = p;
3288
3289 return jhash_1word(zl3vni->vni, 0);
3290}
3291
3292/*
3293 * Compare 2 L3 VNI hash entries.
3294 */
3295static int l3vni_hash_cmp(const void *p1, const void *p2)
3296{
3297 const zebra_l3vni_t *zl3vni1 = p1;
3298 const zebra_l3vni_t *zl3vni2 = p2;
3299
3300 return (zl3vni1->vni == zl3vni2->vni);
3301}
3302
3303/*
3304 * Callback to allocate L3 VNI hash entry.
3305 */
3306static void *zl3vni_alloc(void *p)
3307{
3308 zebra_l3vni_t *zl3vni = NULL;
3309 const zebra_l3vni_t *tmp_l3vni = p;
3310
3311 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(zebra_l3vni_t));
3312 zl3vni->vni = tmp_l3vni->vni;
3313 return ((void *)zl3vni);
3314}
3315
3316/*
3317 * Look up L3 VNI hash entry.
3318 */
3319static zebra_l3vni_t *zl3vni_lookup(vni_t vni)
3320{
3321 struct zebra_ns *zns;
3322 zebra_l3vni_t tmp_l3vni;
3323 zebra_l3vni_t *zl3vni = NULL;
3324
3325 zns = zebra_ns_lookup(NS_DEFAULT);
3326 assert(zns);
3327 memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t));
3328 tmp_l3vni.vni = vni;
3329 zl3vni = hash_lookup(zns->l3vni_table, &tmp_l3vni);
3330
3331 return zl3vni;
3332}
3333
3334/*
3335 * Add L3 VNI hash entry.
3336 */
3337static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
3338{
3339 zebra_l3vni_t tmp_zl3vni;
3340 struct zebra_ns *zns = NULL;
3341 zebra_l3vni_t *zl3vni = NULL;
3342
3343 zns = zebra_ns_lookup(NS_DEFAULT);
3344 assert(zns);
3345
3346 memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t));
3347 tmp_zl3vni.vni = vni;
3348
3349 zl3vni = hash_get(zns->l3vni_table, &tmp_zl3vni, zl3vni_alloc);
3350 assert(zl3vni);
3351
3352 zl3vni->vrf_id = vrf_id;
3353 zl3vni->svi_if = NULL;
3354 zl3vni->vxlan_if = NULL;
3355 zl3vni->l2vnis = list_new();
3356 zl3vni->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp;
3357
3358 /* Create hash table for remote RMAC */
996c9314
LB
3359 zl3vni->rmac_table = hash_create(mac_hash_keymake, mac_cmp,
3360 "Zebra L3-VNI RMAC-Table");
b7cfce93
MK
3361
3362 /* Create hash table for neighbors */
3363 zl3vni->nh_table = hash_create(neigh_hash_keymake, neigh_cmp,
996c9314 3364 "Zebra L3-VNI next-hop table");
b7cfce93
MK
3365
3366 return zl3vni;
3367}
3368
3369/*
3370 * Delete L3 VNI hash entry.
3371 */
3372static int zl3vni_del(zebra_l3vni_t *zl3vni)
3373{
3374 struct zebra_ns *zns;
3375 zebra_l3vni_t *tmp_zl3vni;
3376
3377 zns = zebra_ns_lookup(NS_DEFAULT);
3378 assert(zns);
3379
3380 /* free the list of l2vnis */
3381 list_delete_and_null(&zl3vni->l2vnis);
3382 zl3vni->l2vnis = NULL;
3383
3384 /* Free the rmac table */
3385 hash_free(zl3vni->rmac_table);
3386 zl3vni->rmac_table = NULL;
3387
3388 /* Free the nh table */
3389 hash_free(zl3vni->nh_table);
3390 zl3vni->nh_table = NULL;
3391
3392 /* Free the VNI hash entry and allocated memory. */
3393 tmp_zl3vni = hash_release(zns->l3vni_table, zl3vni);
3394 if (tmp_zl3vni)
3395 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
3396
3397 return 0;
3398}
3399
b7cfce93
MK
3400static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
3401{
3402 struct zebra_ns *zns = NULL;
3403 struct route_node *rn = NULL;
3404 struct interface *ifp = NULL;
3405
3406 /* loop through all vxlan-interface */
3407 zns = zebra_ns_lookup(NS_DEFAULT);
3408 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3409
3410 struct zebra_if *zif = NULL;
3411 struct zebra_l2info_vxlan *vxl = NULL;
3412
3413 ifp = (struct interface *)rn->info;
3414 if (!ifp)
3415 continue;
3416
3417 zif = ifp->info;
3418 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3419 continue;
3420
3421 vxl = &zif->l2info.vxl;
b67a60d2 3422 if (vxl->vni == zl3vni->vni) {
3423 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 3424 return ifp;
b67a60d2 3425 }
b7cfce93
MK
3426 }
3427
3428 return NULL;
3429}
3430
3431static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
3432{
996c9314 3433 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
b7cfce93
MK
3434 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
3435
2aeb403d 3436 if (!zl3vni)
3437 return NULL;
3438
b7cfce93
MK
3439 if (!zl3vni->vxlan_if)
3440 return NULL;
3441
3442 zif = zl3vni->vxlan_if->info;
3443 if (!zif)
3444 return NULL;
3445
3446 vxl = &zif->l2info.vxl;
3447
3448 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
3449}
3450
3451static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
3452{
3453 struct zebra_vrf *zvrf = NULL;
3454
3455 zvrf = zebra_vrf_lookup_by_id(vrf_id);
3456 if (!zvrf)
3457 return NULL;
3458
3459 return zl3vni_lookup(zvrf->l3vni);
3460}
3461
3462/*
3463 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3464 * neighbor notifications, to see if they are of interest.
3465 */
3466static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp,
3467 struct interface *br_if)
3468{
3469 int found = 0;
3470 vlanid_t vid = 0;
d7c0a89a 3471 uint8_t bridge_vlan_aware = 0;
b7cfce93
MK
3472 zebra_l3vni_t *zl3vni = NULL;
3473 struct zebra_ns *zns = NULL;
3474 struct route_node *rn = NULL;
3475 struct zebra_if *zif = NULL;
3476 struct interface *tmp_if = NULL;
3477 struct zebra_l2info_bridge *br = NULL;
3478 struct zebra_l2info_vxlan *vxl = NULL;
3479
3480 if (!br_if)
3481 return NULL;
3482
3483 /* Make sure the linked interface is a bridge. */
3484 if (!IS_ZEBRA_IF_BRIDGE(br_if))
3485 return NULL;
3486
3487 /* Determine if bridge is VLAN-aware or not */
3488 zif = br_if->info;
3489 assert(zif);
3490 br = &zif->l2info.br;
3491 bridge_vlan_aware = br->vlan_aware;
3492 if (bridge_vlan_aware) {
3493 struct zebra_l2info_vlan *vl;
3494
3495 if (!IS_ZEBRA_IF_VLAN(ifp))
3496 return NULL;
3497
3498 zif = ifp->info;
3499 assert(zif);
3500 vl = &zif->l2info.vl;
3501 vid = vl->vid;
3502 }
3503
3504 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3505 /* TODO: Optimize with a hash. */
3506 zns = zebra_ns_lookup(NS_DEFAULT);
3507 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3508 tmp_if = (struct interface *)rn->info;
3509 if (!tmp_if)
3510 continue;
3511 zif = tmp_if->info;
3512 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3513 continue;
3514 if (!if_is_operative(tmp_if))
3515 continue;
3516 vxl = &zif->l2info.vxl;
3517
3518 if (zif->brslave_info.br_if != br_if)
3519 continue;
3520
3521 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3522 found = 1;
3523 break;
3524 }
3525 }
3526
3527 if (!found)
3528 return NULL;
3529
3530 zl3vni = zl3vni_lookup(vxl->vni);
3531 return zl3vni;
3532}
3533
3534/*
3535 * Inform BGP about l3-vni.
3536 */
3537static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
3538{
3539 struct stream *s = NULL;
3540 struct zserv *client = NULL;
3541 struct ethaddr rmac;
3542 char buf[ETHER_ADDR_STRLEN];
3543
6f3a2003 3544 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
3545 /* BGP may not be running. */
3546 if (!client)
3547 return 0;
3548
3549 /* get the rmac */
3550 memset(&rmac, 0, sizeof(struct ethaddr));
3551 zl3vni_get_rmac(zl3vni, &rmac);
3552
1002497a 3553 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 3554
996c9314 3555 zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
b7cfce93
MK
3556 stream_putl(s, zl3vni->vni);
3557 stream_put(s, &rmac, sizeof(struct ethaddr));
b67a60d2 3558 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
c48d9f5f 3559 stream_put(s, &zl3vni->filter, sizeof(int));
b7cfce93
MK
3560
3561 /* Write packet size. */
3562 stream_putw_at(s, 0, stream_get_endp(s));
3563
3564 if (IS_ZEBRA_DEBUG_VXLAN)
c48d9f5f 3565 zlog_debug(
996c9314
LB
3566 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3567 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
3568 prefix_mac2str(&rmac, buf, sizeof(buf)),
3569 inet_ntoa(zl3vni->local_vtep_ip),
3570 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
3571 ? "prefix-routes-only"
3572 : "none",
3573 zebra_route_string(client->proto));
b7cfce93
MK
3574
3575 client->l3vniadd_cnt++;
1002497a 3576 return zebra_server_send_message(client, s);
b7cfce93
MK
3577}
3578
3579/*
3580 * Inform BGP about local l3-VNI deletion.
3581 */
3582static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
3583{
3584 struct stream *s = NULL;
3585 struct zserv *client = NULL;
3586
6f3a2003 3587 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
3588 /* BGP may not be running. */
3589 if (!client)
3590 return 0;
3591
1002497a 3592 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 3593
996c9314 3594 zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
b7cfce93
MK
3595 stream_putl(s, zl3vni->vni);
3596
3597 /* Write packet size. */
3598 stream_putw_at(s, 0, stream_get_endp(s));
3599
3600 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 3601 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
b7cfce93
MK
3602 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
3603 zebra_route_string(client->proto));
3604
3605 client->l3vnidel_cnt++;
1002497a 3606 return zebra_server_send_message(client, s);
b7cfce93
MK
3607}
3608
3609static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
3610{
2aeb403d 3611 if (!zl3vni)
3612 return;
3613
b7cfce93
MK
3614 /* send l3vni add to BGP */
3615 zl3vni_send_add_to_client(zl3vni);
3616}
3617
3618static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni)
3619{
2aeb403d 3620 if (!zl3vni)
3621 return;
3622
b7cfce93
MK
3623 /* send l3-vni del to BGP*/
3624 zl3vni_send_del_to_client(zl3vni);
3625}
3626
996c9314 3627static void zvni_add_to_l3vni_list(struct hash_backet *backet, void *ctxt)
b7cfce93 3628{
996c9314
LB
3629 zebra_vni_t *zvni = (zebra_vni_t *)backet->data;
3630 zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)ctxt;
b7cfce93
MK
3631
3632 if (zvni->vrf_id == zl3vni_vrf_id(zl3vni))
3633 listnode_add_sort(zl3vni->l2vnis, zvni);
3634}
3635
b7cfce93
MK
3636/*
3637 * handle transition of vni from l2 to l3 and vice versa
3638 */
996c9314
LB
3639static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
3640 int add)
b7cfce93
MK
3641{
3642 zebra_vni_t *zvni = NULL;
3643
3644 /* There is a possibility that VNI notification was already received
3645 * from kernel and we programmed it as L2-VNI
3646 * In such a case we need to delete this L2-VNI first, so
3647 * that it can be reprogrammed as L3-VNI in the system. It is also
3648 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3649 * interface is still present in kernel. In this case to keep it
523cafc4 3650 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3651 */
b7cfce93
MK
3652 if (add) {
3653 /* Locate hash entry */
3654 zvni = zvni_lookup(vni);
3655 if (!zvni)
3656 return 0;
3657
3658 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 3659 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
b7cfce93
MK
3660
3661 /* Delete VNI from BGP. */
3662 zvni_send_del_to_client(zvni->vni);
3663
3664 /* Free up all neighbors and MAC, if any. */
3665 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
3666 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
3667
3668 /* Free up all remote VTEPs, if any. */
3669 zvni_vtep_del_all(zvni, 0);
3670
3671 /* Delete the hash entry. */
3672 if (zvni_del(zvni)) {
996c9314
LB
3673 zlog_err("Failed to del VNI hash %p, VNI %u", zvni,
3674 zvni->vni);
b7cfce93
MK
3675 return -1;
3676 }
3677 } else {
3678 /* TODO_MITESH: This needs to be thought through. We don't have
3679 * enough information at this point to reprogram the vni as
3680 * l2-vni. One way is to store the required info in l3-vni and
523cafc4 3681 * used it solely for this purpose
3682 */
b7cfce93
MK
3683 }
3684
3685 return 0;
3686}
3687
5e06422c 3688/* delete and uninstall rmac hash entry */
996c9314 3689static void zl3vni_del_rmac_hash_entry(struct hash_backet *backet, void *ctx)
5e06422c
MK
3690{
3691 zebra_mac_t *zrmac = NULL;
3692 zebra_l3vni_t *zl3vni = NULL;
3693
3694 zrmac = (zebra_mac_t *)backet->data;
3695 zl3vni = (zebra_l3vni_t *)ctx;
3696 zl3vni_rmac_uninstall(zl3vni, zrmac);
3697 zl3vni_rmac_del(zl3vni, zrmac);
3698}
3699
3700/* delete and uninstall nh hash entry */
996c9314 3701static void zl3vni_del_nh_hash_entry(struct hash_backet *backet, void *ctx)
5e06422c
MK
3702{
3703 zebra_neigh_t *n = NULL;
3704 zebra_l3vni_t *zl3vni = NULL;
3705
3706 n = (zebra_neigh_t *)backet->data;
3707 zl3vni = (zebra_l3vni_t *)ctx;
3708 zl3vni_nh_uninstall(zl3vni, n);
3709 zl3vni_nh_del(zl3vni, n);
3710}
3711
996c9314
LB
3712static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
3713 uint16_t cmd)
31310b25
MK
3714{
3715 struct zserv *client = NULL;
3716 struct stream *s = NULL;
3717 char buf[PREFIX_STRLEN];
3718
317f1fe0 3719 client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
31310b25
MK
3720 /* BGP may not be running. */
3721 if (!client)
3722 return 0;
3723
1002497a 3724 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
31310b25 3725
22bd3e94 3726 zclient_create_header(s, cmd, vrf_id);
31310b25
MK
3727 stream_put(s, p, sizeof(struct prefix));
3728
3729 /* Write packet size. */
3730 stream_putw_at(s, 0, stream_get_endp(s));
3731
3732 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 3733 zlog_debug("Send ip prefix %s %s on vrf %s",
31310b25
MK
3734 prefix2str(p, buf, sizeof(buf)),
3735 (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL",
3736 vrf_id_to_name(vrf_id));
3737
3738 if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD)
3739 client->prefixadd_cnt++;
3740 else
3741 client->prefixdel_cnt++;
3742
1002497a 3743 return zebra_server_send_message(client, s);
31310b25
MK
3744}
3745
a9a76262
MK
3746/* re-add remote rmac if needed */
3747static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
996c9314 3748 struct ethaddr *rmac)
a9a76262
MK
3749{
3750 char buf[ETHER_ADDR_STRLEN];
3751 zebra_mac_t *zrmac = NULL;
3752
3753 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3754 if (!zrmac)
3755 return 0;
3756
3757 if (IS_ZEBRA_DEBUG_VXLAN)
3758 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
996c9314 3759 prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni);
a9a76262
MK
3760
3761 zl3vni_rmac_install(zl3vni, zrmac);
3762 return 0;
3763}
3764
b7cfce93
MK
3765/* Public functions */
3766
c48d9f5f
MK
3767int is_l3vni_for_prefix_routes_only(vni_t vni)
3768{
3769 zebra_l3vni_t *zl3vni = NULL;
3770
3771 zl3vni = zl3vni_lookup(vni);
3772 if (!zl3vni)
3773 return 0;
3774
3775 return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
3776}
3777
2dbad57f 3778/* handle evpn route in vrf table */
996c9314
LB
3779void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac,
3780 struct ipaddr *vtep_ip,
3781 struct prefix *host_prefix)
2dbad57f 3782{
3783 zebra_l3vni_t *zl3vni = NULL;
3784
3785 zl3vni = zl3vni_from_vrf(vrf_id);
3786 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
3787 return;
3788
3789 /* add the next hop neighbor */
6134fd82 3790 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
2dbad57f 3791
3792 /* add the rmac */
6134fd82 3793 zl3vni_remote_rmac_add(zl3vni, rmac, vtep_ip, host_prefix);
2dbad57f 3794}
3795
3796/* handle evpn vrf route delete */
996c9314
LB
3797void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, struct ethaddr *rmac,
3798 struct ipaddr *vtep_ip,
3799 struct prefix *host_prefix)
2dbad57f 3800{
3801 zebra_l3vni_t *zl3vni = NULL;
3802
3803 zl3vni = zl3vni_from_vrf(vrf_id);
5e06422c 3804 if (!zl3vni)
2dbad57f 3805 return;
3806
3807 /* delete the next hop entry */
6134fd82 3808 zl3vni_remote_nh_del(zl3vni, vtep_ip, host_prefix);
2dbad57f 3809
3810 /* delete the rmac entry */
6134fd82 3811 zl3vni_remote_rmac_del(zl3vni, rmac, host_prefix);
2dbad57f 3812}
3813
996c9314 3814void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
316f4ca4 3815 struct ethaddr *rmac,
d7c0a89a 3816 uint8_t use_json)
9aa741ea
MK
3817{
3818 zebra_l3vni_t *zl3vni = NULL;
3819 zebra_mac_t *zrmac = NULL;
316f4ca4 3820 json_object *json = NULL;
9aa741ea 3821
316f4ca4
MK
3822 if (!is_evpn_enabled()) {
3823 if (use_json)
3824 vty_out(vty, "{}\n");
9aa741ea 3825 return;
316f4ca4
MK
3826 }
3827
3828 if (use_json)
3829 json = json_object_new_object();
9aa741ea
MK
3830
3831 zl3vni = zl3vni_lookup(l3vni);
3832 if (!zl3vni) {
316f4ca4
MK
3833 if (use_json)
3834 vty_out(vty, "{}\n");
3835 else
996c9314 3836 vty_out(vty, "%% L3-VNI %u doesnt exist\n", l3vni);
9aa741ea
MK
3837 return;
3838 }
3839
3840 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3841 if (!zrmac) {
316f4ca4
MK
3842 if (use_json)
3843 vty_out(vty, "{}\n");
3844 else
3845 vty_out(vty,
3846 "%% Requested RMAC doesnt exist in L3-VNI %u",
3847 l3vni);
9aa741ea
MK
3848 return;
3849 }
3850
316f4ca4
MK
3851 zl3vni_print_rmac(zrmac, vty, json);
3852
3853 if (use_json) {
3854 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3855 json, JSON_C_TO_STRING_PRETTY));
3856 json_object_free(json);
3857 }
9aa741ea 3858}
2dbad57f 3859
996c9314 3860void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni,
d7c0a89a 3861 uint8_t use_json)
b7cfce93
MK
3862{
3863 zebra_l3vni_t *zl3vni;
d7c0a89a 3864 uint32_t num_rmacs;
b7cfce93
MK
3865 struct rmac_walk_ctx wctx;
3866 json_object *json = NULL;
b7cfce93
MK
3867
3868 if (!is_evpn_enabled())
3869 return;
3870
3871 zl3vni = zl3vni_lookup(l3vni);
3872 if (!zl3vni) {
3873 if (use_json)
3874 vty_out(vty, "{}\n");
3875 else
3876 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
3877 return;
3878 }
3879 num_rmacs = hashcount(zl3vni->rmac_table);
3880 if (!num_rmacs)
3881 return;
3882
75223c9e 3883 if (use_json)
b7cfce93 3884 json = json_object_new_object();
b7cfce93
MK
3885
3886 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
3887 wctx.vty = vty;
75223c9e 3888 wctx.json = json;
b7cfce93 3889 if (!use_json) {
996c9314 3890 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
b7cfce93 3891 num_rmacs);
4cce389e 3892 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
b7cfce93
MK
3893 } else
3894 json_object_int_add(json, "numRmacs", num_rmacs);
3895
3896 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
3897
3898 if (use_json) {
b7cfce93
MK
3899 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3900 json, JSON_C_TO_STRING_PRETTY));
3901 json_object_free(json);
3902 }
3903}
3904
d7c0a89a 3905void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, uint8_t use_json)
b7cfce93
MK
3906{
3907 struct zebra_ns *zns = NULL;
b7cfce93 3908 json_object *json = NULL;
c0b4eaa4 3909 void *args[2];
b7cfce93
MK
3910
3911 if (!is_evpn_enabled()) {
3912 if (use_json)
3913 vty_out(vty, "{}\n");
3914 return;
3915 }
3916
3917 zns = zebra_ns_lookup(NS_DEFAULT);
c0b4eaa4
MK
3918 if (!zns) {
3919 if (use_json)
3920 vty_out(vty, "{}\n");
b7cfce93 3921 return;
c0b4eaa4 3922 }
b7cfce93
MK
3923
3924 if (use_json)
3925 json = json_object_new_object();
3926
c0b4eaa4
MK
3927 args[0] = vty;
3928 args[1] = json;
3929 hash_iterate(zns->l3vni_table,
3930 (void (*)(struct hash_backet *,
3931 void *))zl3vni_print_rmac_hash_all_vni,
3932 args);
b7cfce93
MK
3933
3934 if (use_json) {
3935 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3936 json, JSON_C_TO_STRING_PRETTY));
3937 json_object_free(json);
3938 }
3939}
3940
996c9314 3941void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
d7c0a89a 3942 struct ipaddr *ip, uint8_t use_json)
9aa741ea
MK
3943{
3944 zebra_l3vni_t *zl3vni = NULL;
3945 zebra_neigh_t *n = NULL;
c0e519d3 3946 json_object *json = NULL;
9aa741ea 3947
c0e519d3
MK
3948 if (!is_evpn_enabled()) {
3949 if (use_json)
3950 vty_out(vty, "{}\n");
9aa741ea 3951 return;
c0e519d3
MK
3952 }
3953
3954 if (use_json)
3955 json = json_object_new_object();
9aa741ea
MK
3956
3957 zl3vni = zl3vni_lookup(l3vni);
3958 if (!zl3vni) {
c0e519d3
MK
3959 if (use_json)
3960 vty_out(vty, "{}\n");
3961 else
3962 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
9aa741ea
MK
3963 return;
3964 }
3965
3966 n = zl3vni_nh_lookup(zl3vni, ip);
3967 if (!n) {
c0e519d3
MK
3968 if (use_json)
3969 vty_out(vty, "{}\n");
3970 else
3971 vty_out(vty,
3972 "%% Requested next-hop not present for L3-VNI %u",
3973 l3vni);
9aa741ea
MK
3974 return;
3975 }
3976
c0e519d3
MK
3977 zl3vni_print_nh(n, vty, json);
3978
3979 if (use_json) {
3980 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3981 json, JSON_C_TO_STRING_PRETTY));
3982 json_object_free(json);
3983 }
9aa741ea
MK
3984}
3985
d7c0a89a 3986void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, uint8_t use_json)
b7cfce93 3987{
d7c0a89a 3988 uint32_t num_nh;
2dbad57f 3989 struct nh_walk_ctx wctx;
b7cfce93 3990 json_object *json = NULL;
b7cfce93
MK
3991 zebra_l3vni_t *zl3vni = NULL;
3992
3993 if (!is_evpn_enabled())
3994 return;
3995
3996 zl3vni = zl3vni_lookup(l3vni);
3997 if (!zl3vni) {
3998 if (use_json)
3999 vty_out(vty, "{}\n");
4000 else
4001 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
4002 return;
4003 }
4004
4005 num_nh = hashcount(zl3vni->nh_table);
4006 if (!num_nh)
4007 return;
4008
9187f600 4009 if (use_json)
b7cfce93 4010 json = json_object_new_object();
b7cfce93 4011
2dbad57f 4012 wctx.vty = vty;
9187f600 4013 wctx.json = json;
b7cfce93 4014 if (!use_json) {
996c9314 4015 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
b7cfce93 4016 num_nh);
4cce389e 4017 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
b7cfce93 4018 } else
4cce389e 4019 json_object_int_add(json, "numNextHops", num_nh);
b7cfce93
MK
4020
4021 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
4022
4023 if (use_json) {
b7cfce93
MK
4024 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4025 json, JSON_C_TO_STRING_PRETTY));
4026 json_object_free(json);
4027 }
4028}
4029
d7c0a89a 4030void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, uint8_t use_json)
b7cfce93 4031{
2dbad57f 4032 struct zebra_ns *zns = NULL;
2dbad57f 4033 json_object *json = NULL;
32798965 4034 void *args[2];
2dbad57f 4035
4036 if (!is_evpn_enabled()) {
4037 if (use_json)
4038 vty_out(vty, "{}\n");
4039 return;
4040 }
4041
4042 zns = zebra_ns_lookup(NS_DEFAULT);
4043 if (!zns)
4044 return;
4045
4046 if (use_json)
4047 json = json_object_new_object();
4048
32798965
MK
4049 args[0] = vty;
4050 args[1] = json;
4051 hash_iterate(zns->l3vni_table,
4052 (void (*)(struct hash_backet *,
4053 void *))zl3vni_print_nh_hash_all_vni,
4054 args);
2dbad57f 4055
4056 if (use_json) {
4057 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4058 json, JSON_C_TO_STRING_PRETTY));
4059 json_object_free(json);
4060 }
b7cfce93
MK
4061 return;
4062}
4063
4064/*
4065 * Display L3 VNI information (VTY command handler).
4066 */
d7c0a89a 4067void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, uint8_t use_json)
b7cfce93
MK
4068{
4069 void *args[2];
4070 json_object *json = NULL;
4071 zebra_l3vni_t *zl3vni = NULL;
4072
b2ee5a13
MK
4073 if (!is_evpn_enabled()) {
4074 if (use_json)
4075 vty_out(vty, "{}\n");
b7cfce93 4076 return;
b2ee5a13 4077 }
b7cfce93
MK
4078
4079 zl3vni = zl3vni_lookup(vni);
4080 if (!zl3vni) {
4081 if (use_json)
4082 vty_out(vty, "{}\n");
4083 else
4084 vty_out(vty, "%% VNI %u does not exist\n", vni);
4085 return;
4086 }
4087
4088 if (use_json)
4089 json = json_object_new_object();
4090
b2ee5a13
MK
4091 args[0] = vty;
4092 args[1] = json;
b7cfce93
MK
4093 zl3vni_print(zl3vni, (void *)args);
4094
4095 if (use_json) {
4096 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4097 json, JSON_C_TO_STRING_PRETTY));
4098 json_object_free(json);
4099 }
4100}
4101
4cce389e
MK
4102void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
4103 json_object *json_vrfs)
b7cfce93 4104{
4cce389e
MK
4105 char buf[ETHER_ADDR_STRLEN];
4106 zebra_l3vni_t *zl3vni = NULL;
b7cfce93 4107
4cce389e
MK
4108 zl3vni = zl3vni_lookup(zvrf->l3vni);
4109 if (!zl3vni)
b7cfce93 4110 return;
b7cfce93 4111
4cce389e
MK
4112 if (!json_vrfs) {
4113 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
996c9314 4114 zvrf_name(zvrf), zl3vni->vni,
4cce389e 4115 zl3vni_vxlan_if_name(zl3vni),
996c9314 4116 zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
4cce389e 4117 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
b7cfce93 4118 } else {
4cce389e
MK
4119 json_object *json_vrf = NULL;
4120 json_vrf = json_object_new_object();
996c9314 4121 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
4cce389e
MK
4122 json_object_int_add(json_vrf, "vni", zl3vni->vni);
4123 json_object_string_add(json_vrf, "vxlanIntf",
4124 zl3vni_vxlan_if_name(zl3vni));
4125 json_object_string_add(json_vrf, "sviIntf",
4126 zl3vni_svi_if_name(zl3vni));
4127 json_object_string_add(json_vrf, "state",
4128 zl3vni_state2str(zl3vni));
996c9314
LB
4129 json_object_string_add(
4130 json_vrf, "routerMac",
4131 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 4132 json_object_array_add(json_vrfs, json_vrf);
b7cfce93
MK
4133 }
4134}
4135
4136/*
4137 * Display Neighbors for a VNI (VTY command handler).
4138 */
4139void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
d7c0a89a 4140 vni_t vni, uint8_t use_json)
b7cfce93
MK
4141{
4142 zebra_vni_t *zvni;
d7c0a89a 4143 uint32_t num_neigh;
b7cfce93
MK
4144 struct neigh_walk_ctx wctx;
4145 json_object *json = NULL;
4146
4147 if (!is_evpn_enabled())
4148 return;
4149 zvni = zvni_lookup(vni);
4150 if (!zvni) {
4151 if (use_json)
4152 vty_out(vty, "{}\n");
4153 else
4154 vty_out(vty, "%% VNI %u does not exist\n", vni);
4155 return;
4156 }
4157 num_neigh = hashcount(zvni->neigh_table);
4158 if (!num_neigh)
4159 return;
4160
4161 if (use_json)
4162 json = json_object_new_object();
4163
4164 /* Since we have IPv6 addresses to deal with which can vary widely in
4165 * size, we try to be a bit more elegant in display by first computing
4166 * the maximum width.
4167 */
4168 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4169 wctx.zvni = zvni;
4170 wctx.vty = vty;
4171 wctx.addr_width = 15;
4172 wctx.json = json;
4173 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
4174
4175 if (!use_json) {
4176 vty_out(vty,
4177 "Number of ARPs (local and remote) known for this VNI: %u\n",
4178 num_neigh);
4179 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
4180 "Type", "MAC", "Remote VTEP");
4181 } else
4182 json_object_int_add(json, "numArpNd", num_neigh);
4183
4184 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
4185 if (use_json) {
4186 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4187 json, JSON_C_TO_STRING_PRETTY));
4188 json_object_free(json);
4189 }
4190}
4191
4192/*
4193 * Display neighbors across all VNIs (VTY command handler).
4194 */
4195void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
d7c0a89a 4196 uint8_t use_json)
b7cfce93
MK
4197{
4198 json_object *json = NULL;
4199 void *args[2];
4200
4201 if (!is_evpn_enabled())
4202 return;
4203
4204 if (use_json)
4205 json = json_object_new_object();
4206
4207 args[0] = vty;
4208 args[1] = json;
4209 hash_iterate(zvrf->vni_table,
4210 (void (*)(struct hash_backet *,
4211 void *))zvni_print_neigh_hash_all_vni,
4212 args);
4213 if (use_json) {
4214 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4215 json, JSON_C_TO_STRING_PRETTY));
4216 json_object_free(json);
4217 }
4218}
4219
4220/*
4221 * Display specific neighbor for a VNI, if present (VTY command handler).
4222 */
4223void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
4224 struct zebra_vrf *zvrf, vni_t vni,
d7c0a89a 4225 struct ipaddr *ip, uint8_t use_json)
b7cfce93
MK
4226{
4227 zebra_vni_t *zvni;
4228 zebra_neigh_t *n;
4229 json_object *json = NULL;
4230
4231 if (!is_evpn_enabled())
4232 return;
4233 zvni = zvni_lookup(vni);
4234 if (!zvni) {
4235 if (use_json)
cd233079
CS
4236 vty_out(vty, "{}\n");
4237 else
4238 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4239 return;
4240 }
4241 n = zvni_neigh_lookup(zvni, ip);
4242 if (!n) {
cd233079
CS
4243 if (!use_json)
4244 vty_out(vty,
4245 "%% Requested neighbor does not exist in VNI %u\n",
4246 vni);
d62a17ae 4247 return;
4248 }
cd233079
CS
4249 if (use_json)
4250 json = json_object_new_object();
4251
4252 zvni_print_neigh(n, vty, json);
cec2e17d 4253
cd233079
CS
4254 if (use_json) {
4255 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4256 json, JSON_C_TO_STRING_PRETTY));
4257 json_object_free(json);
4258 }
cec2e17d 4259}
4260
4261/*
4262 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4263 * By definition, these are remote neighbors.
4264 */
d62a17ae 4265void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 4266 vni_t vni, struct in_addr vtep_ip,
d7c0a89a 4267 uint8_t use_json)
cec2e17d 4268{
d62a17ae 4269 zebra_vni_t *zvni;
d7c0a89a 4270 uint32_t num_neigh;
d62a17ae 4271 struct neigh_walk_ctx wctx;
cd233079 4272 json_object *json = NULL;
cec2e17d 4273
2853fed6 4274 if (!is_evpn_enabled())
d62a17ae 4275 return;
2853fed6 4276 zvni = zvni_lookup(vni);
d62a17ae 4277 if (!zvni) {
cd233079
CS
4278 if (use_json)
4279 vty_out(vty, "{}\n");
4280 else
4281 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4282 return;
4283 }
4284 num_neigh = hashcount(zvni->neigh_table);
4285 if (!num_neigh)
4286 return;
cec2e17d 4287
d62a17ae 4288 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4289 wctx.zvni = zvni;
4290 wctx.vty = vty;
4291 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
4292 wctx.r_vtep_ip = vtep_ip;
cd233079 4293 wctx.json = json;
d62a17ae 4294 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
4295
4296 if (use_json) {
4297 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4298 json, JSON_C_TO_STRING_PRETTY));
4299 json_object_free(json);
4300 }
cec2e17d 4301}
4302
4303/*
4304 * Display MACs for a VNI (VTY command handler).
4305 */
d62a17ae 4306void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
d7c0a89a 4307 vni_t vni, uint8_t use_json)
cec2e17d 4308{
d62a17ae 4309 zebra_vni_t *zvni;
d7c0a89a 4310 uint32_t num_macs;
d62a17ae 4311 struct mac_walk_ctx wctx;
cd233079
CS
4312 json_object *json = NULL;
4313 json_object *json_mac = NULL;
cec2e17d 4314
2853fed6 4315 if (!is_evpn_enabled())
d62a17ae 4316 return;
2853fed6 4317 zvni = zvni_lookup(vni);
d62a17ae 4318 if (!zvni) {
cd233079
CS
4319 if (use_json)
4320 vty_out(vty, "{}\n");
4321 else
4322 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4323 return;
4324 }
790f8dc5 4325 num_macs = num_valid_macs(zvni);
d62a17ae 4326 if (!num_macs)
4327 return;
cec2e17d 4328
cd233079
CS
4329 if (use_json) {
4330 json = json_object_new_object();
4331 json_mac = json_object_new_object();
4332 }
4333
d62a17ae 4334 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4335 wctx.zvni = zvni;
4336 wctx.vty = vty;
cd233079 4337 wctx.json = json_mac;
cec2e17d 4338
cd233079
CS
4339 if (!use_json) {
4340 vty_out(vty,
4341 "Number of MACs (local and remote) known for this VNI: %u\n",
4342 num_macs);
4343 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4344 "Intf/Remote VTEP", "VLAN");
4345 } else
4346 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 4347
d62a17ae 4348 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
4349
4350 if (use_json) {
4351 json_object_object_add(json, "macs", json_mac);
4352 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4353 json, JSON_C_TO_STRING_PRETTY));
4354 json_object_free(json);
4355 }
cec2e17d 4356}
4357
4358/*
4359 * Display MACs for all VNIs (VTY command handler).
4360 */
cd233079 4361void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
d7c0a89a 4362 uint8_t use_json)
cec2e17d 4363{
d62a17ae 4364 struct mac_walk_ctx wctx;
cd233079 4365 json_object *json = NULL;
cec2e17d 4366
2853fed6 4367 if (!is_evpn_enabled()) {
cd233079
CS
4368 if (use_json)
4369 vty_out(vty, "{}\n");
d62a17ae 4370 return;
cd233079
CS
4371 }
4372 if (use_json)
4373 json = json_object_new_object();
4374
d62a17ae 4375 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4376 wctx.vty = vty;
cd233079 4377 wctx.json = json;
d62a17ae 4378 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
4379
4380 if (use_json) {
4381 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4382 json, JSON_C_TO_STRING_PRETTY));
4383 json_object_free(json);
4384 }
cec2e17d 4385}
4386
4387/*
4388 * Display MACs for all VNIs (VTY command handler).
4389 */
d62a17ae 4390void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
4391 struct zebra_vrf *zvrf,
cd233079 4392 struct in_addr vtep_ip,
d7c0a89a 4393 uint8_t use_json)
cec2e17d 4394{
d62a17ae 4395 struct mac_walk_ctx wctx;
cd233079 4396 json_object *json = NULL;
cec2e17d 4397
2853fed6 4398 if (!is_evpn_enabled())
d62a17ae 4399 return;
cd233079
CS
4400
4401 if (use_json)
4402 json = json_object_new_object();
4403
d62a17ae 4404 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4405 wctx.vty = vty;
4406 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4407 wctx.r_vtep_ip = vtep_ip;
cd233079 4408 wctx.json = json;
d62a17ae 4409 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
4410
4411 if (use_json) {
4412 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4413 json, JSON_C_TO_STRING_PRETTY));
4414 json_object_free(json);
4415 }
cec2e17d 4416}
4417
4418/*
4419 * Display specific MAC for a VNI, if present (VTY command handler).
4420 */
d62a17ae 4421void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
4422 vni_t vni, struct ethaddr *macaddr)
cec2e17d 4423{
d62a17ae 4424 zebra_vni_t *zvni;
4425 zebra_mac_t *mac;
cec2e17d 4426
2853fed6 4427 if (!is_evpn_enabled())
d62a17ae 4428 return;
2853fed6 4429 zvni = zvni_lookup(vni);
d62a17ae 4430 if (!zvni) {
4431 vty_out(vty, "%% VNI %u does not exist\n", vni);
4432 return;
4433 }
4434 mac = zvni_mac_lookup(zvni, macaddr);
4435 if (!mac) {
4436 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
4437 vni);
4438 return;
4439 }
cec2e17d 4440
d62a17ae 4441 zvni_print_mac(mac, vty);
cec2e17d 4442}
4443
4444/*
4445 * Display MACs for a VNI from specific VTEP (VTY command handler).
4446 */
d62a17ae 4447void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 4448 vni_t vni, struct in_addr vtep_ip,
d7c0a89a 4449 uint8_t use_json)
cec2e17d 4450{
d62a17ae 4451 zebra_vni_t *zvni;
d7c0a89a 4452 uint32_t num_macs;
d62a17ae 4453 struct mac_walk_ctx wctx;
cd233079
CS
4454 json_object *json = NULL;
4455 json_object *json_mac = NULL;
cec2e17d 4456
2853fed6 4457 if (!is_evpn_enabled())
d62a17ae 4458 return;
2853fed6 4459 zvni = zvni_lookup(vni);
d62a17ae 4460 if (!zvni) {
cd233079
CS
4461 if (use_json)
4462 vty_out(vty, "{}\n");
4463 else
4464 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 4465 return;
4466 }
790f8dc5 4467 num_macs = num_valid_macs(zvni);
d62a17ae 4468 if (!num_macs)
4469 return;
cd233079
CS
4470
4471 if (use_json) {
4472 json = json_object_new_object();
4473 json_mac = json_object_new_object();
4474 }
4475
d62a17ae 4476 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4477 wctx.zvni = zvni;
4478 wctx.vty = vty;
4479 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4480 wctx.r_vtep_ip = vtep_ip;
cd233079 4481 wctx.json = json_mac;
d62a17ae 4482 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
4483
4484 if (use_json) {
4485 json_object_int_add(json, "numMacs", wctx.count);
4486 if (wctx.count)
4487 json_object_object_add(json, "macs", json_mac);
4488 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4489 json, JSON_C_TO_STRING_PRETTY));
4490 json_object_free(json);
4491 }
cec2e17d 4492}
4493
4494
4495/*
4496 * Display VNI information (VTY command handler).
4497 */
cd233079 4498void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
d7c0a89a 4499 uint8_t use_json)
cec2e17d 4500{
cd233079
CS
4501 json_object *json = NULL;
4502 void *args[2];
1f2129ec 4503 zebra_l3vni_t *zl3vni = NULL;
4504 zebra_vni_t *zvni = NULL;
cec2e17d 4505
2853fed6 4506 if (!is_evpn_enabled())
d62a17ae 4507 return;
4cce389e 4508
cd233079
CS
4509 if (use_json)
4510 json = json_object_new_object();
4511 args[0] = vty;
4512 args[1] = json;
4cce389e 4513
1f2129ec 4514 zl3vni = zl3vni_lookup(vni);
4515 if (zl3vni) {
4cce389e
MK
4516 zl3vni_print(zl3vni, (void *)args);
4517 } else {
4cce389e
MK
4518 zvni = zvni_lookup(vni);
4519 if (!zvni) {
4520 if (use_json)
4521 vty_out(vty, "{}\n");
4522 else
4523 vty_out(vty, "%% VNI %u does not exist\n", vni);
4524 return;
4525 }
4526
4527 zvni_print(zvni, (void *)args);
4528 }
4529
cd233079
CS
4530 if (use_json) {
4531 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4532 json, JSON_C_TO_STRING_PRETTY));
4533 json_object_free(json);
4534 }
cec2e17d 4535}
4536
4cce389e 4537/* Display all global details for EVPN */
d7c0a89a 4538void zebra_vxlan_print_evpn(struct vty *vty, uint8_t uj)
cec2e17d 4539{
4cce389e
MK
4540 int num_l2vnis = 0;
4541 int num_l3vnis = 0;
d4454626 4542 int num_vnis = 0;
cd233079 4543 json_object *json = NULL;
4cce389e
MK
4544 struct zebra_ns *zns = NULL;
4545 struct zebra_vrf *zvrf = NULL;
cec2e17d 4546
2853fed6 4547 if (!is_evpn_enabled())
d62a17ae 4548 return;
4cce389e
MK
4549
4550 zns = zebra_ns_lookup(NS_DEFAULT);
4551 if (!zns)
d62a17ae 4552 return;
4cce389e
MK
4553
4554 zvrf = vrf_info_lookup(VRF_DEFAULT);
4555 if (!zvrf)
4556 return;
4557
4558 num_l3vnis = hashcount(zns->l3vni_table);
4559 num_l2vnis = hashcount(zvrf->vni_table);
d4454626 4560 num_vnis = num_l2vnis + num_l3vnis;
4cce389e
MK
4561
4562 if (uj) {
cd233079 4563 json = json_object_new_object();
ddd16ed5
MK
4564 json_object_string_add(json, "advertiseGatewayMacip",
4565 zvrf->advertise_gw_macip ? "Yes" : "No");
d4454626 4566 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
4567 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4568 json_object_int_add(json, "numL3Vnis", num_l3vnis);
cd233079 4569 } else {
4cce389e
MK
4570 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
4571 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
ddd16ed5
MK
4572 vty_out(vty, "Advertise gateway mac-ip: %s\n",
4573 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079 4574 }
4cce389e
MK
4575
4576 if (uj) {
4577 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4578 json, JSON_C_TO_STRING_PRETTY));
4579 json_object_free(json);
4580 }
4581}
4582
4583/*
4584 * Display VNI hash table (VTY command handler).
4585 */
4586void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
d7c0a89a 4587 uint8_t use_json)
4cce389e
MK
4588{
4589 json_object *json = NULL;
4590 struct zebra_ns *zns = NULL;
4591 void *args[2];
4592
4593 if (!is_evpn_enabled())
4594 return;
4595
4596 zns = zebra_ns_lookup(NS_DEFAULT);
4597 if (!zns)
4598 return;
4599
4600
4601 if (use_json)
4602 json = json_object_new_object();
4603 else
996c9314
LB
4604 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4605 "Type", "VxLAN IF", "# MACs", "# ARPs",
4606 "# Remote VTEPs", "Tenant VRF");
4cce389e 4607
cd233079
CS
4608 args[0] = vty;
4609 args[1] = json;
4610
4cce389e 4611 /* Display all L2-VNIs */
cd233079
CS
4612 hash_iterate(zvrf->vni_table,
4613 (void (*)(struct hash_backet *, void *))zvni_print_hash,
4614 args);
4615
4cce389e
MK
4616 /* Display all L3-VNIs */
4617 hash_iterate(zns->l3vni_table,
4618 (void (*)(struct hash_backet *, void *))zl3vni_print_hash,
4619 args);
4620
cd233079
CS
4621 if (use_json) {
4622 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4623 json, JSON_C_TO_STRING_PRETTY));
4624 json_object_free(json);
4625 }
cec2e17d 4626}
4627
2232a77c 4628/*
4629 * Handle neighbor delete (on a VLAN device / L3 interface) from the
4630 * kernel. This may result in either the neighbor getting deleted from
4631 * our database or being re-added to the kernel (if it is a valid
4632 * remote neighbor).
4633 */
d62a17ae 4634int zebra_vxlan_local_neigh_del(struct interface *ifp,
4635 struct interface *link_if, struct ipaddr *ip)
4636{
d62a17ae 4637 char buf[INET6_ADDRSTRLEN];
b6938a74 4638 char buf2[ETHER_ADDR_STRLEN];
b7cfce93
MK
4639 zebra_neigh_t *n = NULL;
4640 zebra_vni_t *zvni = NULL;
4641 zebra_mac_t *zmac = NULL;
8c9b80b9 4642 zebra_l3vni_t *zl3vni = NULL;
b7cfce93 4643
8c9b80b9 4644 /* check if this is a remote neigh entry corresponding to remote
523cafc4 4645 * next-hop
4646 */
8c9b80b9
MK
4647 zl3vni = zl3vni_from_svi(ifp, link_if);
4648 if (zl3vni)
4649 return zl3vni_local_nh_del(zl3vni, ip);
d62a17ae 4650
4651 /* We are only interested in neighbors on an SVI that resides on top
4652 * of a VxLAN bridge.
4653 */
b7cfce93 4654 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 4655 if (!zvni)
4656 return 0;
8c9b80b9 4657
d62a17ae 4658 if (!zvni->vxlan_if) {
4659 zlog_err(
4660 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4661 zvni->vni, zvni);
4662 return -1;
4663 }
4664
4665 if (IS_ZEBRA_DEBUG_VXLAN)
8c9b80b9 4666 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
996c9314
LB
4667 ipaddr2str(ip, buf, sizeof(buf)), ifp->name,
4668 ifp->ifindex, zvni->vni);
d62a17ae 4669
4670 /* If entry doesn't exist, nothing to do. */
4671 n = zvni_neigh_lookup(zvni, ip);
4672 if (!n)
4673 return 0;
4674
b6938a74
MK
4675 zmac = zvni_mac_lookup(zvni, &n->emac);
4676 if (!zmac) {
4677 if (IS_ZEBRA_DEBUG_VXLAN)
4678 zlog_err(
2853fed6 4679 "Trying to del a neigh %s without a mac %s on VNI %u",
4680 ipaddr2str(ip, buf, sizeof(buf)),
b6938a74
MK
4681 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
4682 zvni->vni);
4683
4684 return 0;
4685 }
4686
d62a17ae 4687 /* If it is a remote entry, the kernel has aged this out or someone has
4688 * deleted it, it needs to be re-installed as Quagga is the owner.
4689 */
4690 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
4691 zvni_neigh_install(zvni, n);
4692 return 0;
4693 }
4694
d62a17ae 4695 /* Remove neighbor from BGP. */
b6938a74 4696 if (IS_ZEBRA_NEIGH_ACTIVE(n))
996c9314 4697 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0);
d62a17ae 4698
4699 /* Delete this neighbor entry. */
4700 zvni_neigh_del(zvni, n);
4701
b6938a74
MK
4702 /* see if the AUTO mac needs to be deleted */
4703 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
f51d8a27 4704 && !listcount(zmac->neigh_list))
b6938a74
MK
4705 zvni_mac_del(zvni, zmac);
4706
d62a17ae 4707 return 0;
2232a77c 4708}
4709
4710/*
859b32c0
MK
4711 * Handle neighbor add or update (on a VLAN device / L3 interface)
4712 * from the kernel.
2232a77c 4713 */
d62a17ae 4714int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
4715 struct interface *link_if,
4716 struct ipaddr *ip,
d7c0a89a
QY
4717 struct ethaddr *macaddr, uint16_t state,
4718 uint8_t ext_learned)
d62a17ae 4719{
d62a17ae 4720 char buf[ETHER_ADDR_STRLEN];
4721 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
4722 zebra_vni_t *zvni = NULL;
4723 zebra_neigh_t *n = NULL;
4724 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
3bcbba10 4725 zebra_l3vni_t *zl3vni = NULL;
4726
4727 /* check if this is a remote neigh entry corresponding to remote
4728 * next-hop
4729 */
4730 zl3vni = zl3vni_from_svi(ifp, link_if);
4731 if (zl3vni)
4732 return zl3vni_local_nh_add_update(zl3vni, ip, state);
b7cfce93 4733
d62a17ae 4734 /* We are only interested in neighbors on an SVI that resides on top
4735 * of a VxLAN bridge.
4736 */
b7cfce93 4737 zvni = zvni_from_svi(ifp, link_if);
d62a17ae 4738 if (!zvni)
4739 return 0;
4740
d62a17ae 4741 if (IS_ZEBRA_DEBUG_VXLAN)
4742 zlog_debug(
8c9b80b9 4743 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
2853fed6 4744 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 4745 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
4746 ifp->ifindex, state, ext_learned ? "ext-learned " : "",
8c9b80b9 4747 zvni->vni);
d62a17ae 4748
b6938a74
MK
4749 /* create a dummy MAC if the MAC is not already present */
4750 zmac = zvni_mac_lookup(zvni, macaddr);
4751 if (!zmac) {
4752 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4753 zlog_debug("AUTO MAC %s created for neigh %s on VNI %u",
4754 prefix_mac2str(macaddr, buf, sizeof(buf)),
4755 ipaddr2str(ip, buf2, sizeof(buf2)),
4756 zvni->vni);
b6938a74
MK
4757
4758 zmac = zvni_mac_add(zvni, macaddr);
4759 if (!zmac) {
2853fed6 4760 zlog_warn("Failed to add MAC %s VNI %u",
b6938a74
MK
4761 prefix_mac2str(macaddr, buf, sizeof(buf)),
4762 zvni->vni);
4763 return -1;
4764 }
4765
4766 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
d7c0a89a 4767 memset(&zmac->flags, 0, sizeof(uint32_t));
b6938a74
MK
4768 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
4769 }
4770
d62a17ae 4771 /* If same entry already exists, it might be a change or it might be a
4772 * move from remote to local.
4773 */
4774 n = zvni_neigh_lookup(zvni, ip);
4775 if (n) {
4776 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
996c9314 4777 if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN)
d62a17ae 4778 == 0) {
b682f6de 4779 /* Update any params and return - client doesn't
4780 * care about a purely local change.
4781 */
4782 n->ifindex = ifp->ifindex;
4783 return 0;
57f7feb6 4784 }
b682f6de 4785
57f7feb6
MK
4786 /* If the MAC has changed,
4787 * need to issue a delete first
4788 * as this means a different MACIP route.
4789 * Also, need to do some unlinking/relinking.
4790 */
2853fed6 4791 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
60466a63 4792 &n->emac, 0);
57f7feb6
MK
4793 old_zmac = zvni_mac_lookup(zvni, &n->emac);
4794 if (old_zmac) {
60466a63 4795 listnode_delete(old_zmac->neigh_list, n);
57f7feb6 4796 zvni_deref_ip2mac(zvni, old_zmac, 0);
b682f6de 4797 }
57f7feb6
MK
4798
4799 /* Set "local" forwarding info. */
4800 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4801 n->ifindex = ifp->ifindex;
4802 memcpy(&n->emac, macaddr, ETH_ALEN);
4803
4804 /* Link to new MAC */
4805 listnode_add_sort(zmac->neigh_list, n);
d62a17ae 4806 } else if (ext_learned)
4807 /* The neighbor is remote and that is the notification we got.
9d303b37 4808 */
d62a17ae 4809 {
859b32c0 4810 /* TODO: Evaluate if we need to do anything here. */
d62a17ae 4811 return 0;
4812 } else
4813 /* Neighbor has moved from remote to local. */
4814 {
4815 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
4816 n->r_vtep_ip.s_addr = 0;
b682f6de 4817 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4818 n->ifindex = ifp->ifindex;
d62a17ae 4819 }
4820 } else {
b6938a74 4821 n = zvni_neigh_add(zvni, ip, macaddr);
d62a17ae 4822 if (!n) {
4823 zlog_err(
2853fed6 4824 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
4825 ipaddr2str(ip, buf2, sizeof(buf2)),
d62a17ae 4826 prefix_mac2str(macaddr, buf, sizeof(buf)),
4827 ifp->name, ifp->ifindex, zvni->vni);
4828 return -1;
4829 }
b682f6de 4830 /* Set "local" forwarding info. */
4831 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
4832 n->ifindex = ifp->ifindex;
d62a17ae 4833 }
4834
b6938a74
MK
4835 /* Before we program this in BGP, we need to check if MAC is locally
4836 * learnt as well */
4837 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
4838 if (IS_ZEBRA_DEBUG_VXLAN)
4839 zlog_debug(
2853fed6 4840 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
4841 ipaddr2str(ip, buf2, sizeof(buf2)),
b6938a74
MK
4842 prefix_mac2str(macaddr, buf, sizeof(buf)),
4843 zvni->vni);
4844
4845 return 0;
4846 }
4847
b682f6de 4848 /* Inform BGP. */
4849 if (IS_ZEBRA_DEBUG_VXLAN)
8c9b80b9 4850 zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
2853fed6 4851 ipaddr2str(ip, buf2, sizeof(buf2)),
60466a63 4852 prefix_mac2str(macaddr, buf, sizeof(buf)),
8c9b80b9 4853 zvni->vni);
b682f6de 4854 ZEBRA_NEIGH_SET_ACTIVE(n);
b7cfce93 4855
ead40654 4856 return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
2232a77c 4857}
4858
b682f6de 4859
2232a77c 4860/*
4861 * Handle message from client to delete a remote MACIP for a VNI.
4862 */
89f4e507 4863void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
d62a17ae 4864{
4865 struct stream *s;
4866 vni_t vni;
4867 struct ethaddr macaddr;
4868 struct ipaddr ip;
4869 struct in_addr vtep_ip;
4870 zebra_vni_t *zvni;
4871 zebra_mac_t *mac;
4872 zebra_neigh_t *n;
d7c0a89a 4873 unsigned short l = 0, ipa_len;
d62a17ae 4874 char buf[ETHER_ADDR_STRLEN];
4875 char buf1[INET6_ADDRSTRLEN];
b5ebdc9b 4876 struct interface *ifp = NULL;
4877 struct zebra_if *zif = NULL;
d62a17ae 4878
b7cfce93 4879 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
4880 memset(&ip, 0, sizeof(struct ipaddr));
4881 memset(&vtep_ip, 0, sizeof(struct in_addr));
4882
1002497a 4883 s = msg;
d62a17ae 4884
89f4e507 4885 while (l < hdr->length) {
d62a17ae 4886 /* Obtain each remote MACIP and process. */
4887 /* Message contains VNI, followed by MAC followed by IP (if any)
4888 * followed by remote VTEP IP.
4889 */
4890 mac = NULL;
4891 n = NULL;
4892 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
4893 STREAM_GETL(s, vni);
4894 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
4895 STREAM_GETL(s, ipa_len);
d62a17ae 4896 if (ipa_len) {
4897 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
4898 : IPADDR_V6;
ec93aa12 4899 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 4900 }
ff8b7eb8 4901 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 4902 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4903 l += IPV4_MAX_BYTELEN;
4904
4905 if (IS_ZEBRA_DEBUG_VXLAN)
4906 zlog_debug(
23a06e11 4907 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
d62a17ae 4908 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4909 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
4910 inet_ntoa(vtep_ip),
4911 zebra_route_string(client->proto));
4912
4913 /* Locate VNI hash entry - expected to exist. */
2853fed6 4914 zvni = zvni_lookup(vni);
d62a17ae 4915 if (!zvni) {
4916 if (IS_ZEBRA_DEBUG_VXLAN)
4917 zlog_debug(
4918 "Failed to locate VNI hash upon remote MACIP DEL, "
2853fed6 4919 "VNI %u",
4920 vni);
d62a17ae 4921 continue;
4922 }
b5ebdc9b 4923 ifp = zvni->vxlan_if;
af026ae4 4924 if (!ifp) {
d62a17ae 4925 zlog_err(
4926 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
4927 vni, zvni);
4928 continue;
4929 }
b5ebdc9b 4930 zif = ifp->info;
4931
4932 /* If down or not mapped to a bridge, we're done. */
b682f6de 4933 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 4934 continue;
d62a17ae 4935
4936 /* The remote VTEP specified is normally expected to exist, but
4937 * it is
4938 * possible that the peer may delete the VTEP before deleting
4939 * any MACs
4940 * referring to the VTEP, in which case the handler (see
4941 * remote_vtep_del)
4942 * would have already deleted the MACs.
4943 */
4944 if (!zvni_vtep_find(zvni, &vtep_ip))
4945 continue;
4946
d62a17ae 4947 mac = zvni_mac_lookup(zvni, &macaddr);
4948 if (ipa_len)
4949 n = zvni_neigh_lookup(zvni, &ip);
4950
4951 if (n && !mac) {
996c9314
LB
4952 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
4953 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4954 ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
d62a17ae 4955 continue;
4956 }
4957
4958 /* If the remote mac or neighbor doesn't exist there is nothing
4959 * more
4960 * to do. Otherwise, uninstall the entry and then remove it.
4961 */
4962 if (!mac && !n)
4963 continue;
4964
ead40654 4965 /* Ignore the delete if this mac is a gateway mac-ip */
996c9314
LB
4966 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
4967 && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
4968 zlog_err(
4969 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
4970 zvrf_id(zvrf),
4971 prefix_mac2str(&macaddr, buf, sizeof(buf)),
4972 ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
ead40654
MK
4973 continue;
4974 }
4975
d62a17ae 4976 /* Uninstall remote neighbor or MAC. */
4977 if (n) {
4978 /* When the MAC changes for an IP, it is possible the
4979 * client may
4980 * update the new MAC before trying to delete the "old"
4981 * neighbor
4982 * (as these are two different MACIP routes). Do the
4983 * delete only
4984 * if the MAC matches.
4985 */
4986 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
996c9314 4987 && (memcmp(n->emac.octet, macaddr.octet, ETH_ALEN)
d62a17ae 4988 == 0)) {
4989 zvni_neigh_uninstall(zvni, n);
4990 zvni_neigh_del(zvni, n);
4991 zvni_deref_ip2mac(zvni, mac, 1);
4992 }
4993 } else {
4994 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
996c9314 4995 zvni_process_neigh_on_remote_mac_del(zvni, mac);
b6938a74 4996
0a97666d 4997 if (list_isempty(mac->neigh_list)) {
d62a17ae 4998 zvni_mac_uninstall(zvni, mac, 0);
4999 zvni_mac_del(zvni, mac);
5000 } else
5001 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5002 }
5003 }
5004 }
5005
ec93aa12 5006stream_failure:
8068a649 5007 return;
2232a77c 5008}
5009
5010/*
5011 * Handle message from client to add a remote MACIP for a VNI. This
5012 * could be just the add of a MAC address or the add of a neighbor
5013 * (IP+MAC).
5014 */
89f4e507 5015void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
d62a17ae 5016{
5017 struct stream *s;
5018 vni_t vni;
5019 struct ethaddr macaddr;
5020 struct ipaddr ip;
5021 struct in_addr vtep_ip;
5022 zebra_vni_t *zvni;
5023 zebra_vtep_t *zvtep;
5024 zebra_mac_t *mac, *old_mac;
5025 zebra_neigh_t *n;
d7c0a89a 5026 unsigned short l = 0, ipa_len;
d62a17ae 5027 int update_mac = 0, update_neigh = 0;
5028 char buf[ETHER_ADDR_STRLEN];
5029 char buf1[INET6_ADDRSTRLEN];
d7c0a89a
QY
5030 uint8_t sticky = 0;
5031 uint8_t flags = 0;
b5ebdc9b 5032 struct interface *ifp = NULL;
5033 struct zebra_if *zif = NULL;
d62a17ae 5034
b7cfce93 5035 memset(&macaddr, 0, sizeof(struct ethaddr));
b7cfce93
MK
5036 memset(&ip, 0, sizeof(struct ipaddr));
5037 memset(&vtep_ip, 0, sizeof(struct in_addr));
5038
ec93aa12 5039 if (!EVPN_ENABLED(zvrf)) {
996c9314
LB
5040 zlog_warn(
5041 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5042 __PRETTY_FUNCTION__);
8068a649 5043 return;
ec93aa12 5044 }
d62a17ae 5045
1002497a 5046 s = msg;
d62a17ae 5047
89f4e507 5048 while (l < hdr->length) {
d62a17ae 5049 /* Obtain each remote MACIP and process. */
5050 /* Message contains VNI, followed by MAC followed by IP (if any)
5051 * followed by remote VTEP IP.
5052 */
5053 update_mac = update_neigh = 0;
5054 mac = NULL;
5055 n = NULL;
5056 memset(&ip, 0, sizeof(ip));
ec93aa12
DS
5057 STREAM_GETL(s, vni);
5058 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
5059 STREAM_GETL(s, ipa_len);
d62a17ae 5060 if (ipa_len) {
5061 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
5062 : IPADDR_V6;
ec93aa12 5063 STREAM_GET(&ip.ip.addr, s, ipa_len);
d62a17ae 5064 }
ff8b7eb8 5065 l += 4 + ETH_ALEN + 4 + ipa_len;
ec93aa12 5066 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5067 l += IPV4_MAX_BYTELEN;
5068
ead40654
MK
5069 /* Get flags - sticky mac and/or gateway mac */
5070 flags = stream_getc(s);
5071 sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
d62a17ae 5072 l++;
5073
5074 if (IS_ZEBRA_DEBUG_VXLAN)
5075 zlog_debug(
ead40654 5076 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
d62a17ae 5077 prefix_mac2str(&macaddr, buf, sizeof(buf)),
5078 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
ead40654 5079 inet_ntoa(vtep_ip), flags,
d62a17ae 5080 zebra_route_string(client->proto));
5081
5082 /* Locate VNI hash entry - expected to exist. */
2853fed6 5083 zvni = zvni_lookup(vni);
d62a17ae 5084 if (!zvni) {
5085 zlog_err(
2853fed6 5086 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5087 vni);
d62a17ae 5088 continue;
5089 }
b5ebdc9b 5090 ifp = zvni->vxlan_if;
5091 if (!ifp) {
d62a17ae 5092 zlog_err(
5093 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5094 vni, zvni);
5095 continue;
5096 }
b5ebdc9b 5097 zif = ifp->info;
5098
5099 /* If down or not mapped to a bridge, we're done. */
b682f6de 5100 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 5101 continue;
5102
5103 /* The remote VTEP specified should normally exist, but it is
5104 * possible
5105 * that when peering comes up, peer may advertise MACIP routes
5106 * before
5107 * advertising type-3 routes.
5108 */
5109 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5110 if (!zvtep) {
5111 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5112 zlog_err(
2853fed6 5113 "Failed to add remote VTEP, VNI %u zvni %p",
5114 vni, zvni);
d62a17ae 5115 continue;
5116 }
5117
5118 zvni_vtep_install(zvni, &vtep_ip);
5119 }
5120
d62a17ae 5121 mac = zvni_mac_lookup(zvni, &macaddr);
ead40654
MK
5122
5123 /* Ignore the update if the mac is already present
5124 as a gateway mac */
996c9314
LB
5125 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)
5126 && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
ead40654 5127 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5128 zlog_debug(
5129 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5130 zvrf_id(zvrf),
5131 prefix_mac2str(&macaddr, buf,
5132 sizeof(buf)),
5133 ipaddr2str(&ip, buf1, sizeof(buf1)),
5134 vni);
ead40654
MK
5135 continue;
5136 }
5137
5138 /* check if the remote MAC is unknown or has a change.
5139 * If so, that needs to be updated first. Note that client could
5140 * install MAC and MACIP separately or just install the latter.
5141 */
d62a17ae 5142 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
5143 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
5144 != sticky
5145 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
5146 update_mac = 1;
5147
5148 if (update_mac) {
5149 if (!mac) {
5150 mac = zvni_mac_add(zvni, &macaddr);
5151 if (!mac) {
5152 zlog_warn(
2853fed6 5153 "Failed to add MAC %s VNI %u Remote VTEP %s",
d62a17ae 5154 prefix_mac2str(&macaddr, buf,
5155 sizeof(buf)),
5156 vni, inet_ntoa(vtep_ip));
8068a649 5157 return;
d62a17ae 5158 }
5159
5160 /* Is this MAC created for a MACIP? */
5161 if (ipa_len)
5162 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 5163 }
5164
5165 /* Set "auto" and "remote" forwarding info. */
5166 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5167 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
5168 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5169 mac->fwd_info.r_vtep_ip = vtep_ip;
5170
5171 if (sticky)
5172 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5173 else
5174 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5175
2853fed6 5176 zvni_process_neigh_on_remote_mac_add(zvni, mac);
b6938a74 5177
d62a17ae 5178 /* Install the entry. */
5179 zvni_mac_install(zvni, mac);
5180 }
5181
5182 /* If there is no IP, continue - after clearing AUTO flag of
5183 * MAC. */
5184 if (!ipa_len) {
5185 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5186 continue;
5187 }
5188
5189 /* Check if the remote neighbor itself is unknown or has a
5190 * change.
5191 * If so, create or update and then install the entry.
5192 */
5193 n = zvni_neigh_lookup(zvni, &ip);
5194 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5195 || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0)
5196 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip))
5197 update_neigh = 1;
5198
5199 if (update_neigh) {
5200 if (!n) {
b6938a74 5201 n = zvni_neigh_add(zvni, &ip, &macaddr);
d62a17ae 5202 if (!n) {
5203 zlog_warn(
2853fed6 5204 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
d62a17ae 5205 ipaddr2str(&ip, buf1,
5206 sizeof(buf1)),
5207 prefix_mac2str(&macaddr, buf,
5208 sizeof(buf)),
5209 vni, inet_ntoa(vtep_ip));
8068a649 5210 return;
d62a17ae 5211 }
5212
d62a17ae 5213 } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
5214 != 0) {
0a97666d
MK
5215 /* MAC change, update neigh list for old and new
5216 * mac */
d62a17ae 5217 old_mac = zvni_mac_lookup(zvni, &n->emac);
0a97666d
MK
5218 if (old_mac) {
5219 listnode_delete(old_mac->neigh_list, n);
d62a17ae 5220 zvni_deref_ip2mac(zvni, old_mac, 1);
0a97666d
MK
5221 }
5222 listnode_add_sort(mac->neigh_list, n);
b6938a74 5223 memcpy(&n->emac, &macaddr, ETH_ALEN);
d62a17ae 5224 }
5225
5226 /* Set "remote" forwarding info. */
5227 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
5228 /* TODO: Handle MAC change. */
d62a17ae 5229 n->r_vtep_ip = vtep_ip;
5230 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
5231
5232 /* Install the entry. */
5233 zvni_neigh_install(zvni, n);
5234 }
5235 }
5236
ec93aa12 5237stream_failure:
8068a649 5238 return;
13d60d35 5239}
5240
5241/*
2232a77c 5242 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5243 * us, this must involve a multihoming scenario. Treat this as implicit delete
5244 * of any prior local MAC.
13d60d35 5245 */
d62a17ae 5246int zebra_vxlan_check_del_local_mac(struct interface *ifp,
5247 struct interface *br_if,
5248 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5249{
d62a17ae 5250 struct zebra_if *zif;
d62a17ae 5251 struct zebra_l2info_vxlan *vxl;
5252 vni_t vni;
5253 zebra_vni_t *zvni;
5254 zebra_mac_t *mac;
5255 char buf[ETHER_ADDR_STRLEN];
13d60d35 5256
d62a17ae 5257 zif = ifp->info;
5258 assert(zif);
5259 vxl = &zif->l2info.vxl;
5260 vni = vxl->vni;
13d60d35 5261
2853fed6 5262 /* Check if EVPN is enabled. */
5263 if (!is_evpn_enabled())
d62a17ae 5264 return 0;
13d60d35 5265
d62a17ae 5266 /* Locate hash entry; it is expected to exist. */
2853fed6 5267 zvni = zvni_lookup(vni);
d62a17ae 5268 if (!zvni)
5269 return 0;
13d60d35 5270
d62a17ae 5271 /* If entry doesn't exist, nothing to do. */
5272 mac = zvni_mac_lookup(zvni, macaddr);
5273 if (!mac)
5274 return 0;
13d60d35 5275
d62a17ae 5276 /* Is it a local entry? */
5277 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5278 return 0;
13d60d35 5279
d62a17ae 5280 if (IS_ZEBRA_DEBUG_VXLAN)
5281 zlog_debug(
2853fed6 5282 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
996c9314
LB
5283 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5284 ifp->ifindex, vni);
13d60d35 5285
d62a17ae 5286 /* Remove MAC from BGP. */
ead40654 5287 zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
13d60d35 5288
b6938a74
MK
5289 /*
5290 * If there are no neigh associated with the mac delete the mac
5291 * else mark it as AUTO for forward reference
5292 */
5293 if (!listcount(mac->neigh_list)) {
5294 zvni_mac_del(zvni, mac);
5295 } else {
5296 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5297 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5298 }
13d60d35 5299
d62a17ae 5300 return 0;
13d60d35 5301}
5302
5303/*
2232a77c 5304 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5305 * This can happen because the remote MAC entries are also added as "dynamic",
5306 * so the kernel can ageout the entry.
13d60d35 5307 */
d62a17ae 5308int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
5309 struct interface *br_if,
5310 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5311{
a9a76262
MK
5312 struct zebra_if *zif = NULL;
5313 struct zebra_l2info_vxlan *vxl = NULL;
d62a17ae 5314 vni_t vni;
a9a76262
MK
5315 zebra_vni_t *zvni = NULL;
5316 zebra_l3vni_t *zl3vni = NULL;
5317 zebra_mac_t *mac = NULL;
d62a17ae 5318 char buf[ETHER_ADDR_STRLEN];
2232a77c 5319
d62a17ae 5320 zif = ifp->info;
5321 assert(zif);
5322 vxl = &zif->l2info.vxl;
5323 vni = vxl->vni;
2232a77c 5324
2853fed6 5325 /* Check if EVPN is enabled. */
5326 if (!is_evpn_enabled())
d62a17ae 5327 return 0;
2232a77c 5328
a9a76262
MK
5329 /* check if this is a remote RMAC and readd simillar to remote macs */
5330 zl3vni = zl3vni_lookup(vni);
5331 if (zl3vni)
5332 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
5333
d62a17ae 5334 /* Locate hash entry; it is expected to exist. */
2853fed6 5335 zvni = zvni_lookup(vni);
d62a17ae 5336 if (!zvni)
5337 return 0;
13d60d35 5338
d62a17ae 5339 /* If entry doesn't exist, nothing to do. */
5340 mac = zvni_mac_lookup(zvni, macaddr);
5341 if (!mac)
5342 return 0;
2232a77c 5343
d62a17ae 5344 /* Is it a remote entry? */
5345 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
5346 return 0;
2232a77c 5347
d62a17ae 5348 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5349 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
d62a17ae 5350 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5351 ifp->ifindex, vni);
13d60d35 5352
d62a17ae 5353 zvni_mac_install(zvni, mac);
5354 return 0;
13d60d35 5355}
5356
5357/*
2232a77c 5358 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 5359 */
d62a17ae 5360int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
5361 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 5362{
d62a17ae 5363 zebra_vni_t *zvni;
5364 zebra_mac_t *mac;
d62a17ae 5365 char buf[ETHER_ADDR_STRLEN];
13d60d35 5366
d62a17ae 5367 /* We are interested in MACs only on ports or (port, VLAN) that
5368 * map to a VNI.
5369 */
5370 zvni = zvni_map_vlan(ifp, br_if, vid);
5371 if (!zvni)
5372 return 0;
5373 if (!zvni->vxlan_if) {
5374 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5375 zvni->vni, zvni);
5376 return -1;
5377 }
13d60d35 5378
d62a17ae 5379 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5380 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
d62a17ae 5381 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5382 ifp->ifindex, vid, zvni->vni);
2232a77c 5383
d62a17ae 5384 /* If entry doesn't exist, nothing to do. */
5385 mac = zvni_mac_lookup(zvni, macaddr);
5386 if (!mac)
5387 return 0;
2232a77c 5388
d62a17ae 5389 /* Is it a local entry? */
5390 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5391 return 0;
2232a77c 5392
d62a17ae 5393 /* Remove MAC from BGP. */
ead40654 5394 zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
2232a77c 5395
b6938a74 5396 /* Update all the neigh entries associated with this mac */
2853fed6 5397 zvni_process_neigh_on_local_mac_del(zvni, mac);
b6938a74
MK
5398
5399 /*
5400 * If there are no neigh associated with the mac delete the mac
5401 * else mark it as AUTO for forward reference
5402 */
5403 if (!listcount(mac->neigh_list)) {
5404 zvni_mac_del(zvni, mac);
5405 } else {
5406 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5407 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5408 }
2232a77c 5409
d62a17ae 5410 return 0;
13d60d35 5411}
5412
5413/*
2232a77c 5414 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 5415 */
d62a17ae 5416int zebra_vxlan_local_mac_add_update(struct interface *ifp,
5417 struct interface *br_if,
5418 struct ethaddr *macaddr, vlanid_t vid,
d7c0a89a 5419 uint8_t sticky)
d62a17ae 5420{
5421 zebra_vni_t *zvni;
5422 zebra_mac_t *mac;
d62a17ae 5423 char buf[ETHER_ADDR_STRLEN];
5424 int add = 1;
d7c0a89a 5425 uint8_t mac_sticky;
d62a17ae 5426
5427 /* We are interested in MACs only on ports or (port, VLAN) that
5428 * map to a VNI.
5429 */
5430 zvni = zvni_map_vlan(ifp, br_if, vid);
5431 if (!zvni) {
5432 if (IS_ZEBRA_DEBUG_VXLAN)
5433 zlog_debug(
2853fed6 5434 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5435 sticky ? "sticky " : "",
d62a17ae 5436 prefix_mac2str(macaddr, buf, sizeof(buf)),
5437 ifp->name, ifp->ifindex, vid);
5438 return 0;
5439 }
5440
5441 if (!zvni->vxlan_if) {
5442 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5443 zvni->vni, zvni);
5444 return -1;
5445 }
5446
5447 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5448 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5449 sticky ? "sticky " : "",
5450 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5451 ifp->ifindex, vid, zvni->vni);
d62a17ae 5452
5453 /* If same entry already exists, nothing to do. */
5454 mac = zvni_mac_lookup(zvni, macaddr);
5455 if (mac) {
5456 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
5457 mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
5458 ? 1
5459 : 0;
5460
b6938a74 5461
b8ce75a5
MK
5462 /*
5463 * return if nothing has changed.
5464 * inform bgp if sticky flag has changed
5465 * update locally and do not inform bgp if local
5466 * parameters like interface has changed
5467 */
d62a17ae 5468 if (mac_sticky == sticky
5469 && mac->fwd_info.local.ifindex == ifp->ifindex
5470 && mac->fwd_info.local.vid == vid) {
5471 if (IS_ZEBRA_DEBUG_VXLAN)
5472 zlog_debug(
2853fed6 5473 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
d62a17ae 5474 "entry exists and has not changed ",
d62a17ae 5475 sticky ? "sticky " : "",
5476 prefix_mac2str(macaddr, buf,
5477 sizeof(buf)),
5478 ifp->name, ifp->ifindex, vid,
5479 zvni->vni);
5480 return 0;
b6938a74 5481 } else if (mac_sticky != sticky) {
b8ce75a5 5482 add = 1;
b6938a74 5483 } else {
b8ce75a5
MK
5484 add = 0; /* This is an update of local
5485 interface. */
b6938a74 5486 }
421bb26a
MK
5487 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5488 /*
5489 * If we have already learned the MAC as a remote sticky
5490 * MAC,
5491 * this is a operator error and we must log a warning
5492 */
8f4b98ee 5493 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
421bb26a
MK
5494 zlog_warn(
5495 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5496 prefix_mac2str(macaddr, buf,
5497 sizeof(buf)),
5498 inet_ntoa(mac->fwd_info.r_vtep_ip),
5499 zvni->vni);
8f4b98ee
MK
5500 return 0;
5501 }
d62a17ae 5502 }
5503 }
5504
d62a17ae 5505 if (!mac) {
5506 mac = zvni_mac_add(zvni, macaddr);
5507 if (!mac) {
2853fed6 5508 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
d62a17ae 5509 prefix_mac2str(macaddr, buf, sizeof(buf)),
5510 ifp->name, ifp->ifindex, vid);
5511 return -1;
5512 }
5513 }
5514
5515 /* Set "local" forwarding info. */
5516 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
b6938a74 5517 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 5518 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
b6938a74 5519 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
d62a17ae 5520 mac->fwd_info.local.ifindex = ifp->ifindex;
5521 mac->fwd_info.local.vid = vid;
5522
5523 if (sticky)
5524 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5525 else
5526 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5527
5528 /* Inform BGP if required. */
b6938a74 5529 if (add) {
2853fed6 5530 zvni_process_neigh_on_local_mac_add(zvni, mac);
5531 return zvni_mac_send_add_to_client(zvni->vni, macaddr,
ead40654 5532 mac->flags);
b6938a74 5533 }
d62a17ae 5534
5535 return 0;
2232a77c 5536}
13d60d35 5537
5538/*
5539 * Handle message from client to delete a remote VTEP for a VNI.
5540 */
89f4e507 5541void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
d62a17ae 5542{
5543 struct stream *s;
d7c0a89a 5544 unsigned short l = 0;
d62a17ae 5545 vni_t vni;
5546 struct in_addr vtep_ip;
5547 zebra_vni_t *zvni;
5548 zebra_vtep_t *zvtep;
b5ebdc9b 5549 struct interface *ifp;
5550 struct zebra_if *zif;
d62a17ae 5551
ec93aa12 5552 if (!is_evpn_enabled()) {
996c9314
LB
5553 zlog_warn(
5554 "%s: EVPN is not enabled yet we have received a vtep del command",
5555 __PRETTY_FUNCTION__);
8068a649 5556 return;
ec93aa12
DS
5557 }
5558
2853fed6 5559 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5560 zlog_err("Recv MACIP DEL for non-default VRF %u",
5561 zvrf_id(zvrf));
8068a649 5562 return;
2853fed6 5563 }
5564
1002497a 5565 s = msg;
d62a17ae 5566
89f4e507 5567 while (l < hdr->length) {
d62a17ae 5568 /* Obtain each remote VTEP and process. */
ec93aa12 5569 STREAM_GETL(s, vni);
d62a17ae 5570 l += 4;
ec93aa12 5571 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5572 l += IPV4_MAX_BYTELEN;
5573
5574 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5575 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5576 inet_ntoa(vtep_ip), vni,
d62a17ae 5577 zebra_route_string(client->proto));
5578
5579 /* Locate VNI hash entry - expected to exist. */
2853fed6 5580 zvni = zvni_lookup(vni);
d62a17ae 5581 if (!zvni) {
5582 if (IS_ZEBRA_DEBUG_VXLAN)
5583 zlog_debug(
5584 "Failed to locate VNI hash upon remote VTEP DEL, "
2853fed6 5585 "VNI %u",
5586 vni);
d62a17ae 5587 continue;
5588 }
5589
b5ebdc9b 5590 ifp = zvni->vxlan_if;
5591 if (!ifp) {
60466a63
QY
5592 zlog_err(
5593 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5594 zvni->vni, zvni);
b682f6de 5595 continue;
b5ebdc9b 5596 }
5597 zif = ifp->info;
5598
5599 /* If down or not mapped to a bridge, we're done. */
b682f6de 5600 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 5601 continue;
5602
d62a17ae 5603 /* If the remote VTEP does not exist, there's nothing more to
5604 * do.
5605 * Otherwise, uninstall any remote MACs pointing to this VTEP
5606 * and
5607 * then, the VTEP entry itself and remove it.
5608 */
5609 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5610 if (!zvtep)
5611 continue;
5612
5613 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
5614 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
5615 zvni_vtep_uninstall(zvni, &vtep_ip);
5616 zvni_vtep_del(zvni, zvtep);
5617 }
5618
ec93aa12 5619stream_failure:
8068a649 5620 return;
13d60d35 5621}
5622
5623/*
5624 * Handle message from client to add a remote VTEP for a VNI.
5625 */
89f4e507 5626void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
d62a17ae 5627{
5628 struct stream *s;
d7c0a89a 5629 unsigned short l = 0;
d62a17ae 5630 vni_t vni;
5631 struct in_addr vtep_ip;
5632 zebra_vni_t *zvni;
b5ebdc9b 5633 struct interface *ifp;
5634 struct zebra_if *zif;
d62a17ae 5635
ec93aa12 5636 if (!is_evpn_enabled()) {
996c9314
LB
5637 zlog_warn(
5638 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5639 __PRETTY_FUNCTION__);
8068a649 5640 return;
ec93aa12
DS
5641 }
5642
2853fed6 5643 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5644 zlog_err("Recv MACIP ADD for non-default VRF %u",
5645 zvrf_id(zvrf));
8068a649 5646 return;
2853fed6 5647 }
d62a17ae 5648
1002497a 5649 s = msg;
d62a17ae 5650
89f4e507 5651 while (l < hdr->length) {
d62a17ae 5652 /* Obtain each remote VTEP and process. */
ec93aa12 5653 STREAM_GETL(s, vni);
d62a17ae 5654 l += 4;
ec93aa12 5655 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 5656 l += IPV4_MAX_BYTELEN;
5657
5658 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5659 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5660 inet_ntoa(vtep_ip), vni,
d62a17ae 5661 zebra_route_string(client->proto));
5662
5663 /* Locate VNI hash entry - expected to exist. */
2853fed6 5664 zvni = zvni_lookup(vni);
d62a17ae 5665 if (!zvni) {
5666 zlog_err(
2853fed6 5667 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5668 vni);
d62a17ae 5669 continue;
5670 }
b5ebdc9b 5671
5672 ifp = zvni->vxlan_if;
5673 if (!ifp) {
d62a17ae 5674 zlog_err(
5675 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5676 zvni->vni, zvni);
5677 continue;
5678 }
5679
b5ebdc9b 5680 zif = ifp->info;
d62a17ae 5681
b5ebdc9b 5682 /* If down or not mapped to a bridge, we're done. */
b682f6de 5683 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 5684 continue;
5685
b682f6de 5686 /* If the remote VTEP already exists,
5687 there's nothing more to do. */
b5ebdc9b 5688 if (zvni_vtep_find(zvni, &vtep_ip))
d62a17ae 5689 continue;
5690
5691 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
996c9314
LB
5692 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5693 vni, zvni);
d62a17ae 5694 continue;
5695 }
5696
5697 zvni_vtep_install(zvni, &vtep_ip);
5698 }
5699
ec93aa12 5700stream_failure:
8068a649 5701 return;
13d60d35 5702}
5703
1a98c087
MK
5704/*
5705 * Add/Del gateway macip to evpn
5706 * g/w can be:
5707 * 1. SVI interface on a vlan aware bridge
5708 * 2. SVI interface on a vlan unaware bridge
5709 * 3. vrr interface (MACVLAN) associated to a SVI
5710 * We advertise macip routes for an interface if it is associated to VxLan vlan
5711 */
5712int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
5713 int add)
5714{
5715 struct ipaddr ip;
5716 struct ethaddr macaddr;
5717 zebra_vni_t *zvni = NULL;
1a98c087
MK
5718
5719 memset(&ip, 0, sizeof(struct ipaddr));
5720 memset(&macaddr, 0, sizeof(struct ethaddr));
5721
2853fed6 5722 /* Check if EVPN is enabled. */
5723 if (!is_evpn_enabled())
297a21b6
MK
5724 return 0;
5725
1a98c087
MK
5726 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
5727 struct interface *svi_if =
5728 NULL; /* SVI corresponding to the MACVLAN */
5729 struct zebra_if *ifp_zif =
5730 NULL; /* Zebra daemon specific info for MACVLAN */
5731 struct zebra_if *svi_if_zif =
5732 NULL; /* Zebra daemon specific info for SVI*/
5733
5734 ifp_zif = ifp->info;
5735 if (!ifp_zif)
5736 return -1;
5737
71349e03
MK
5738 /*
5739 * for a MACVLAN interface the link represents the svi_if
5740 */
5741 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
5742 ifp_zif->link_ifindex);
1a98c087 5743 if (!svi_if) {
2853fed6 5744 zlog_err("MACVLAN %s(%u) without link information",
5745 ifp->name, ifp->ifindex);
1a98c087
MK
5746 return -1;
5747 }
5748
5749 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
5750 /*
5751 * If it is a vlan aware bridge then the link gives the
5752 * bridge information
5753 */
5754 struct interface *svi_if_link = NULL;
5755
1a98c087 5756 svi_if_zif = svi_if->info;
71349e03
MK
5757 if (svi_if_zif) {
5758 svi_if_link = if_lookup_by_index_per_ns(
60466a63
QY
5759 zebra_ns_lookup(NS_DEFAULT),
5760 svi_if_zif->link_ifindex);
b7cfce93 5761 zvni = zvni_from_svi(svi_if, svi_if_link);
71349e03 5762 }
1a98c087 5763 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
5764 /*
5765 * If it is a vlan unaware bridge then svi is the bridge
5766 * itself
5767 */
b7cfce93 5768 zvni = zvni_from_svi(svi_if, svi_if);
1a98c087
MK
5769 }
5770 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
5771 struct zebra_if *svi_if_zif =
71349e03
MK
5772 NULL; /* Zebra daemon specific info for SVI */
5773 struct interface *svi_if_link =
5774 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
5775
5776 svi_if_zif = ifp->info;
e3bb770c
IS
5777 if (svi_if_zif) {
5778 svi_if_link = if_lookup_by_index_per_ns(
5779 zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex);
5780 if (svi_if_link)
5781 zvni = zvni_from_svi(ifp, svi_if_link);
5782 }
1a98c087 5783 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
b7cfce93 5784 zvni = zvni_from_svi(ifp, ifp);
1a98c087
MK
5785 }
5786
5787 if (!zvni)
5788 return 0;
5789
5790 if (!zvni->vxlan_if) {
5791 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5792 zvni->vni, zvni);
5793 return -1;
5794 }
5795
1a98c087 5796
1a98c087
MK
5797 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
5798
5799 if (p->family == AF_INET) {
5800 ip.ipa_type = IPADDR_V4;
5801 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
5802 sizeof(struct in_addr));
5803 } else if (p->family == AF_INET6) {
5804 ip.ipa_type = IPADDR_V6;
5805 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
5806 sizeof(struct in6_addr));
5807 }
5808
5809
5810 if (add)
5811 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
5812 else
5813 zvni_gw_macip_del(ifp, zvni, &ip);
5814
5815 return 0;
5816}
5817
2232a77c 5818/*
b7cfce93
MK
5819 * Handle SVI interface going down.
5820 * SVI can be associated to either L3-VNI or L2-VNI.
5821 * For L2-VNI: At this point, this is a NOP since
5822 * the kernel deletes the neighbor entries on this SVI (if any).
5823 * We only need to update the vrf corresponding to zvni.
5824 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5825 * from bgp
2232a77c 5826 */
d62a17ae 5827int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 5828{
b7cfce93
MK
5829 zebra_l3vni_t *zl3vni = NULL;
5830
5831 zl3vni = zl3vni_from_svi(ifp, link_if);
5832 if (zl3vni) {
5833
5834 /* process l3-vni down */
5835 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5836
5837 /* remove association with svi-if */
5838 zl3vni->svi_if = NULL;
5839 } else {
5840 zebra_vni_t *zvni = NULL;
5841
5842 /* since we dont have svi corresponding to zvni, we associate it
5843 * to default vrf. Note: the corresponding neigh entries on the
5844 * SVI would have already been deleted */
5845 zvni = zvni_from_svi(ifp, link_if);
5846 if (zvni) {
5847 zvni->vrf_id = VRF_DEFAULT;
5848
5849 /* update the tenant vrf in BGP */
5850 zvni_send_add_to_client(zvni);
5851 }
5852 }
d62a17ae 5853 return 0;
2232a77c 5854}
5855
5856/*
b7cfce93
MK
5857 * Handle SVI interface coming up.
5858 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5859 * vxlan intf).
5860 * For L2-VNI: we need to install any remote neighbors entried (used for
5861 * apr-suppression)
5862 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
2232a77c 5863 */
d62a17ae 5864int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 5865{
b7cfce93
MK
5866 zebra_vni_t *zvni = NULL;
5867 zebra_l3vni_t *zl3vni = NULL;
2232a77c 5868
b7cfce93
MK
5869 zl3vni = zl3vni_from_svi(ifp, link_if);
5870 if (zl3vni) {
2232a77c 5871
b7cfce93
MK
5872 /* associate with svi */
5873 zl3vni->svi_if = ifp;
2232a77c 5874
b7cfce93
MK
5875 /* process oper-up */
5876 if (is_l3vni_oper_up(zl3vni))
5877 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5878 } else {
5879
5880 /* process SVI up for l2-vni */
5881 struct neigh_walk_ctx n_wctx;
5882
5883 zvni = zvni_from_svi(ifp, link_if);
5884 if (!zvni)
5885 return 0;
5886
5887 if (!zvni->vxlan_if) {
5888 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
5889 zvni->vni, zvni);
5890 return -1;
5891 }
5892
5893 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5894 zlog_debug(
5895 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
5896 ifp->name, ifp->ifindex, zvni->vni,
5897 vrf_id_to_name(ifp->vrf_id));
2232a77c 5898
b7cfce93
MK
5899 /* update the vrf information for l2-vni and inform bgp */
5900 zvni->vrf_id = ifp->vrf_id;
5901 zvni_send_add_to_client(zvni);
5902
5903 /* Install any remote neighbors for this VNI. */
5904 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
5905 n_wctx.zvni = zvni;
996c9314 5906 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
b7cfce93
MK
5907 &n_wctx);
5908 }
2232a77c 5909
d62a17ae 5910 return 0;
2232a77c 5911}
5912
13d60d35 5913/*
b7cfce93 5914 * Handle VxLAN interface down
13d60d35 5915 */
d62a17ae 5916int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 5917{
d62a17ae 5918 vni_t vni;
b7cfce93
MK
5919 struct zebra_if *zif = NULL;
5920 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 5921 zebra_l3vni_t *zl3vni = NULL;
5922 zebra_vni_t *zvni;
13d60d35 5923
2853fed6 5924 /* Check if EVPN is enabled. */
5925 if (!is_evpn_enabled())
d62a17ae 5926 return 0;
13d60d35 5927
d62a17ae 5928 zif = ifp->info;
5929 assert(zif);
5930 vxl = &zif->l2info.vxl;
5931 vni = vxl->vni;
13d60d35 5932
643215ce 5933 zl3vni = zl3vni_lookup(vni);
5934 if (zl3vni) {
b7cfce93 5935 /* process-if-down for l3-vni */
b7cfce93 5936 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5937 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
5938 ifp->ifindex, vni);
b7cfce93 5939
b7cfce93 5940 zebra_vxlan_process_l3vni_oper_down(zl3vni);
b7cfce93
MK
5941 } else {
5942 /* process if-down for l2-vni */
b7cfce93 5943 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5944 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
5945 ifp->ifindex, vni);
13d60d35 5946
b7cfce93
MK
5947 /* Locate hash entry; it is expected to exist. */
5948 zvni = zvni_lookup(vni);
5949 if (!zvni) {
5950 zlog_err(
5951 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
5952 ifp->name, ifp->ifindex, vni);
5953 return -1;
5954 }
13d60d35 5955
b7cfce93 5956 assert(zvni->vxlan_if == ifp);
13d60d35 5957
b7cfce93
MK
5958 /* Delete this VNI from BGP. */
5959 zvni_send_del_to_client(zvni->vni);
2232a77c 5960
b7cfce93
MK
5961 /* Free up all neighbors and MACs, if any. */
5962 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
5963 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
13d60d35 5964
b7cfce93
MK
5965 /* Free up all remote VTEPs, if any. */
5966 zvni_vtep_del_all(zvni, 1);
5967 }
d62a17ae 5968 return 0;
13d60d35 5969}
5970
5971/*
5972 * Handle VxLAN interface up - update BGP if required.
5973 */
d62a17ae 5974int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 5975{
d62a17ae 5976 vni_t vni;
b7cfce93
MK
5977 struct zebra_if *zif = NULL;
5978 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 5979 zebra_vni_t *zvni = NULL;
5980 zebra_l3vni_t *zl3vni = NULL;
13d60d35 5981
2853fed6 5982 /* Check if EVPN is enabled. */
5983 if (!is_evpn_enabled())
d62a17ae 5984 return 0;
13d60d35 5985
d62a17ae 5986 zif = ifp->info;
5987 assert(zif);
5988 vxl = &zif->l2info.vxl;
5989 vni = vxl->vni;
13d60d35 5990
643215ce 5991 zl3vni = zl3vni_lookup(vni);
5992 if (zl3vni) {
13d60d35 5993
b7cfce93 5994 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5995 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp->name,
5996 ifp->ifindex, vni);
13d60d35 5997
b7cfce93 5998 /* we need to associate with SVI, if any, we can associate with
523cafc4 5999 * svi-if only after association with vxlan-intf is complete
6000 */
b7cfce93
MK
6001 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6002
6003 if (is_l3vni_oper_up(zl3vni))
6004 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6005 } else {
6006 /* Handle L2-VNI add */
b7cfce93
MK
6007 struct interface *vlan_if = NULL;
6008
6009 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
6010 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
6011 ifp->ifindex, vni);
b7cfce93
MK
6012
6013 /* Locate hash entry; it is expected to exist. */
6014 zvni = zvni_lookup(vni);
6015 if (!zvni) {
6016 zlog_err(
6017 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6018 ifp->name, ifp->ifindex, vni);
6019 return -1;
6020 }
6021
6022 assert(zvni->vxlan_if == ifp);
6023 vlan_if = zvni_map_to_svi(vxl->access_vlan,
6024 zif->brslave_info.br_if);
6025 if (vlan_if) {
6026 zvni->vrf_id = vlan_if->vrf_id;
6027 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
6028 if (zl3vni)
6029 listnode_add_sort(zl3vni->l2vnis, zvni);
6030 }
6031
6032 /* If part of a bridge, inform BGP about this VNI. */
6033 /* Also, read and populate local MACs and neighbors. */
6034 if (zif->brslave_info.br_if) {
6035 zvni_send_add_to_client(zvni);
6036 zvni_read_mac_neigh(zvni, ifp);
6037 }
d62a17ae 6038 }
13d60d35 6039
d62a17ae 6040 return 0;
13d60d35 6041}
6042
6043/*
6044 * Handle VxLAN interface delete. Locate and remove entry in hash table
6045 * and update BGP, if required.
6046 */
d62a17ae 6047int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 6048{
d62a17ae 6049 vni_t vni;
b7cfce93
MK
6050 struct zebra_if *zif = NULL;
6051 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 6052 zebra_vni_t *zvni = NULL;
6053 zebra_l3vni_t *zl3vni = NULL;
13d60d35 6054
2853fed6 6055 /* Check if EVPN is enabled. */
6056 if (!is_evpn_enabled())
d62a17ae 6057 return 0;
13d60d35 6058
d62a17ae 6059 zif = ifp->info;
6060 assert(zif);
6061 vxl = &zif->l2info.vxl;
6062 vni = vxl->vni;
13d60d35 6063
643215ce 6064 zl3vni = zl3vni_lookup(vni);
6065 if (zl3vni) {
b7cfce93
MK
6066
6067 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
6068 zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
6069 ifp->ifindex);
13d60d35 6070
b7cfce93
MK
6071 /* process oper-down for l3-vni */
6072 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2232a77c 6073
b7cfce93 6074 /* remove the association with vxlan_if */
b67a60d2 6075 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
b7cfce93
MK
6076 zl3vni->vxlan_if = NULL;
6077 } else {
13d60d35 6078
b7cfce93 6079 /* process if-del for l2-vni*/
b7cfce93 6080 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
6081 zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
6082 ifp->ifindex);
b7cfce93
MK
6083
6084 /* Locate hash entry; it is expected to exist. */
6085 zvni = zvni_lookup(vni);
6086 if (!zvni) {
6087 zlog_err(
6088 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6089 ifp->name, ifp->ifindex, vni);
6090 return 0;
6091 }
6092
6093 /* remove from l3-vni list */
6094 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
6095 if (zl3vni)
6096 listnode_delete(zl3vni->l2vnis, zvni);
6097
6098 /* Delete VNI from BGP. */
6099 zvni_send_del_to_client(zvni->vni);
6100
6101 /* Free up all neighbors and MAC, if any. */
6102 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
6103 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
6104
6105 /* Free up all remote VTEPs, if any. */
6106 zvni_vtep_del_all(zvni, 0);
6107
6108 /* Delete the hash entry. */
6109 if (zvni_del(zvni)) {
6110 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6111 zvni, ifp->name, ifp->ifindex, zvni->vni);
6112 return -1;
6113 }
d62a17ae 6114 }
d62a17ae 6115 return 0;
13d60d35 6116}
6117
6118/*
6119 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6120 */
d7c0a89a 6121int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
d62a17ae 6122{
d62a17ae 6123 vni_t vni;
b7cfce93
MK
6124 struct zebra_if *zif = NULL;
6125 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 6126 zebra_vni_t *zvni = NULL;
6127 zebra_l3vni_t *zl3vni = NULL;
d62a17ae 6128
2853fed6 6129 /* Check if EVPN is enabled. */
6130 if (!is_evpn_enabled())
d62a17ae 6131 return 0;
6132
6133 zif = ifp->info;
6134 assert(zif);
6135 vxl = &zif->l2info.vxl;
6136 vni = vxl->vni;
6137
643215ce 6138 zl3vni = zl3vni_lookup(vni);
6139 if (zl3vni) {
af026ae4 6140
b7cfce93
MK
6141 if (IS_ZEBRA_DEBUG_VXLAN)
6142 zlog_debug(
6143 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
996c9314
LB
6144 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
6145 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
6146 zif->brslave_info.bridge_ifindex, chgflags);
6147
6148 /* Removed from bridge? Cleanup and return */
6149 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6150 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6151 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6152 return 0;
6153 }
6154
6155 /* access-vlan change - process oper down, associate with new
523cafc4 6156 * svi_if and then process oper up again
6157 */
b7cfce93
MK
6158 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6159 if (if_is_operative(ifp)) {
6160 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6161 zl3vni->svi_if = NULL;
6162 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
bca63dc8 6163 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
6164 if (is_l3vni_oper_up(zl3vni))
6165 zebra_vxlan_process_l3vni_oper_up(
996c9314 6166 zl3vni);
b7cfce93
MK
6167 }
6168 }
d62a17ae 6169
12eeac84
MK
6170 /*
6171 * local-ip change - process oper down, associate with new
6172 * local-ip and then process oper up again
6173 */
6174 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
6175 if (if_is_operative(ifp)) {
6176 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6177 zl3vni->local_vtep_ip = vxl->vtep_ip;
6178 if (is_l3vni_oper_up(zl3vni))
6179 zebra_vxlan_process_l3vni_oper_up(
996c9314 6180 zl3vni);
12eeac84
MK
6181 }
6182 }
6183
bca63dc8
MK
6184 /* Update local tunnel IP. */
6185 zl3vni->local_vtep_ip = vxl->vtep_ip;
6186
12eeac84
MK
6187 /* if we have a valid new master, process l3-vni oper up */
6188 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
6189 if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
b7cfce93
MK
6190 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6191 }
6192 } else {
d62a17ae 6193
b7cfce93
MK
6194 /* Update VNI hash. */
6195 zvni = zvni_lookup(vni);
6196 if (!zvni) {
6197 zlog_err(
6198 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6199 ifp->name, ifp->ifindex, vni);
6200 return -1;
6201 }
d62a17ae 6202
b7cfce93
MK
6203 if (IS_ZEBRA_DEBUG_VXLAN)
6204 zlog_debug(
6205 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
996c9314
LB
6206 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
6207 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
6208 zif->brslave_info.bridge_ifindex, chgflags);
6209
6210 /* Removed from bridge? Cleanup and return */
6211 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6212 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6213 /* Delete from client, remove all remote VTEPs */
6214 /* Also, free up all MACs and neighbors. */
6215 zvni_send_del_to_client(zvni->vni);
6216 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
6217 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
6218 zvni_vtep_del_all(zvni, 1);
6219 return 0;
6220 }
d62a17ae 6221
b7cfce93
MK
6222 /* Handle other changes. */
6223 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6224 /* Remove all existing local neigh and MACs for this VNI
6225 * (including from BGP)
6226 */
6227 zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6228 zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6229 }
d62a17ae 6230
b7cfce93
MK
6231 zvni->local_vtep_ip = vxl->vtep_ip;
6232 zvni->vxlan_if = ifp;
d62a17ae 6233
b7cfce93
MK
6234 /* Take further actions needed.
6235 * Note that if we are here, there is a change of interest.
6236 */
6237 /* If down or not mapped to a bridge, we're done. */
6238 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6239 return 0;
d62a17ae 6240
b7cfce93
MK
6241 /* Inform BGP, if there is a change of interest. */
6242 if (chgflags
6243 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
6244 zvni_send_add_to_client(zvni);
6245
6246 /* If there is a valid new master or a VLAN mapping change,
6247 * read and populate local MACs and neighbors.
6248 * Also, reinstall any remote MACs and neighbors
6249 * for this VNI (based on new VLAN).
6250 */
6251 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6252 zvni_read_mac_neigh(zvni, ifp);
6253 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6254 struct mac_walk_ctx m_wctx;
6255 struct neigh_walk_ctx n_wctx;
6256
6257 zvni_read_mac_neigh(zvni, ifp);
6258
6259 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6260 m_wctx.zvni = zvni;
996c9314 6261 hash_iterate(zvni->mac_table, zvni_install_mac_hash,
b7cfce93
MK
6262 &m_wctx);
6263
6264 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6265 n_wctx.zvni = zvni;
6266 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
6267 &n_wctx);
6268 }
d62a17ae 6269 }
6270
6271 return 0;
13d60d35 6272}
6273
6274/*
6275 * Handle VxLAN interface add.
6276 */
d62a17ae 6277int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 6278{
d62a17ae 6279 vni_t vni;
b7cfce93
MK
6280 struct zebra_if *zif = NULL;
6281 struct zebra_l2info_vxlan *vxl = NULL;
643215ce 6282 zebra_vni_t *zvni = NULL;
6283 zebra_l3vni_t *zl3vni = NULL;
13d60d35 6284
2853fed6 6285 /* Check if EVPN is enabled. */
6286 if (!is_evpn_enabled())
d62a17ae 6287 return 0;
13d60d35 6288
d62a17ae 6289 zif = ifp->info;
6290 assert(zif);
6291 vxl = &zif->l2info.vxl;
6292 vni = vxl->vni;
13d60d35 6293
643215ce 6294 zl3vni = zl3vni_lookup(vni);
6295 if (zl3vni) {
13d60d35 6296
b7cfce93 6297 /* process if-add for l3-vni*/
b7cfce93
MK
6298 if (IS_ZEBRA_DEBUG_VXLAN)
6299 zlog_debug(
6300 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
996c9314
LB
6301 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
6302 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
6303 zif->brslave_info.bridge_ifindex);
6304
b7cfce93 6305 /* associate with vxlan_if */
b67a60d2 6306 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
6307 zl3vni->vxlan_if = ifp;
6308
6309 /* Associate with SVI, if any. We can associate with svi-if only
6310 * after association with vxlan_if is complete */
6311 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6312
6313 if (is_l3vni_oper_up(zl3vni))
6314 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6315 } else {
6316
6317 /* process if-add for l2-vni */
b7cfce93
MK
6318 struct interface *vlan_if = NULL;
6319
6320 /* Create or update VNI hash. */
6321 zvni = zvni_lookup(vni);
6322 if (!zvni) {
6323 zvni = zvni_add(vni);
6324 if (!zvni) {
6325 zlog_err(
6326 "Failed to add VNI hash, IF %s(%u) VNI %u",
6327 ifp->name, ifp->ifindex, vni);
6328 return -1;
6329 }
6330 }
6331
6332 zvni->local_vtep_ip = vxl->vtep_ip;
6333 zvni->vxlan_if = ifp;
6334 vlan_if = zvni_map_to_svi(vxl->access_vlan,
6335 zif->brslave_info.br_if);
6336 if (vlan_if) {
6337 zvni->vrf_id = vlan_if->vrf_id;
6338 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
6339 if (zl3vni)
6340 listnode_add_sort(zl3vni->l2vnis, zvni);
6341 }
6342
6343 if (IS_ZEBRA_DEBUG_VXLAN)
6344 zlog_debug(
6345 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6346 vni,
996c9314
LB
6347 vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
6348 : "Default",
6349 ifp->name, ifp->ifindex, vxl->access_vlan,
6350 inet_ntoa(vxl->vtep_ip),
b7cfce93
MK
6351 zif->brslave_info.bridge_ifindex);
6352
6353 /* If down or not mapped to a bridge, we're done. */
6354 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6355 return 0;
6356
6357 /* Inform BGP */
6358 zvni_send_add_to_client(zvni);
6359
6360 /* Read and populate local MACs and neighbors */
6361 zvni_read_mac_neigh(zvni, ifp);
6362 }
6363
6364 return 0;
6365}
6366
996c9314
LB
6367int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
6368 char *err, int err_str_sz, int filter,
6369 int add)
b7cfce93
MK
6370{
6371 zebra_l3vni_t *zl3vni = NULL;
6372 struct zebra_vrf *zvrf_default = NULL;
6373
6374 zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
6375 if (!zvrf_default)
6376 return -1;
6377
6378 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 6379 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
b7cfce93
MK
6380 add ? "ADD" : "DEL");
6381
6382 if (add) {
6383
6384 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
6385
6386 /* check if the vni is already present under zvrf */
6387 if (zvrf->l3vni) {
3f02fbab 6388 snprintf(err, err_str_sz,
b7cfce93
MK
6389 "VNI is already configured under the vrf");
6390 return -1;
6391 }
6392
6393 /* check if this VNI is already present in the system */
6394 zl3vni = zl3vni_lookup(vni);
6395 if (zl3vni) {
3f02fbab 6396 snprintf(err, err_str_sz,
b7cfce93
MK
6397 "VNI is already configured as L3-VNI");
6398 return -1;
6399 }
6400
6401 /* add the L3-VNI to the global table */
6402 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
6403 if (!zl3vni) {
996c9314 6404 snprintf(err, err_str_sz, "Could not add L3-VNI");
b7cfce93
MK
6405 return -1;
6406 }
6407
6408 /* associate the vrf with vni */
6409 zvrf->l3vni = vni;
6410
c48d9f5f
MK
6411 /* set the filter in l3vni to denote if we are using l3vni only
6412 * for prefix routes
6413 */
6414 if (filter)
6415 SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
6416
b7cfce93 6417 /* associate with vxlan-intf;
523cafc4 6418 * we need to associate with the vxlan-intf first
6419 */
b7cfce93
MK
6420 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
6421
6422 /* associate with corresponding SVI interface, we can associate
6423 * with svi-if only after vxlan interface association is
523cafc4 6424 * complete
6425 */
b7cfce93
MK
6426 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6427
6428 /* formulate l2vni list */
996c9314
LB
6429 hash_iterate(zvrf_default->vni_table, zvni_add_to_l3vni_list,
6430 zl3vni);
b7cfce93
MK
6431
6432 if (is_l3vni_oper_up(zl3vni))
6433 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6434
6435 } else {
6436 zl3vni = zl3vni_lookup(vni);
6437 if (!zl3vni) {
3f02fbab 6438 snprintf(err, err_str_sz, "VNI doesn't exist");
d62a17ae 6439 return -1;
6440 }
b7cfce93
MK
6441
6442 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6443
5e06422c 6444 /* delete and uninstall all rmacs */
996c9314 6445 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
5e06422c
MK
6446 zl3vni);
6447
6448 /* delete and uninstall all next-hops */
996c9314 6449 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
5e06422c
MK
6450 zl3vni);
6451
b7cfce93
MK
6452 zvrf->l3vni = 0;
6453 zl3vni_del(zl3vni);
6454
6455 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
d62a17ae 6456 }
b7cfce93
MK
6457 return 0;
6458}
13d60d35 6459
84915b0a 6460int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
6461{
6462 zebra_l3vni_t *zl3vni = NULL;
6463
6464 if (zvrf->l3vni)
6465 zl3vni = zl3vni_lookup(zvrf->l3vni);
6466 if (!zl3vni)
6467 return 0;
6468
6469 zl3vni->vrf_id = zvrf_id(zvrf);
6470 if (is_l3vni_oper_up(zl3vni))
6471 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6472 return 0;
6473}
6474
6475int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
b7cfce93
MK
6476{
6477 zebra_l3vni_t *zl3vni = NULL;
13d60d35 6478
84915b0a 6479 if (zvrf->l3vni)
6480 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93 6481 if (!zl3vni)
d62a17ae 6482 return 0;
13d60d35 6483
84915b0a 6484 zl3vni->vrf_id = VRF_UNKNOWN;
b7cfce93 6485 zebra_vxlan_process_l3vni_oper_down(zl3vni);
84915b0a 6486 return 0;
6487}
6488
6489int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
6490{
6491 zebra_l3vni_t *zl3vni = NULL;
6492 vni_t vni;
6493
6494 if (zvrf->l3vni)
6495 zl3vni = zl3vni_lookup(zvrf->l3vni);
6496 if (!zl3vni)
6497 return 0;
6498
6499 vni = zl3vni->vni;
b7cfce93 6500 zl3vni_del(zl3vni);
84915b0a 6501 zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
2232a77c 6502
d62a17ae 6503 return 0;
13d60d35 6504}
6505
31310b25
MK
6506/*
6507 * Handle message from client to enable/disable advertisement of g/w macip
6508 * routes
6509 */
89f4e507 6510void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
31310b25
MK
6511{
6512 struct stream *s;
6513 int advertise;
6514 vni_t vni = 0;
6515 zebra_vni_t *zvni = NULL;
6516 struct interface *ifp = NULL;
6517 struct zebra_if *zif = NULL;
6518 struct zebra_l2info_vxlan zl2_info;
6519 struct interface *vlan_if = NULL;
6520
6521 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6522 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6523 zvrf_id(zvrf));
8068a649 6524 return;
31310b25
MK
6525 }
6526
1002497a 6527 s = msg;
31310b25
MK
6528 advertise = stream_getc(s);
6529 vni = stream_get3(s);
6530
6531 zvni = zvni_lookup(vni);
6532 if (!zvni)
8068a649 6533 return;
31310b25
MK
6534
6535 if (zvni->advertise_subnet == advertise)
8068a649 6536 return;
31310b25
MK
6537
6538 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
6539 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6540 advertise ? "enabled" : "disabled", vni,
6541 zvni->advertise_subnet ? "enabled" : "disabled");
31310b25
MK
6542
6543
6544 zvni->advertise_subnet = advertise;
6545
6546 ifp = zvni->vxlan_if;
6547 if (!ifp)
8068a649 6548 return;
31310b25
MK
6549
6550 zif = ifp->info;
6551
6552 /* If down or not mapped to a bridge, we're done. */
6553 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 6554 return;
31310b25
MK
6555
6556 zl2_info = zif->l2info.vxl;
6557
996c9314
LB
6558 vlan_if =
6559 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
31310b25 6560 if (!vlan_if)
8068a649 6561 return;
31310b25
MK
6562
6563 if (zvni->advertise_subnet)
6564 zvni_advertise_subnet(zvni, vlan_if, 1);
6565 else
6566 zvni_advertise_subnet(zvni, vlan_if, 0);
31310b25
MK
6567}
6568
1a98c087
MK
6569/*
6570 * Handle message from client to enable/disable advertisement of g/w macip
6571 * routes
6572 */
89f4e507 6573void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
1a98c087
MK
6574{
6575 struct stream *s;
6576 int advertise;
6577 vni_t vni = 0;
6578 zebra_vni_t *zvni = NULL;
b5ebdc9b 6579 struct interface *ifp = NULL;
1a98c087 6580
2853fed6 6581 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6582 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6583 zvrf_id(zvrf));
8068a649 6584 return;
2853fed6 6585 }
6586
1002497a 6587 s = msg;
ec93aa12
DS
6588 STREAM_GETC(s, advertise);
6589 STREAM_GET(&vni, s, 3);
1a98c087
MK
6590
6591 if (!vni) {
6592 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 6593 zlog_debug("EVPN gateway macip Adv %s, currently %s",
1a98c087 6594 advertise ? "enabled" : "disabled",
2853fed6 6595 advertise_gw_macip_enabled(NULL)
1a98c087
MK
6596 ? "enabled"
6597 : "disabled");
6598
6599 if (zvrf->advertise_gw_macip == advertise)
8068a649 6600 return;
1a98c087
MK
6601
6602 zvrf->advertise_gw_macip = advertise;
6603
2853fed6 6604 if (advertise_gw_macip_enabled(zvni))
1a98c087 6605 hash_iterate(zvrf->vni_table,
2853fed6 6606 zvni_gw_macip_add_for_vni_hash, NULL);
1a98c087
MK
6607 else
6608 hash_iterate(zvrf->vni_table,
2853fed6 6609 zvni_gw_macip_del_for_vni_hash, NULL);
1a98c087
MK
6610
6611 } else {
6612 struct zebra_if *zif = NULL;
6613 struct zebra_l2info_vxlan zl2_info;
6614 struct interface *vlan_if = NULL;
6615 struct interface *vrr_if = NULL;
6616
01a6143b
MK
6617 zvni = zvni_lookup(vni);
6618 if (!zvni)
124ead27 6619 return;
01a6143b 6620
1a98c087
MK
6621 if (IS_ZEBRA_DEBUG_VXLAN)
6622 zlog_debug(
2853fed6 6623 "EVPN gateway macip Adv %s on VNI %d , currently %s",
1a98c087 6624 advertise ? "enabled" : "disabled", vni,
996c9314
LB
6625 advertise_gw_macip_enabled(zvni) ? "enabled"
6626 : "disabled");
1a98c087 6627
1a98c087 6628 if (zvni->advertise_gw_macip == advertise)
8068a649 6629 return;
1a98c087
MK
6630
6631 zvni->advertise_gw_macip = advertise;
6632
b5ebdc9b 6633 ifp = zvni->vxlan_if;
6634 if (!ifp)
8068a649 6635 return;
b5ebdc9b 6636
6637 zif = ifp->info;
6638
6639 /* If down or not mapped to a bridge, we're done. */
b682f6de 6640 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 6641 return;
b5ebdc9b 6642
1a98c087
MK
6643 zl2_info = zif->l2info.vxl;
6644
2853fed6 6645 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
1a98c087
MK
6646 zif->brslave_info.br_if);
6647 if (!vlan_if)
8068a649 6648 return;
1a98c087 6649
2853fed6 6650 if (advertise_gw_macip_enabled(zvni)) {
1a98c087
MK
6651 /* Add primary SVI MAC-IP */
6652 zvni_add_macip_for_intf(vlan_if, zvni);
6653
6654 /* Add VRR MAC-IP - if any*/
6655 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6656 if (vrr_if)
6657 zvni_add_macip_for_intf(vrr_if, zvni);
6658 } else {
6659 /* Del primary MAC-IP */
6660 zvni_del_macip_for_intf(vlan_if, zvni);
6661
6662 /* Del VRR MAC-IP - if any*/
6663 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6664 if (vrr_if)
6665 zvni_del_macip_for_intf(vrr_if, zvni);
6666 }
6667 }
6668
ec93aa12 6669stream_failure:
8068a649 6670 return;
1a98c087
MK
6671}
6672
6673
13d60d35 6674/*
6675 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6676 * When enabled, the VNI hash table will be built and MAC FDB table read;
6677 * when disabled, the entries should be deleted and remote VTEPs and MACs
6678 * uninstalled from the kernel.
6679 */
89f4e507 6680void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
13d60d35 6681{
655b04d1
MK
6682 struct stream *s = NULL;
6683 int advertise = 0;
6684 struct zebra_ns *zns = NULL;
13d60d35 6685
2853fed6 6686 if (zvrf_id(zvrf) != VRF_DEFAULT) {
996c9314 6687 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf));
8068a649 6688 return;
2853fed6 6689 }
6690
1002497a 6691 s = msg;
ec93aa12 6692 STREAM_GETC(s, advertise);
13d60d35 6693
d62a17ae 6694 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 6695 zlog_debug("EVPN VNI Adv %s, currently %s",
d62a17ae 6696 advertise ? "enabled" : "disabled",
2853fed6 6697 is_evpn_enabled() ? "enabled" : "disabled");
13d60d35 6698
d62a17ae 6699 if (zvrf->advertise_all_vni == advertise)
8068a649 6700 return;
13d60d35 6701
d62a17ae 6702 zvrf->advertise_all_vni = advertise;
2853fed6 6703 if (is_evpn_enabled()) {
d62a17ae 6704 /* Build VNI hash table and inform BGP. */
2853fed6 6705 zvni_build_hash_table();
2232a77c 6706
1a98c087
MK
6707 /* Add all SVI (L3 GW) MACs to BGP*/
6708 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
2853fed6 6709 NULL);
1a98c087 6710
d62a17ae 6711 /* Read the MAC FDB */
6712 macfdb_read(zvrf->zns);
2232a77c 6713
d62a17ae 6714 /* Read neighbors */
6715 neigh_read(zvrf->zns);
6716 } else {
6717 /* Cleanup VTEPs for all VNIs - uninstall from
6718 * kernel and free entries.
6719 */
6720 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
655b04d1
MK
6721
6722 /* cleanup all l3vnis */
6723 zns = zebra_ns_lookup(NS_DEFAULT);
6724 if (!zns)
8068a649 6725 return;
655b04d1
MK
6726
6727 hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
d62a17ae 6728 }
13d60d35 6729
ec93aa12 6730stream_failure:
8068a649 6731 return;
13d60d35 6732}
6733
6734/*
6735 * Allocate VNI hash table for this VRF and do other initialization.
6736 * NOTE: Currently supported only for default VRF.
6737 */
d62a17ae 6738void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 6739{
d62a17ae 6740 if (!zvrf)
6741 return;
6742 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
6743 "Zebra VRF VNI Table");
13d60d35 6744}
6745
84915b0a 6746/* Cleanup VNI info, but don't free the table. */
6747void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
6748{
6749 if (!zvrf)
6750 return;
6751 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
6752}
6753
13d60d35 6754/* Close all VNI handling */
d62a17ae 6755void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 6756{
2853fed6 6757 if (!zvrf)
6758 return;
d62a17ae 6759 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9b67b514 6760 hash_free(zvrf->vni_table);
13d60d35 6761}
b7cfce93
MK
6762
6763/* init the l3vni table */
6764void zebra_vxlan_ns_init(struct zebra_ns *zns)
6765{
6766 zns->l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
6767 "Zebra VRF L3 VNI table");
6768}
6769
6770/* free l3vni table */
6771void zebra_vxlan_ns_disable(struct zebra_ns *zns)
6772{
6773 hash_free(zns->l3vni_table);
6774}
d3135ba3 6775
6776/* get the l3vni svi ifindex */
6777ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
6778{
6779 zebra_l3vni_t *zl3vni = NULL;
6780
6781 zl3vni = zl3vni_from_vrf(vrf_id);
6782 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
6783 return 0;
6784
6785 return zl3vni->svi_if->ifindex;
6786}