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