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