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