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