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