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