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