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