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