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