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