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