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