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