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