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