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