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