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