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