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