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