]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
zebra: Delete AUTO macs when neigh list is empty
[mirror_frr.git] / zebra / zebra_vxlan.c
CommitLineData
13d60d35 1/*
2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "if.h"
26#include "prefix.h"
27#include "table.h"
28#include "memory.h"
29#include "log.h"
30#include "linklist.h"
31#include "stream.h"
32#include "hash.h"
33#include "jhash.h"
34#include "vlan.h"
35#include "vxlan.h"
36
37#include "zebra/rib.h"
38#include "zebra/rt.h"
39#include "zebra/zebra_ns.h"
40#include "zebra/zserv.h"
41#include "zebra/debug.h"
42#include "zebra/interface.h"
43#include "zebra/zebra_vrf.h"
44#include "zebra/rt_netlink.h"
45#include "zebra/zebra_vxlan_private.h"
46#include "zebra/zebra_vxlan.h"
47#include "zebra/zebra_memory.h"
48#include "zebra/zebra_l2.h"
cd233079 49#include "lib/json.h"
13d60d35 50
d62a17ae 51DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
13d60d35 52DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP");
d62a17ae 53DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC");
54DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
13d60d35 55
56/* definitions */
57
58
59/* static function declarations */
cd233079 60static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
d62a17ae 61static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
62static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
cd233079 63 void **args);
d62a17ae 64static void zvni_print_mac(zebra_mac_t *mac, void *ctxt);
65static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt);
66static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt);
cd233079
CS
67static void zvni_print(zebra_vni_t *zvni, void **ctxt);
68static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]);
d62a17ae 69
70static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
71 struct ethaddr *macaddr,
1a98c087 72 struct ipaddr *ip, u_char flags,
d62a17ae 73 u_int16_t cmd);
74static unsigned int neigh_hash_keymake(void *p);
75static int neigh_cmp(const void *p1, const void *p2);
76static void *zvni_neigh_alloc(void *p);
b6938a74
MK
77static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
78 struct ethaddr *mac);
d62a17ae 79static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n);
80static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg);
81static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
82 struct in_addr *r_vtep_ip);
83static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
84 int uninstall, int upd_client, u_int32_t flags);
85static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip);
86static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
87 struct ipaddr *ip,
1a98c087 88 struct ethaddr *macaddr, u_char flags);
d62a17ae 89static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
90 struct ipaddr *ip,
1a98c087 91 struct ethaddr *macaddr, u_char flags);
d62a17ae 92static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
93static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
94static zebra_vni_t *zvni_map_svi(struct interface *ifp,
95 struct interface *br_if);
96static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid,
97 struct interface *br_if);
98
99static unsigned int mac_hash_keymake(void *p);
100static int mac_cmp(const void *p1, const void *p2);
101static void *zvni_mac_alloc(void *p);
102static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr);
103static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac);
104static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg);
105static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
106 struct in_addr *r_vtep_ip);
107static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
108 int uninstall, int upd_client, u_int32_t flags);
109static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
110static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
1a98c087 111 struct ethaddr *macaddr, u_char flags);
d62a17ae 112static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
1a98c087 113 struct ethaddr *macaddr, u_char flags);
d62a17ae 114static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
115 struct interface *br_if, vlanid_t vid);
116static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
117static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local);
118static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt);
119
120static unsigned int vni_hash_keymake(void *p);
121static int vni_hash_cmp(const void *p1, const void *p2);
122static void *zvni_alloc(void *p);
123static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni);
124static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni);
125static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni);
126static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni);
127static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni);
128static void zvni_build_hash_table(struct zebra_vrf *zvrf);
129static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
130static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
131static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
132static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep);
133static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall);
134static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip);
135static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip);
1a98c087
MK
136static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
137static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
138static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
139 struct ethaddr *macaddr, struct ipaddr *ip);
140static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
141 struct ipaddr *ip);
142struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
143static int advertise_gw_macip_enabled(struct zebra_vrf *zvrf,
144 zebra_vni_t *zvni);
145static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
146 int uninstall);
13d60d35 147
148/* Private functions */
149
1a98c087
MK
150static int advertise_gw_macip_enabled(struct zebra_vrf *zvrf, zebra_vni_t *zvni)
151{
152 if (zvrf && zvrf->advertise_gw_macip)
153 return 1;
154
155 if (zvni && zvni->advertise_gw_macip)
156 return 1;
157
158 return 0;
159}
160
cec2e17d 161/*
162 * Helper function to determine maximum width of neighbor IP address for
163 * display - just because we're dealing with IPv6 addresses that can
164 * widely vary.
165 */
d62a17ae 166static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt)
cec2e17d 167{
d62a17ae 168 zebra_neigh_t *n;
169 char buf[INET6_ADDRSTRLEN];
170 struct neigh_walk_ctx *wctx = ctxt;
171 int width;
cec2e17d 172
d62a17ae 173 n = (zebra_neigh_t *)backet->data;
174 if (!n)
175 return;
cec2e17d 176
d62a17ae 177 ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf);
178 if (width > wctx->addr_width)
179 wctx->addr_width = width;
cec2e17d 180}
181
182/*
183 * Print a specific neighbor entry.
184 */
cd233079 185static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
cec2e17d 186{
d62a17ae 187 struct vty *vty;
188 char buf1[ETHER_ADDR_STRLEN];
189 char buf2[INET6_ADDRSTRLEN];
cec2e17d 190
cd233079
CS
191 ipaddr2str(&n->ip, buf2, sizeof(buf2));
192 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
193 vty = (struct vty *)ctxt;
194 if (json == NULL) {
195 vty_out(vty, "IP: %s\n",
196 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
197 vty_out(vty, " MAC: %s",
198 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
199 } else {
200 json_object_string_add(json, "ip", buf2);
201 json_object_string_add(json, "mac", buf1);
202 }
203 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
b6938a74 204 if (json == NULL) {
cd233079
CS
205 vty_out(vty, " Remote VTEP: %s",
206 inet_ntoa(n->r_vtep_ip));
b6938a74 207 } else
cd233079
CS
208 json_object_string_add(json, "remoteVtep",
209 inet_ntoa(n->r_vtep_ip));
210 }
f51d8a27
MK
211 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
212 if (!json) {
213 vty_out(vty, "\n");
214 vty_out(vty, " State: %s",
215 IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active"
216 : "Inactive");
217 }
218 }
cd233079
CS
219 if (json == NULL)
220 vty_out(vty, "\n");
cec2e17d 221}
222
223/*
224 * Print neighbor hash entry - called for display of all neighbors.
225 */
d62a17ae 226static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt)
227{
228 struct vty *vty;
cd233079 229 json_object *json_vni = NULL, *json_row = NULL;
d62a17ae 230 zebra_neigh_t *n;
231 char buf1[ETHER_ADDR_STRLEN];
232 char buf2[INET6_ADDRSTRLEN];
233 struct neigh_walk_ctx *wctx = ctxt;
234
235 vty = wctx->vty;
cd233079 236 json_vni = wctx->json;
d62a17ae 237 n = (zebra_neigh_t *)backet->data;
238 if (!n)
239 return;
240
cd233079
CS
241 if (json_vni)
242 json_row = json_object_new_object();
243
d62a17ae 244 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
245 ipaddr2str(&n->ip, buf2, sizeof(buf2));
246 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)
247 && !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) {
cd233079
CS
248 if (json_vni == NULL) {
249 vty_out(vty, "%*s %-6s %-17s\n", -wctx->addr_width,
250 buf2, "local", buf1);
251 } else {
252 json_object_string_add(json_row, "type", "local");
253 json_object_string_add(json_row, "mac", buf1);
254 }
d62a17ae 255 wctx->count++;
256 } else {
257 if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) {
258 if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) {
cd233079
CS
259 if (json_vni == NULL) {
260 if (wctx->count == 0)
261 vty_out(vty,
262 "%*s %-6s %-17s %-21s\n",
263 -wctx->addr_width,
264 "Neighbor", "Type",
265 "MAC", "Remote VTEP");
d62a17ae 266 vty_out(vty, "%*s %-6s %-17s %-21s\n",
cd233079
CS
267 -wctx->addr_width, buf2,
268 "remote", buf1,
269 inet_ntoa(n->r_vtep_ip));
270 } else {
271 json_object_string_add(json_row, "type",
272 "remote");
273 json_object_string_add(json_row, "mac",
274 buf1);
275 json_object_string_add(
276 json_row, "remoteVtep",
277 inet_ntoa(n->r_vtep_ip));
278 }
279 wctx->count++;
280 }
281 } else {
282 if (json_vni == NULL) {
d62a17ae 283 vty_out(vty, "%*s %-6s %-17s %-21s\n",
284 -wctx->addr_width, buf2, "remote", buf1,
285 inet_ntoa(n->r_vtep_ip));
cd233079
CS
286 } else {
287 json_object_string_add(json_row, "type",
288 "remote");
289 json_object_string_add(json_row, "mac", buf1);
290 json_object_string_add(json_row, "remoteVtep",
291 inet_ntoa(n->r_vtep_ip));
d62a17ae 292 }
d62a17ae 293 wctx->count++;
294 }
295 }
cd233079
CS
296
297 if (json_vni)
298 json_object_object_add(json_vni, buf2, json_row);
cec2e17d 299}
300
301/*
302 * Print neighbors for all VNI.
303 */
d62a17ae 304static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
cd233079 305 void **args)
cec2e17d 306{
d62a17ae 307 struct vty *vty;
cd233079 308 json_object *json = NULL, *json_vni = NULL;
d62a17ae 309 zebra_vni_t *zvni;
310 u_int32_t num_neigh;
311 struct neigh_walk_ctx wctx;
cd233079
CS
312 char vni_str[VNI_STR_LEN];
313
314 vty = (struct vty *)args[0];
315 json = (json_object *)args[1];
cec2e17d 316
d62a17ae 317 zvni = (zebra_vni_t *)backet->data;
cd233079
CS
318 if (!zvni) {
319 if (json)
320 vty_out(vty, "{}\n");
d62a17ae 321 return;
cd233079 322 }
d62a17ae 323 num_neigh = hashcount(zvni->neigh_table);
cd233079
CS
324 if (json == NULL)
325 vty_out(vty,
326 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
327 zvni->vni, num_neigh);
328 else {
329 json_vni = json_object_new_object();
330 json_object_int_add(json_vni, "numArpNd", num_neigh);
331 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
332 }
333 if (!num_neigh) {
334 if (json)
335 json_object_object_add(json, vni_str, json_vni);
d62a17ae 336 return;
cd233079 337 }
cec2e17d 338
d62a17ae 339 /* Since we have IPv6 addresses to deal with which can vary widely in
340 * size, we try to be a bit more elegant in display by first computing
341 * the maximum width.
342 */
343 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
344 wctx.zvni = zvni;
345 wctx.vty = vty;
346 wctx.addr_width = 15;
cd233079 347 wctx.json = json_vni;
d62a17ae 348 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
cec2e17d 349
cd233079
CS
350 if (json == NULL)
351 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
352 "Type", "MAC", "Remote VTEP");
d62a17ae 353 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
354
355 if (json)
356 json_object_object_add(json, vni_str, json_vni);
cec2e17d 357}
358
359/*
360 * Print a specific MAC entry.
361 */
d62a17ae 362static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
363{
364 struct vty *vty;
b6938a74
MK
365 zebra_neigh_t *n = NULL;
366 struct listnode *node = NULL;
d62a17ae 367 char buf1[20];
b6938a74 368 char buf2[INET6_ADDRSTRLEN];
d62a17ae 369
370 vty = (struct vty *)ctxt;
371 vty_out(vty, "MAC: %s",
372 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)));
373 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
374 struct zebra_ns *zns;
375 struct interface *ifp;
376 ifindex_t ifindex;
377
378 ifindex = mac->fwd_info.local.ifindex;
379 zns = zebra_ns_lookup(NS_DEFAULT);
380 ifp = if_lookup_by_index_per_ns(zns, ifindex);
381 if (!ifp) // unexpected
382 return;
383 vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex);
384 if (mac->fwd_info.local.vid)
385 vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid);
b6938a74 386 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
d62a17ae 387 vty_out(vty, " Remote VTEP: %s",
388 inet_ntoa(mac->fwd_info.r_vtep_ip));
b6938a74
MK
389 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
390 vty_out(vty, " Auto Mac ");
391 }
b6938a74 392
0a97666d 393 vty_out(vty, "\n");
b6938a74
MK
394 /* print all the associated neigh */
395 vty_out(vty, " Neighbors:\n");
396 if (!listcount(mac->neigh_list))
397 vty_out(vty, " No Neighbors\n");
398 else {
399 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
400 vty_out(vty, " %s %s\n",
401 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
402 CHECK_FLAG(n->flags, ZEBRA_MAC_LOCAL)
403 ? (IS_ZEBRA_NEIGH_ACTIVE(n)
404 ? "Active"
405 : "Inactive")
406 : "");
407 }
d62a17ae 408 }
b6938a74 409
d62a17ae 410 vty_out(vty, "\n");
cec2e17d 411}
412
413/*
414 * Print MAC hash entry - called for display of all MACs.
415 */
d62a17ae 416static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt)
417{
418 struct vty *vty;
cd233079 419 json_object *json_mac_hdr = NULL, *json_mac = NULL;
d62a17ae 420 zebra_mac_t *mac;
421 char buf1[20];
422 struct mac_walk_ctx *wctx = ctxt;
423
424 vty = wctx->vty;
cd233079 425 json_mac_hdr = wctx->json;
d62a17ae 426 mac = (zebra_mac_t *)backet->data;
427 if (!mac)
428 return;
429
430 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
cd233079
CS
431
432 if (json_mac_hdr)
433 json_mac = json_object_new_object();
434
d62a17ae 435 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
436 && !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) {
437 struct zebra_ns *zns;
438 ifindex_t ifindex;
439 struct interface *ifp;
440 vlanid_t vid;
441
442 zns = zebra_ns_lookup(NS_DEFAULT);
443 ifindex = mac->fwd_info.local.ifindex;
444 ifp = if_lookup_by_index_per_ns(zns, ifindex);
445 if (!ifp) // unexpected
446 return;
447 vid = mac->fwd_info.local.vid;
cd233079
CS
448 if (json_mac_hdr == NULL)
449 vty_out(vty, "%-17s %-6s %-21s", buf1, "local",
450 ifp->name);
451 else {
452 json_object_string_add(json_mac, "type", "local");
453 json_object_string_add(json_mac, "intf", ifp->name);
454 }
455 if (vid) {
456 if (json_mac_hdr == NULL)
457 vty_out(vty, " %-5u", vid);
458 else
459 json_object_int_add(json_mac, "vlan", vid);
460 }
461 if (json_mac_hdr == NULL)
462 vty_out(vty, "\n");
463 else
464 json_object_object_add(json_mac_hdr, buf1, json_mac);
d62a17ae 465 wctx->count++;
b6938a74 466 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
d62a17ae 467 if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) {
468 if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
469 &wctx->r_vtep_ip)) {
470 if (wctx->count == 0) {
cd233079
CS
471 if (json_mac_hdr == NULL) {
472 vty_out(vty, "\nVNI %u\n\n",
473 wctx->zvni->vni);
474 vty_out(vty,
475 "%-17s %-6s %-21s %-5s\n",
476 "MAC", "Type",
477 "Intf/Remote VTEP",
478 "VLAN");
479 }
480 }
481 if (json_mac_hdr == NULL)
482 vty_out(vty, "%-17s %-6s %-21s\n", buf1,
483 "remote",
484 inet_ntoa(mac->fwd_info
485 .r_vtep_ip));
486 else {
487 json_object_string_add(json_mac, "type",
488 "remote");
489 json_object_string_add(
490 json_mac, "remoteVtep",
491 inet_ntoa(mac->fwd_info
492 .r_vtep_ip));
493 json_object_object_add(json_mac_hdr,
494 buf1, json_mac);
d62a17ae 495 }
d62a17ae 496 wctx->count++;
497 }
498 } else {
cd233079
CS
499 if (json_mac_hdr == NULL)
500 vty_out(vty, "%-17s %-6s %-21s\n", buf1,
501 "remote",
502 inet_ntoa(mac->fwd_info.r_vtep_ip));
503 else {
504 json_object_string_add(json_mac, "type",
505 "remote");
506 json_object_string_add(
507 json_mac, "remoteVtep",
508 inet_ntoa(mac->fwd_info.r_vtep_ip));
509 json_object_object_add(json_mac_hdr, buf1,
510 json_mac);
511 }
d62a17ae 512 wctx->count++;
513 }
514 }
cec2e17d 515}
516
517/*
518 * Print MACs for all VNI.
519 */
d62a17ae 520static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
cec2e17d 521{
d62a17ae 522 struct vty *vty;
cd233079
CS
523 json_object *json = NULL, *json_vni = NULL;
524 json_object *json_mac = NULL;
d62a17ae 525 zebra_vni_t *zvni;
526 u_int32_t num_macs;
527 struct mac_walk_ctx *wctx = ctxt;
cd233079 528 char vni_str[VNI_STR_LEN];
cec2e17d 529
d62a17ae 530 vty = (struct vty *)wctx->vty;
cd233079 531 json = (struct json_object *)wctx->json;
cec2e17d 532
d62a17ae 533 zvni = (zebra_vni_t *)backet->data;
cd233079
CS
534 if (!zvni) {
535 if (json)
536 vty_out(vty, "{}\n");
d62a17ae 537 return;
cd233079 538 }
d62a17ae 539 wctx->zvni = zvni;
cec2e17d 540
d62a17ae 541 /*We are iterating over a new VNI, set the count to 0*/
542 wctx->count = 0;
cec2e17d 543
d62a17ae 544 num_macs = hashcount(zvni->mac_table);
545 if (!num_macs)
546 return;
cd233079
CS
547
548 if (json) {
549 json_vni = json_object_new_object();
550 json_mac = json_object_new_object();
551 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
d62a17ae 552 }
cec2e17d 553
cd233079
CS
554 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
555 if (json == NULL) {
556 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
557 zvni->vni, num_macs);
558 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
559 "Intf/Remote VTEP", "VLAN");
560 } else
561 json_object_int_add(json_vni, "numMacs", num_macs);
562 }
563 /* assign per-vni to wctx->json object to fill macs
564 * under the vni. Re-assign primary json object to fill
565 * next vni information.
566 */
567 wctx->json = json_mac;
d62a17ae 568 hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
cd233079
CS
569 wctx->json = json;
570 if (json) {
571 if (wctx->count)
572 json_object_object_add(json_vni, "macs", json_mac);
573 json_object_object_add(json, vni_str, json_vni);
574 }
cec2e17d 575}
576
577/*
578 * Print a specific VNI entry.
579 */
cd233079 580static void zvni_print(zebra_vni_t *zvni, void **ctxt)
d62a17ae 581{
582 struct vty *vty;
583 zebra_vtep_t *zvtep;
584 u_int32_t num_macs;
585 u_int32_t num_neigh;
cd233079
CS
586 json_object *json = NULL;
587 json_object *json_vtep_list = NULL;
588 json_object *json_ip_str = NULL;
d62a17ae 589
cd233079
CS
590 vty = ctxt[0];
591 json = ctxt[1];
592
593 if (json == NULL)
594 vty_out(vty, "VNI: %u\n", zvni->vni);
595 else
596 json_object_int_add(json, "vni", zvni->vni);
d62a17ae 597
d62a17ae 598 if (!zvni->vxlan_if) { // unexpected
cd233079
CS
599 if (json == NULL)
600 vty_out(vty, " VxLAN interface: unknown\n");
d62a17ae 601 return;
602 }
cd233079
CS
603 num_macs = hashcount(zvni->mac_table);
604 num_neigh = hashcount(zvni->neigh_table);
605 if (json == NULL)
606 vty_out(vty, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n",
607 zvni->vxlan_if->name, zvni->vxlan_if->ifindex,
608 inet_ntoa(zvni->local_vtep_ip));
609 else {
610 json_object_string_add(json, "vxlanInterface",
611 zvni->vxlan_if->name);
612 json_object_int_add(json, "ifindex", zvni->vxlan_if->ifindex);
613 json_object_string_add(json, "vtepIp",
614 inet_ntoa(zvni->local_vtep_ip));
ddd16ed5
MK
615 json_object_string_add(json, "advertiseGatewayMacip",
616 zvni->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
617 json_object_int_add(json, "numMacs", num_macs);
618 json_object_int_add(json, "numArpNd", num_neigh);
619 }
d62a17ae 620 if (!zvni->vteps) {
cd233079
CS
621 if (json == NULL)
622 vty_out(vty, " No remote VTEPs known for this VNI\n");
d62a17ae 623 } else {
cd233079
CS
624 if (json == NULL)
625 vty_out(vty, " Remote VTEPs for this VNI:\n");
626 else
627 json_vtep_list = json_object_new_array();
628 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
629 if (json == NULL)
630 vty_out(vty, " %s\n",
631 inet_ntoa(zvtep->vtep_ip));
632 else {
633 json_ip_str = json_object_new_string(
634 inet_ntoa(zvtep->vtep_ip));
635 json_object_array_add(json_vtep_list,
636 json_ip_str);
637 }
638 }
639 if (json)
640 json_object_object_add(json, "numRemoteVteps",
641 json_vtep_list);
642 }
643 if (json == NULL) {
644 vty_out(vty,
645 " Number of MACs (local and remote) known for this VNI: %u\n",
646 num_macs);
647 vty_out(vty,
648 " Number of ARPs (IPv4 and IPv6, local and remote) "
649 "known for this VNI: %u\n",
650 num_neigh);
ddd16ed5
MK
651 vty_out(vty, " Advertise-gw-macip: %s\n",
652 zvni->advertise_gw_macip ? "Yes" : "No");
d62a17ae 653 }
cec2e17d 654}
655
656/*
657 * Print a VNI hash entry - called for display of all VNIs.
658 */
cd233079 659static void zvni_print_hash(struct hash_backet *backet, void *ctxt[])
cec2e17d 660{
d62a17ae 661 struct vty *vty;
662 zebra_vni_t *zvni;
663 zebra_vtep_t *zvtep;
664 u_int32_t num_vteps = 0;
665 u_int32_t num_macs = 0;
666 u_int32_t num_neigh = 0;
cd233079
CS
667 json_object *json = NULL;
668 json_object *json_vni = NULL;
669 json_object *json_ip_str = NULL;
670 json_object *json_vtep_list = NULL;
671
672 vty = ctxt[0];
673 json = ctxt[1];
cec2e17d 674
d62a17ae 675 zvni = (zebra_vni_t *)backet->data;
676 if (!zvni)
677 return;
cec2e17d 678
d62a17ae 679 zvtep = zvni->vteps;
680 while (zvtep) {
681 num_vteps++;
682 zvtep = zvtep->next;
683 }
cec2e17d 684
d62a17ae 685 num_macs = hashcount(zvni->mac_table);
686 num_neigh = hashcount(zvni->neigh_table);
cd233079
CS
687 if (json == NULL)
688 vty_out(vty, "%-10u %-21s %-15s %-8u %-8u %-15u\n", zvni->vni,
689 zvni->vxlan_if ? zvni->vxlan_if->name : "unknown",
690 inet_ntoa(zvni->local_vtep_ip), num_macs, num_neigh,
691 num_vteps);
692 else {
693 char vni_str[VNI_STR_LEN];
694 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
695 json_vni = json_object_new_object();
696 json_object_string_add(json_vni, "vxlanIf",
697 zvni->vxlan_if ? zvni->vxlan_if->name
698 : "unknown");
699 json_object_string_add(json_vni, "vtepIp",
700 inet_ntoa(zvni->local_vtep_ip));
701 json_object_int_add(json_vni, "numMacs", num_macs);
702 json_object_int_add(json_vni, "numArpNd", num_neigh);
703 json_object_int_add(json_vni, "numRemoteVteps", num_vteps);
704 if (num_vteps) {
705 json_vtep_list = json_object_new_array();
706 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
707 json_ip_str = json_object_new_string(
708 inet_ntoa(zvtep->vtep_ip));
709 json_object_array_add(json_vtep_list,
710 json_ip_str);
711 }
712 json_object_object_add(json_vni, "remoteVteps",
713 json_vtep_list);
714 }
715 json_object_object_add(json, vni_str, json_vni);
716 }
cec2e17d 717}
718
13d60d35 719/*
2232a77c 720 * Inform BGP about local MACIP.
721 */
d62a17ae 722static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
723 struct ethaddr *macaddr,
1a98c087 724 struct ipaddr *ip, u_char flags,
d62a17ae 725 u_int16_t cmd)
726{
727 struct zserv *client;
728 struct stream *s;
729 int ipa_len;
730 char buf[ETHER_ADDR_STRLEN];
731 char buf2[INET6_ADDRSTRLEN];
732
733 client = zebra_find_client(ZEBRA_ROUTE_BGP);
734 /* BGP may not be running. */
735 if (!client)
736 return 0;
737
738 s = client->obuf;
739 stream_reset(s);
740
741 zserv_create_header(s, cmd, zvrf_id(zvrf));
742 stream_putl(s, vni);
ff8b7eb8 743 stream_put(s, macaddr->octet, ETH_ALEN);
d62a17ae 744 if (ip) {
745 ipa_len = 0;
746 if (IS_IPADDR_V4(ip))
747 ipa_len = IPV4_MAX_BYTELEN;
748 else if (IS_IPADDR_V6(ip))
749 ipa_len = IPV6_MAX_BYTELEN;
750
751 stream_putl(s, ipa_len); /* IP address length */
752 if (ipa_len)
753 stream_put(s, &ip->ip.addr, ipa_len); /* IP address */
754 } else
755 stream_putl(s, 0); /* Just MAC. */
756
1a98c087 757 stream_putc(s, flags); /* sticky mac/gateway mac */
d62a17ae 758
759 /* Write packet size. */
760 stream_putw_at(s, 0, stream_get_endp(s));
761
762 if (IS_ZEBRA_DEBUG_VXLAN)
1a98c087
MK
763 zlog_debug(
764 "%u:Send MACIP %s flags 0x%x MAC %s IP %s VNI %u to %s",
765 zvrf_id(zvrf), (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
766 flags, prefix_mac2str(macaddr, buf, sizeof(buf)),
767 ipaddr2str(ip, buf2, sizeof(buf2)), vni,
768 zebra_route_string(client->proto));
d62a17ae 769
770 if (cmd == ZEBRA_MACIP_ADD)
771 client->macipadd_cnt++;
772 else
773 client->macipdel_cnt++;
774
775 return zebra_server_send_message(client);
2232a77c 776}
777
778/*
779 * Make hash key for neighbors.
13d60d35 780 */
d62a17ae 781static unsigned int neigh_hash_keymake(void *p)
13d60d35 782{
d62a17ae 783 zebra_neigh_t *n = p;
784 struct ipaddr *ip = &n->ip;
13d60d35 785
d62a17ae 786 if (IS_IPADDR_V4(ip))
787 return jhash_1word(ip->ipaddr_v4.s_addr, 0);
2232a77c 788
d62a17ae 789 return jhash2(ip->ipaddr_v6.s6_addr32,
790 ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0);
13d60d35 791}
792
793/*
2232a77c 794 * Compare two neighbor hash structures.
13d60d35 795 */
d62a17ae 796static int neigh_cmp(const void *p1, const void *p2)
13d60d35 797{
d62a17ae 798 const zebra_neigh_t *n1 = p1;
799 const zebra_neigh_t *n2 = p2;
13d60d35 800
d62a17ae 801 if (n1 == NULL && n2 == NULL)
802 return 1;
2232a77c 803
d62a17ae 804 if (n1 == NULL || n2 == NULL)
805 return 0;
2232a77c 806
d62a17ae 807 return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0);
13d60d35 808}
809
810/*
2232a77c 811 * Callback to allocate neighbor hash entry.
13d60d35 812 */
d62a17ae 813static void *zvni_neigh_alloc(void *p)
13d60d35 814{
d62a17ae 815 const zebra_neigh_t *tmp_n = p;
816 zebra_neigh_t *n;
13d60d35 817
d62a17ae 818 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
819 *n = *tmp_n;
2232a77c 820
d62a17ae 821 return ((void *)n);
13d60d35 822}
823
824/*
2232a77c 825 * Add neighbor entry.
13d60d35 826 */
b6938a74
MK
827static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
828 struct ethaddr *mac)
13d60d35 829{
d62a17ae 830 zebra_neigh_t tmp_n;
831 zebra_neigh_t *n = NULL;
b6938a74 832 zebra_mac_t *zmac = NULL;
13d60d35 833
d62a17ae 834 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
835 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
836 n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
837 assert(n);
13d60d35 838
b6938a74
MK
839 memcpy(&n->emac, mac, ETH_ALEN);
840 n->state = ZEBRA_NEIGH_INACTIVE;
841
842 /* Associate the neigh to mac */
843 zmac = zvni_mac_lookup(zvni, mac);
844 if (zmac)
845 listnode_add_sort(zmac->neigh_list, n);
846
d62a17ae 847 return n;
13d60d35 848}
849
850/*
2232a77c 851 * Delete neighbor entry.
13d60d35 852 */
d62a17ae 853static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
13d60d35 854{
d62a17ae 855 zebra_neigh_t *tmp_n;
b6938a74
MK
856 zebra_mac_t *zmac = NULL;
857
858 zmac = zvni_mac_lookup(zvni, &n->emac);
859 if (zmac)
860 listnode_delete(zmac->neigh_list, n);
13d60d35 861
d62a17ae 862 /* Free the VNI hash entry and allocated memory. */
863 tmp_n = hash_release(zvni->neigh_table, n);
864 if (tmp_n)
865 XFREE(MTYPE_NEIGH, tmp_n);
13d60d35 866
d62a17ae 867 return 0;
13d60d35 868}
869
870/*
2232a77c 871 * Free neighbor hash entry (callback)
13d60d35 872 */
d62a17ae 873static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg)
13d60d35 874{
d62a17ae 875 struct neigh_walk_ctx *wctx = arg;
876 zebra_neigh_t *n = backet->data;
2232a77c 877
d62a17ae 878 if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL))
879 || ((wctx->flags & DEL_REMOTE_NEIGH)
880 && (n->flags & ZEBRA_NEIGH_REMOTE))
881 || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP)
882 && (n->flags & ZEBRA_NEIGH_REMOTE)
883 && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
884 if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
1a98c087
MK
885 zvni_neigh_send_del_to_client(wctx->zvrf,
886 wctx->zvni->vni, &n->ip,
887 &n->emac, 0);
13d60d35 888
d62a17ae 889 if (wctx->uninstall)
890 zvni_neigh_uninstall(wctx->zvni, n);
13d60d35 891
d62a17ae 892 return zvni_neigh_del(wctx->zvni, n);
893 }
13d60d35 894
d62a17ae 895 return 0;
13d60d35 896}
897
898/*
2232a77c 899 * Delete all neighbor entries from specific VTEP for a particular VNI.
13d60d35 900 */
d62a17ae 901static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
902 struct in_addr *r_vtep_ip)
13d60d35 903{
d62a17ae 904 struct neigh_walk_ctx wctx;
13d60d35 905
d62a17ae 906 if (!zvni->neigh_table)
907 return;
13d60d35 908
d62a17ae 909 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
910 wctx.zvni = zvni;
911 wctx.uninstall = uninstall;
912 wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP;
913 wctx.r_vtep_ip = *r_vtep_ip;
13d60d35 914
d62a17ae 915 hash_iterate(zvni->neigh_table,
916 (void (*)(struct hash_backet *,
917 void *))zvni_neigh_del_hash_entry,
918 &wctx);
2232a77c 919}
13d60d35 920
2232a77c 921/*
922 * Delete all neighbor entries for this VNI.
923 */
d62a17ae 924static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
925 int uninstall, int upd_client, u_int32_t flags)
2232a77c 926{
d62a17ae 927 struct neigh_walk_ctx wctx;
13d60d35 928
d62a17ae 929 if (!zvni->neigh_table)
930 return;
13d60d35 931
d62a17ae 932 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
933 wctx.zvni = zvni;
934 wctx.zvrf = zvrf;
935 wctx.uninstall = uninstall;
936 wctx.upd_client = upd_client;
937 wctx.flags = flags;
2232a77c 938
d62a17ae 939 hash_iterate(zvni->neigh_table,
940 (void (*)(struct hash_backet *,
941 void *))zvni_neigh_del_hash_entry,
942 &wctx);
13d60d35 943}
944
945/*
2232a77c 946 * Look up neighbor hash entry.
947 */
d62a17ae 948static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip)
2232a77c 949{
d62a17ae 950 zebra_neigh_t tmp;
951 zebra_neigh_t *n;
2232a77c 952
d62a17ae 953 memset(&tmp, 0, sizeof(tmp));
954 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
955 n = hash_lookup(zvni->neigh_table, &tmp);
2232a77c 956
d62a17ae 957 return n;
2232a77c 958}
959
b6938a74
MK
960/* Process all neigh associated to a mac upon local mac add event */
961static void zvni_process_neigh_on_local_mac_add(struct zebra_vrf *zvrf,
962 zebra_vni_t *zvni,
963 zebra_mac_t *zmac)
964{
965 zebra_neigh_t *n = NULL;
966 struct listnode *node = NULL;
967 char buf[ETHER_ADDR_STRLEN];
968 char buf2[INET6_ADDRSTRLEN];
969
970 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
971 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
972 /* MAC is learnt locally, program all inactive neigh
973 * pointing to this mac */
974 if (IS_ZEBRA_NEIGH_INACTIVE(n)) {
975 if (IS_ZEBRA_DEBUG_VXLAN)
976 zlog_debug(
977 "%u: neigh %s (MAC %s) on VNI %u is now ACTIVE",
978 zvrf_id(zvrf),
979 ipaddr2str(&n->ip, buf2,
980 sizeof(buf2)),
981 prefix_mac2str(&n->emac, buf,
982 sizeof(buf)),
983 zvni->vni);
984
985 ZEBRA_NEIGH_SET_ACTIVE(n);
986 zvni_neigh_send_add_to_client(
987 zvrf, zvni->vni, &n->ip, &n->emac, 0);
988 } else {
989 if (IS_ZEBRA_DEBUG_VXLAN)
990 zlog_debug(
991 "%u: neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
992 zvrf_id(zvrf),
993 ipaddr2str(&n->ip, buf2,
994 sizeof(buf2)),
995 prefix_mac2str(&n->emac, buf,
996 sizeof(buf)),
997 zvni->vni);
998 }
999 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1000 /* TODO: assume the neigh has moved too ?? */
1001 }
1002 }
1003}
1004
1005/* Process all neigh associated to a mac upon local mac del event */
1006static void zvni_process_neigh_on_local_mac_del(struct zebra_vrf *zvrf,
1007 zebra_vni_t *zvni,
1008 zebra_mac_t *zmac)
1009{
1010 zebra_neigh_t *n = NULL;
1011 struct listnode *node = NULL;
1012 char buf[ETHER_ADDR_STRLEN];
1013 char buf2[INET6_ADDRSTRLEN];
1014
1015 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1016 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1017 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
1018 if (IS_ZEBRA_DEBUG_VXLAN)
1019 zlog_debug(
1020 "%u: neigh %s (MAC %s) on VNI %u is now INACTIVE",
1021 zvrf_id(zvrf),
1022 ipaddr2str(&n->ip, buf2,
1023 sizeof(buf2)),
1024 prefix_mac2str(&n->emac, buf,
1025 sizeof(buf)),
1026 zvni->vni);
1027
1028 ZEBRA_NEIGH_SET_INACTIVE(n);
1029 zvni_neigh_send_del_to_client(
1030 zvrf, zvni->vni, &n->ip, &n->emac, 0);
1031 }
1032 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1033 if (IS_ZEBRA_DEBUG_VXLAN)
1034 zlog_err(
1035 "%u: local MAC %s getting deleted on VNI %u has remote neigh %s",
1036 zvrf_id(zvrf),
1037 prefix_mac2str(&n->emac, buf,
1038 sizeof(buf)),
1039 zvni->vni,
1040 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1041 }
1042 }
1043}
1044
1045/* process all neigh associated to a mac entry upon remote mac add */
1046static void zvni_process_neigh_on_remote_mac_add(struct zebra_vrf *zvrf,
1047 zebra_vni_t *zvni,
1048 zebra_mac_t *zmac)
1049{
1050 zebra_neigh_t *n = NULL;
1051 struct listnode *node = NULL;
1052 char buf[ETHER_ADDR_STRLEN];
1053 char buf2[INET6_ADDRSTRLEN];
1054
1055 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1056 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1057 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
1058 if (IS_ZEBRA_DEBUG_VXLAN)
1059 zlog_debug(
1060 "%u: neigh %s (MAC %s) on VNI %u INACTIVE",
1061 zvrf_id(zvrf),
1062 ipaddr2str(&n->ip, buf2,
1063 sizeof(buf2)),
1064 prefix_mac2str(&n->emac, buf,
1065 sizeof(buf)),
1066 zvni->vni);
1067
1068 ZEBRA_NEIGH_SET_INACTIVE(n);
1069 zvni_neigh_send_del_to_client(
1070 zvrf, zvni->vni, &n->ip, &n->emac, 0);
1071 }
1072 }
1073 }
1074}
1075
1076/* process all neigh associated to mac entry upon remote mac del */
1077static void zvni_process_neigh_on_remote_mac_del(struct zebra_vrf *zvrf,
1078 zebra_vni_t *zvni,
1079 zebra_mac_t *zmac)
1080{
1081 zebra_neigh_t *n = NULL;
1082 struct listnode *node = NULL;
1083 char buf[ETHER_ADDR_STRLEN];
1084 char buf2[INET6_ADDRSTRLEN];
1085
1086 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1087 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1088 if (IS_ZEBRA_DEBUG_VXLAN)
1089 zlog_err(
1090 "%u: remote MAC %s getting deleted on VNI %u has local neigh %s",
1091 zvrf_id(zvrf),
1092 prefix_mac2str(&n->emac, buf,
1093 sizeof(buf)),
1094 zvni->vni,
1095 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1096 }
1097 }
1098}
1099
2232a77c 1100/*
1101 * Inform BGP about local neighbor addition.
13d60d35 1102 */
d62a17ae 1103static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
1104 struct ipaddr *ip,
1a98c087 1105 struct ethaddr *macaddr, u_char flags)
13d60d35 1106{
1a98c087 1107 return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, flags,
d62a17ae 1108 ZEBRA_MACIP_ADD);
2232a77c 1109}
13d60d35 1110
2232a77c 1111/*
1112 * Inform BGP about local neighbor deletion.
1113 */
d62a17ae 1114static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
1115 struct ipaddr *ip,
1a98c087 1116 struct ethaddr *macaddr, u_char flags)
2232a77c 1117{
1a98c087 1118 return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, flags,
d62a17ae 1119 ZEBRA_MACIP_DEL);
2232a77c 1120}
1121
1122/*
1123 * Install remote neighbor into the kernel.
1124 */
d62a17ae 1125static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
2232a77c 1126{
d62a17ae 1127 struct zebra_vrf *zvrf;
1128 struct zebra_if *zif;
1129 struct zebra_l2info_vxlan *vxl;
1130 struct interface *vlan_if;
2232a77c 1131
d62a17ae 1132 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
1133 return 0;
13d60d35 1134
d62a17ae 1135 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
1136 assert(zvrf);
1137 zif = zvni->vxlan_if->info;
1138 if (!zif)
1139 return -1;
1140 vxl = &zif->l2info.vxl;
13d60d35 1141
d62a17ae 1142 vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan,
1143 zif->brslave_info.br_if);
1144 if (!vlan_if)
1145 return -1;
13d60d35 1146
d62a17ae 1147 return kernel_add_neigh(vlan_if, &n->ip, &n->emac);
2232a77c 1148}
13d60d35 1149
2232a77c 1150/*
1151 * Uninstall remote neighbor from the kernel.
1152 */
d62a17ae 1153static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
2232a77c 1154{
d62a17ae 1155 struct zebra_vrf *zvrf;
1156 struct zebra_if *zif;
1157 struct zebra_l2info_vxlan *vxl;
1158 struct interface *vlan_if;
13d60d35 1159
d62a17ae 1160 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
1161 return 0;
2232a77c 1162
d62a17ae 1163 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
1164 assert(zvrf);
1165 if (!zvni->vxlan_if) {
1166 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1167 zvni->vni, zvni);
1168 return -1;
1169 }
2232a77c 1170
d62a17ae 1171 zif = zvni->vxlan_if->info;
1172 if (!zif)
1173 return -1;
1174 vxl = &zif->l2info.vxl;
1175 vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan,
1176 zif->brslave_info.br_if);
1177 if (!vlan_if)
1178 return -1;
2232a77c 1179
d62a17ae 1180 return kernel_del_neigh(vlan_if, &n->ip);
13d60d35 1181}
1182
1183/*
2232a77c 1184 * Install neighbor hash entry - called upon access VLAN change.
13d60d35 1185 */
d62a17ae 1186static void zvni_install_neigh_hash(struct hash_backet *backet, void *ctxt)
13d60d35 1187{
d62a17ae 1188 zebra_neigh_t *n;
1189 struct neigh_walk_ctx *wctx = ctxt;
13d60d35 1190
d62a17ae 1191 n = (zebra_neigh_t *)backet->data;
1192 if (!n)
1193 return;
13d60d35 1194
d62a17ae 1195 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
1196 zvni_neigh_install(wctx->zvni, n);
2232a77c 1197}
13d60d35 1198
1a98c087
MK
1199/* Get the VRR interface for SVI if any */
1200struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp)
1201{
1202 struct zebra_vrf *zvrf = NULL;
1203 struct interface *tmp_if = NULL;
1204 struct zebra_if *zif = NULL;
1205 struct listnode *node;
1206
1207 zvrf = vrf_info_lookup(ifp->vrf_id);
1208 assert(zvrf);
1209
1210 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
1211 zif = tmp_if->info;
1212 if (!zif)
1213 continue;
1214
1215 if (!IS_ZEBRA_IF_MACVLAN(tmp_if))
1216 continue;
1217
1218 if (zif->link == ifp)
1219 return tmp_if;
1220 }
1221
1222 return NULL;
1223}
1224
1225static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
1226{
1227 struct zebra_vrf *zvrf = NULL;
1228 struct listnode *cnode = NULL, *cnnode = NULL;
1229 struct connected *c = NULL;
1230 struct ethaddr macaddr;
1231
1232 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
1233 if (!zvrf)
1234 return -1;
1235
1236 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
1237
1238 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
1239 struct ipaddr ip;
1240
1241 memset(&ip, 0, sizeof(struct ipaddr));
1242 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
1243 continue;
1244
1245 if (c->address->family == AF_INET) {
1246 ip.ipa_type = IPADDR_V4;
1247 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
1248 sizeof(struct in_addr));
1249 } else if (c->address->family == AF_INET6) {
1250 ip.ipa_type = IPADDR_V6;
1251 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
1252 sizeof(struct in6_addr));
1253 } else {
1254 continue;
1255 }
1256
1257 zvni_gw_macip_del(ifp, zvni, &ip);
1258 }
1259
1260 return 0;
1261}
1262
1263static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
1264{
1265 struct zebra_vrf *zvrf = NULL;
1266 struct listnode *cnode = NULL, *cnnode = NULL;
1267 struct connected *c = NULL;
1268 struct ethaddr macaddr;
1269
1270 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
1271 if (!zvrf)
1272 return -1;
1273
1274 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
1275
1276 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
1277 struct ipaddr ip;
1278
1279 memset(&ip, 0, sizeof(struct ipaddr));
1280 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
1281 continue;
1282
1283 if (c->address->family == AF_INET) {
1284 ip.ipa_type = IPADDR_V4;
1285 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
1286 sizeof(struct in_addr));
1287 } else if (c->address->family == AF_INET6) {
1288 ip.ipa_type = IPADDR_V6;
1289 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
1290 sizeof(struct in6_addr));
1291 } else {
1292 continue;
1293 }
1294
1295 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
1296 }
1297
1298 return 0;
1299}
1300
1301/*
1302 * zvni_gw_macip_add_to_client
1303 */
1304static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
1305 struct ethaddr *macaddr, struct ipaddr *ip)
1306{
1307 struct zebra_vrf *zvrf = NULL;
1308 struct zebra_if *zif = NULL;
1309 struct zebra_l2info_vxlan *vxl = NULL;
1310 zebra_neigh_t *n = NULL;
1311 zebra_mac_t *mac = NULL;
1312 char buf[ETHER_ADDR_STRLEN];
1313 char buf2[INET6_ADDRSTRLEN];
1314
1315 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
1316 if (!zvrf)
1317 return -1;
1318
1319 zif = zvni->vxlan_if->info;
1320 if (!zif)
1321 return -1;
1322
1323 vxl = &zif->l2info.vxl;
1324
1325 mac = zvni_mac_lookup(zvni, macaddr);
1326 if (!mac) {
1327 mac = zvni_mac_add(zvni, macaddr);
1328 if (!mac) {
1329 zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u",
1330 ifp->vrf_id,
1331 prefix_mac2str(macaddr, buf, sizeof(buf)),
1332 ifp->name, ifp->ifindex, vxl->access_vlan);
1333 return -1;
1334 }
1335 }
1336
1337 /* Set "local" forwarding info. */
1338 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
1339 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
1340 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
1341 mac->fwd_info.local.ifindex = ifp->ifindex;
1342 mac->fwd_info.local.vid = vxl->access_vlan;
1343
1344 n = zvni_neigh_lookup(zvni, ip);
1345 if (!n) {
b6938a74 1346 n = zvni_neigh_add(zvni, ip, macaddr);
1a98c087
MK
1347 if (!n) {
1348 zlog_err(
1349 "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1350 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
1351 prefix_mac2str(macaddr, NULL,
1352 ETHER_ADDR_STRLEN),
1353 ifp->name, ifp->ifindex, zvni->vni);
1354 return -1;
1355 }
1356 }
1357
1358 /* Set "local" forwarding info. */
1359 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
1360 memcpy(&n->emac, macaddr, ETH_ALEN);
1361 n->ifindex = ifp->ifindex;
1362
1a98c087
MK
1363 if (IS_ZEBRA_DEBUG_VXLAN)
1364 zlog_debug(
1365 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP",
1366 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
1367 prefix_mac2str(macaddr, NULL, ETHER_ADDR_STRLEN),
1368 ipaddr2str(ip, buf2, sizeof(buf2)));
1369
1370 zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr,
1371 ZEBRA_MAC_TYPE_GW);
1372
1373 return 0;
1374}
1375
1376/*
1377 * zvni_gw_macip_del_from_client
1378 */
1379static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
1380 struct ipaddr *ip)
1381{
1382 struct zebra_vrf *zvrf = NULL;
1383 zebra_neigh_t *n = NULL;
1384 zebra_mac_t *mac = NULL;
1385 char buf2[INET6_ADDRSTRLEN];
1386
1387 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
1388 if (!zvrf)
1389 return -1;
1390
1391 /* If the neigh entry is not present nothing to do*/
1392 n = zvni_neigh_lookup(zvni, ip);
1393 if (!n)
1394 return 0;
1395
1396 /* mac entry should be present */
1397 mac = zvni_mac_lookup(zvni, &n->emac);
1398 if (!mac)
1399 zlog_err("%u: MAC %s doesnt exsists for neigh %s on VNI %u",
1400 ifp->vrf_id,
1401 prefix_mac2str(&n->emac, NULL, ETHER_ADDR_STRLEN),
1402 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
1403
1404 /* If the entry is not local nothing to do*/
1405 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
1406 return -1;
1407
1408 if (IS_ZEBRA_DEBUG_VXLAN)
1409 zlog_debug(
1410 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1411 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
1412 prefix_mac2str(&(n->emac), NULL, ETHER_ADDR_STRLEN),
1413 ipaddr2str(ip, buf2, sizeof(buf2)));
1414
1415 /* Remove neighbor from BGP. */
1416 zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
1417 ZEBRA_MAC_TYPE_GW);
1418
1419 /* Delete this neighbor entry. */
1420 zvni_neigh_del(zvni, n);
1421
1422 /* see if the mac needs to be deleted as well*/
1423 zvni_deref_ip2mac(zvni, mac, 0);
1424
1425 return 0;
1426}
1427
1428static void zvni_gw_macip_del_for_vni_hash(struct hash_backet *backet,
1429 void *zvrf)
1430{
1431 zebra_vni_t *zvni = NULL;
1432 struct zebra_if *zif = NULL;
1433 struct zebra_l2info_vxlan zl2_info;
1434 struct interface *vlan_if = NULL;
1435 struct interface *vrr_if = NULL;
b5ebdc9b 1436 struct interface *ifp;
1a98c087
MK
1437
1438 /* Add primary SVI MAC*/
1439 zvni = (zebra_vni_t *)backet->data;
1440 if (!zvni)
1441 return;
1442
b5ebdc9b 1443 ifp = zvni->vxlan_if;
1444 if (!ifp)
1445 return;
1446 zif = ifp->info;
1447
1448 /* If down or not mapped to a bridge, we're done. */
b682f6de 1449 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 1450 return;
1451
1a98c087
MK
1452 zl2_info = zif->l2info.vxl;
1453
1454 vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
1455 zif->brslave_info.br_if);
1456 if (!vlan_if)
1457 return;
1458
1459 /* Del primary MAC-IP */
1460 zvni_del_macip_for_intf(vlan_if, zvni);
1461
1462 /* Del VRR MAC-IP - if any*/
1463 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
1464 if (vrr_if)
1465 zvni_del_macip_for_intf(vrr_if, zvni);
1466
1467 return;
1468}
1469
1470static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
1471 void *zvrf)
1472{
1473 zebra_vni_t *zvni = NULL;
1474 struct zebra_if *zif = NULL;
1475 struct zebra_l2info_vxlan zl2_info;
1476 struct interface *vlan_if = NULL;
1477 struct interface *vrr_if = NULL;
b5ebdc9b 1478 struct interface *ifp = NULL;
1a98c087
MK
1479
1480 zvni = (zebra_vni_t *)backet->data;
1481 if (!zvni)
1482 return;
1483
1484 if (!advertise_gw_macip_enabled(zvrf, zvni))
1485 return;
1486
b5ebdc9b 1487 ifp = zvni->vxlan_if;
1488 if (!ifp)
1489 return;
1490 zif = ifp->info;
1491
1492 /* If down or not mapped to a bridge, we're done. */
b682f6de 1493 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 1494 return;
1a98c087
MK
1495 zl2_info = zif->l2info.vxl;
1496
1497 vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
1498 zif->brslave_info.br_if);
1499 if (!vlan_if)
1500 return;
1501
1502 if (!advertise_gw_macip_enabled(zvrf, zvni))
1503 return;
1504
1505 /* Add primary SVI MAC-IP */
1506 zvni_add_macip_for_intf(vlan_if, zvni);
1507
1508 /* Add VRR MAC-IP - if any*/
1509 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
1510 if (vrr_if)
1511 zvni_add_macip_for_intf(vrr_if, zvni);
1512
1513 return;
1514}
1515
2232a77c 1516/*
1517 * Make hash key for MAC.
1518 */
d62a17ae 1519static unsigned int mac_hash_keymake(void *p)
2232a77c 1520{
d62a17ae 1521 zebra_mac_t *pmac = p;
25331def
DS
1522 const void *pnt = (void *)pmac->macaddr.octet;
1523
ff8b7eb8 1524 return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
2232a77c 1525}
13d60d35 1526
2232a77c 1527/*
1528 * Compare two MAC addresses.
1529 */
d62a17ae 1530static int mac_cmp(const void *p1, const void *p2)
2232a77c 1531{
d62a17ae 1532 const zebra_mac_t *pmac1 = p1;
1533 const zebra_mac_t *pmac2 = p2;
2232a77c 1534
d62a17ae 1535 if (pmac1 == NULL && pmac2 == NULL)
1536 return 1;
2232a77c 1537
d62a17ae 1538 if (pmac1 == NULL || pmac2 == NULL)
1539 return 0;
2232a77c 1540
d62a17ae 1541 return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet,
ff8b7eb8 1542 ETH_ALEN)
d62a17ae 1543 == 0);
2232a77c 1544}
1545
1546/*
1547 * Callback to allocate MAC hash entry.
1548 */
d62a17ae 1549static void *zvni_mac_alloc(void *p)
2232a77c 1550{
d62a17ae 1551 const zebra_mac_t *tmp_mac = p;
1552 zebra_mac_t *mac;
2232a77c 1553
d62a17ae 1554 mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
1555 *mac = *tmp_mac;
2232a77c 1556
d62a17ae 1557 return ((void *)mac);
2232a77c 1558}
1559
1560/*
1561 * Add MAC entry.
1562 */
d62a17ae 1563static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
2232a77c 1564{
d62a17ae 1565 zebra_mac_t tmp_mac;
1566 zebra_mac_t *mac = NULL;
2232a77c 1567
d62a17ae 1568 memset(&tmp_mac, 0, sizeof(zebra_mac_t));
ff8b7eb8 1569 memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
d62a17ae 1570 mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
1571 assert(mac);
2232a77c 1572
b6938a74
MK
1573 mac->neigh_list = list_new();
1574 mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp;
1575
d62a17ae 1576 return mac;
2232a77c 1577}
1578
1579/*
1580 * Delete MAC entry.
1581 */
d62a17ae 1582static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 1583{
d62a17ae 1584 zebra_mac_t *tmp_mac;
2232a77c 1585
b6938a74
MK
1586 list_delete(mac->neigh_list);
1587
d62a17ae 1588 /* Free the VNI hash entry and allocated memory. */
1589 tmp_mac = hash_release(zvni->mac_table, mac);
1590 if (tmp_mac)
1591 XFREE(MTYPE_MAC, tmp_mac);
2232a77c 1592
d62a17ae 1593 return 0;
2232a77c 1594}
1595
1596/*
1597 * Free MAC hash entry (callback)
1598 */
d62a17ae 1599static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
2232a77c 1600{
d62a17ae 1601 struct mac_walk_ctx *wctx = arg;
1602 zebra_mac_t *mac = backet->data;
1603 u_char sticky = 0;
2232a77c 1604
d62a17ae 1605 if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
1606 || ((wctx->flags & DEL_REMOTE_MAC)
1607 && (mac->flags & ZEBRA_MAC_REMOTE))
1608 || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
1609 && (mac->flags & ZEBRA_MAC_REMOTE)
1610 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
1611 &wctx->r_vtep_ip))) {
1612 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
1613 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1
1614 : 0;
1a98c087
MK
1615 zvni_mac_send_del_to_client(
1616 wctx->zvrf, wctx->zvni->vni, &mac->macaddr,
1617 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
d62a17ae 1618 }
2232a77c 1619
d62a17ae 1620 if (wctx->uninstall)
1621 zvni_mac_uninstall(wctx->zvni, mac, 0);
2232a77c 1622
d62a17ae 1623 return zvni_mac_del(wctx->zvni, mac);
1624 }
2232a77c 1625
d62a17ae 1626 return 0;
2232a77c 1627}
1628
1629/*
1630 * Delete all MAC entries from specific VTEP for a particular VNI.
1631 */
d62a17ae 1632static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
1633 struct in_addr *r_vtep_ip)
2232a77c 1634{
d62a17ae 1635 struct mac_walk_ctx wctx;
2232a77c 1636
d62a17ae 1637 if (!zvni->mac_table)
1638 return;
2232a77c 1639
d62a17ae 1640 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
1641 wctx.zvni = zvni;
1642 wctx.uninstall = uninstall;
1643 wctx.flags = DEL_REMOTE_MAC_FROM_VTEP;
1644 wctx.r_vtep_ip = *r_vtep_ip;
2232a77c 1645
9d303b37
DL
1646 hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *,
1647 void *))zvni_mac_del_hash_entry,
1648 &wctx);
2232a77c 1649}
1650
1651/*
1652 * Delete all MAC entries for this VNI.
1653 */
d62a17ae 1654static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
1655 int uninstall, int upd_client, u_int32_t flags)
2232a77c 1656{
d62a17ae 1657 struct mac_walk_ctx wctx;
2232a77c 1658
d62a17ae 1659 if (!zvni->mac_table)
1660 return;
2232a77c 1661
d62a17ae 1662 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
1663 wctx.zvni = zvni;
1664 wctx.zvrf = zvrf;
1665 wctx.uninstall = uninstall;
1666 wctx.upd_client = upd_client;
1667 wctx.flags = flags;
2232a77c 1668
9d303b37
DL
1669 hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *,
1670 void *))zvni_mac_del_hash_entry,
1671 &wctx);
2232a77c 1672}
1673
1674/*
1675 * Look up MAC hash entry.
1676 */
d62a17ae 1677static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
2232a77c 1678{
d62a17ae 1679 zebra_mac_t tmp;
1680 zebra_mac_t *pmac;
2232a77c 1681
d62a17ae 1682 memset(&tmp, 0, sizeof(tmp));
ff8b7eb8 1683 memcpy(&tmp.macaddr, mac, ETH_ALEN);
d62a17ae 1684 pmac = hash_lookup(zvni->mac_table, &tmp);
2232a77c 1685
d62a17ae 1686 return pmac;
2232a77c 1687}
1688
1689/*
1690 * Inform BGP about local MAC addition.
1691 */
d62a17ae 1692static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni,
1a98c087 1693 struct ethaddr *macaddr, u_char flags)
2232a77c 1694{
1a98c087 1695 return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, flags,
d62a17ae 1696 ZEBRA_MACIP_ADD);
2232a77c 1697}
1698
1699/*
1700 * Inform BGP about local MAC deletion.
1701 */
d62a17ae 1702static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni,
1a98c087 1703 struct ethaddr *macaddr, u_char flags)
2232a77c 1704{
1a98c087 1705 return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, flags,
d62a17ae 1706 ZEBRA_MACIP_DEL);
2232a77c 1707}
1708
1709/*
1710 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
1711 * notifications, to see if there are of interest.
1712 * TODO: Need to make this as a hash table.
1713 */
d62a17ae 1714static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
1715 struct interface *br_if, vlanid_t vid)
2232a77c 1716{
d62a17ae 1717 struct zebra_vrf *zvrf;
1718 struct listnode *node;
1719 struct interface *tmp_if;
1720 struct zebra_if *zif;
1721 struct zebra_l2info_bridge *br;
1722 struct zebra_l2info_vxlan *vxl;
1723 u_char bridge_vlan_aware;
1724 zebra_vni_t *zvni;
2232a77c 1725
d62a17ae 1726 /* Locate VRF corresponding to interface. */
1727 zvrf = vrf_info_lookup(ifp->vrf_id);
1728 assert(zvrf);
2232a77c 1729
d62a17ae 1730 /* Determine if bridge is VLAN-aware or not */
1731 zif = br_if->info;
1732 assert(zif);
1733 br = &zif->l2info.br;
1734 bridge_vlan_aware = br->vlan_aware;
2232a77c 1735
d62a17ae 1736 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1737 /* TODO: Optimize with a hash. */
1738 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
1739 zif = tmp_if->info;
1740 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1741 continue;
1742 if (!if_is_operative(tmp_if))
1743 continue;
1744 vxl = &zif->l2info.vxl;
2232a77c 1745
d62a17ae 1746 if (zif->brslave_info.br_if != br_if)
1747 continue;
2232a77c 1748
d62a17ae 1749 if (!bridge_vlan_aware)
1750 break;
2232a77c 1751
d62a17ae 1752 if (vxl->access_vlan == vid)
1753 break;
1754 }
2232a77c 1755
d62a17ae 1756 if (!tmp_if)
1757 return NULL;
2232a77c 1758
d62a17ae 1759 zvni = zvni_lookup(zvrf, vxl->vni);
1760 return zvni;
2232a77c 1761}
1762
1763/*
1764 * Map SVI and associated bridge to a VNI. This is invoked upon getting
1765 * neighbor notifications, to see if they are of interest.
1766 * TODO: Need to make this as a hash table.
1767 */
d62a17ae 1768static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if)
1769{
1770 struct zebra_vrf *zvrf;
1771 struct listnode *node;
1772 struct interface *tmp_if;
1773 struct zebra_if *zif;
1774 struct zebra_l2info_bridge *br;
1775 struct zebra_l2info_vxlan *vxl;
1776 u_char bridge_vlan_aware;
1777 vlanid_t vid = 0;
1778 zebra_vni_t *zvni;
1779
1780 /* Make sure the linked interface is a bridge. */
1781 if (!IS_ZEBRA_IF_BRIDGE(br_if))
1782 return NULL;
1783
1784 /* Locate VRF corresponding to interface. */
1785 zvrf = vrf_info_lookup(ifp->vrf_id);
1786 assert(zvrf);
1787
1788 /* Determine if bridge is VLAN-aware or not */
1789 zif = br_if->info;
1790 assert(zif);
1791 br = &zif->l2info.br;
1792 bridge_vlan_aware = br->vlan_aware;
1793 if (bridge_vlan_aware) {
1794 struct zebra_l2info_vlan *vl;
1795
1796 if (!IS_ZEBRA_IF_VLAN(ifp))
1797 return NULL;
1798
1799 zif = ifp->info;
1800 assert(zif);
1801 vl = &zif->l2info.vl;
1802 vid = vl->vid;
1803 }
1804
1805 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1806 /* TODO: Optimize with a hash. */
1807 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
1808 zif = tmp_if->info;
1809 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1810 continue;
1811 if (!if_is_operative(tmp_if))
1812 continue;
1813 vxl = &zif->l2info.vxl;
1814
1815 if (zif->brslave_info.br_if != br_if)
1816 continue;
1817
1818 if (!bridge_vlan_aware)
1819 break;
1820
1821 if (vxl->access_vlan == vid)
1822 break;
1823 }
1824
1825 if (!tmp_if)
1826 return NULL;
1827
1828 zvni = zvni_lookup(zvrf, vxl->vni);
1829 return zvni;
2232a77c 1830}
1831
1832/* Map to SVI on bridge corresponding to specified VLAN. This can be one
1833 * of two cases:
1834 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
1835 * linked to the bridge
1836 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
1837 * itself
1838 */
d62a17ae 1839static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid,
1840 struct interface *br_if)
1841{
1842 struct listnode *node;
1843 struct interface *tmp_if;
1844 struct zebra_if *zif;
1845 struct zebra_l2info_bridge *br;
1846 struct zebra_l2info_vlan *vl;
1847 u_char bridge_vlan_aware;
1848
b5ebdc9b 1849 /* Defensive check, caller expected to invoke only with valid bridge. */
1850 if (!br_if)
1851 return NULL;
1852
d62a17ae 1853 /* Determine if bridge is VLAN-aware or not */
1854 zif = br_if->info;
1855 assert(zif);
1856 br = &zif->l2info.br;
1857 bridge_vlan_aware = br->vlan_aware;
1858
1859 /* Check oper status of the SVI. */
1860 if (!bridge_vlan_aware)
1861 return if_is_operative(br_if) ? br_if : NULL;
1862
1863 /* Identify corresponding VLAN interface. */
1864 /* TODO: Optimize with a hash. */
1865 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
1866 /* Check oper status of the SVI. */
1867 if (!if_is_operative(tmp_if))
1868 continue;
1869 zif = tmp_if->info;
1870 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
1871 || zif->link != br_if)
1872 continue;
1873 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
1874
1875 if (vl->vid == vid)
1876 break;
1877 }
1878
1879 return tmp_if;
2232a77c 1880}
1881
1882/*
1883 * Install remote MAC into the kernel.
1884 */
d62a17ae 1885static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 1886{
d62a17ae 1887 struct zebra_if *zif;
1888 struct zebra_l2info_vxlan *vxl;
1889 u_char sticky;
2232a77c 1890
d62a17ae 1891 if (!(mac->flags & ZEBRA_MAC_REMOTE))
1892 return 0;
2232a77c 1893
d62a17ae 1894 zif = zvni->vxlan_if->info;
1895 if (!zif)
1896 return -1;
1897 vxl = &zif->l2info.vxl;
2232a77c 1898
d62a17ae 1899 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
c85c03c7 1900
d62a17ae 1901 return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
1902 mac->fwd_info.r_vtep_ip, sticky);
2232a77c 1903}
1904
1905/*
1906 * Uninstall remote MAC from the kernel. In the scenario where the MAC
1907 * moves to remote, we have to uninstall any existing local entry first.
1908 */
d62a17ae 1909static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local)
2232a77c 1910{
d62a17ae 1911 struct zebra_if *zif;
1912 struct zebra_l2info_vxlan *vxl;
1913 struct in_addr vtep_ip = {.s_addr = 0};
1914 struct zebra_ns *zns;
1915 struct interface *ifp;
2232a77c 1916
d62a17ae 1917 if (!local && !(mac->flags & ZEBRA_MAC_REMOTE))
1918 return 0;
2232a77c 1919
d62a17ae 1920 if (!zvni->vxlan_if) {
1921 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1922 zvni->vni, zvni);
1923 return -1;
1924 }
2232a77c 1925
d62a17ae 1926 zif = zvni->vxlan_if->info;
1927 if (!zif)
1928 return -1;
1929 vxl = &zif->l2info.vxl;
2232a77c 1930
d62a17ae 1931 if (local) {
1932 zns = zebra_ns_lookup(NS_DEFAULT);
1933 ifp = if_lookup_by_index_per_ns(zns,
1934 mac->fwd_info.local.ifindex);
1935 if (!ifp) // unexpected
1936 return -1;
1937 } else {
1938 ifp = zvni->vxlan_if;
1939 vtep_ip = mac->fwd_info.r_vtep_ip;
1940 }
2232a77c 1941
d62a17ae 1942 return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip,
1943 local);
2232a77c 1944}
1945
1946/*
1947 * Install MAC hash entry - called upon access VLAN change.
1948 */
d62a17ae 1949static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
2232a77c 1950{
d62a17ae 1951 zebra_mac_t *mac;
1952 struct mac_walk_ctx *wctx = ctxt;
2232a77c 1953
d62a17ae 1954 mac = (zebra_mac_t *)backet->data;
1955 if (!mac)
1956 return;
2232a77c 1957
d62a17ae 1958 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
1959 zvni_mac_install(wctx->zvni, mac);
2232a77c 1960}
1961
1962/*
1963 * Decrement neighbor refcount of MAC; uninstall and free it if
1964 * appropriate.
1965 */
d62a17ae 1966static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
1967 int uninstall)
2232a77c 1968{
0a97666d
MK
1969 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ||
1970 !list_isempty(mac->neigh_list))
d62a17ae 1971 return;
2232a77c 1972
d62a17ae 1973 if (uninstall)
1974 zvni_mac_uninstall(zvni, mac, 0);
2232a77c 1975
d62a17ae 1976 zvni_mac_del(zvni, mac);
2232a77c 1977}
1978
1979/*
1980 * Read and populate local MACs and neighbors corresponding to this VNI.
1981 */
d62a17ae 1982static void zvni_read_mac_neigh(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
1983 struct interface *ifp)
2232a77c 1984{
d62a17ae 1985 struct zebra_if *zif;
1986 struct interface *vlan_if;
1987 struct zebra_l2info_vxlan *vxl;
1a98c087 1988 struct interface *vrr_if;
2232a77c 1989
d62a17ae 1990 zif = ifp->info;
1991 vxl = &zif->l2info.vxl;
2232a77c 1992
d62a17ae 1993 if (IS_ZEBRA_DEBUG_VXLAN)
1994 zlog_debug(
1995 "%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
1996 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
1997 zif->brslave_info.bridge_ifindex);
2232a77c 1998
d62a17ae 1999 macfdb_read_for_bridge(zvrf->zns, ifp, zif->brslave_info.br_if);
2000 vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan,
2001 zif->brslave_info.br_if);
1a98c087
MK
2002 if (vlan_if) {
2003
2004 if (advertise_gw_macip_enabled(zvrf, zvni)) {
2005 /* Add SVI MAC-IP */
2006 zvni_add_macip_for_intf(vlan_if, zvni);
2007
2008 /* Add VRR MAC-IP - if any*/
2009 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2010 if (vrr_if)
2011 zvni_add_macip_for_intf(vrr_if, zvni);
2012 }
2013
d62a17ae 2014 neigh_read_for_vlan(zvrf->zns, vlan_if);
1a98c087 2015 }
2232a77c 2016}
2017
2018/*
2019 * Hash function for VNI.
2020 */
d62a17ae 2021static unsigned int vni_hash_keymake(void *p)
2232a77c 2022{
d62a17ae 2023 const zebra_vni_t *zvni = p;
2232a77c 2024
d62a17ae 2025 return (jhash_1word(zvni->vni, 0));
2232a77c 2026}
2027
2028/*
2029 * Compare 2 VNI hash entries.
2030 */
d62a17ae 2031static int vni_hash_cmp(const void *p1, const void *p2)
2232a77c 2032{
d62a17ae 2033 const zebra_vni_t *zvni1 = p1;
2034 const zebra_vni_t *zvni2 = p2;
2232a77c 2035
d62a17ae 2036 return (zvni1->vni == zvni2->vni);
2232a77c 2037}
2038
2039/*
2040 * Callback to allocate VNI hash entry.
2041 */
d62a17ae 2042static void *zvni_alloc(void *p)
2232a77c 2043{
d62a17ae 2044 const zebra_vni_t *tmp_vni = p;
2045 zebra_vni_t *zvni;
2232a77c 2046
d62a17ae 2047 zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t));
2048 zvni->vni = tmp_vni->vni;
2049 return ((void *)zvni);
2232a77c 2050}
2051
2052/*
2053 * Look up VNI hash entry.
2054 */
d62a17ae 2055static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni)
2232a77c 2056{
d62a17ae 2057 zebra_vni_t tmp_vni;
2058 zebra_vni_t *zvni = NULL;
2232a77c 2059
d62a17ae 2060 memset(&tmp_vni, 0, sizeof(zebra_vni_t));
2061 tmp_vni.vni = vni;
2062 zvni = hash_lookup(zvrf->vni_table, &tmp_vni);
2232a77c 2063
d62a17ae 2064 return zvni;
2232a77c 2065}
2066
2067/*
2068 * Add VNI hash entry.
2069 */
d62a17ae 2070static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni)
2232a77c 2071{
d62a17ae 2072 zebra_vni_t tmp_zvni;
2073 zebra_vni_t *zvni = NULL;
2232a77c 2074
d62a17ae 2075 memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
2076 tmp_zvni.vni = vni;
2077 zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc);
2078 assert(zvni);
2232a77c 2079
d62a17ae 2080 /* Create hash table for MAC */
2081 zvni->mac_table =
2082 hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table");
2232a77c 2083
d62a17ae 2084 /* Create hash table for neighbors */
2085 zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp,
2086 "Zebra VNI Neighbor Table");
2232a77c 2087
d62a17ae 2088 return zvni;
2232a77c 2089}
2090
2091/*
2092 * Delete VNI hash entry.
2093 */
d62a17ae 2094static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni)
2232a77c 2095{
d62a17ae 2096 zebra_vni_t *tmp_zvni;
2232a77c 2097
d62a17ae 2098 zvni->vxlan_if = NULL;
2232a77c 2099
d62a17ae 2100 /* Free the neighbor hash table. */
2101 hash_free(zvni->neigh_table);
2102 zvni->neigh_table = NULL;
2232a77c 2103
d62a17ae 2104 /* Free the MAC hash table. */
2105 hash_free(zvni->mac_table);
2106 zvni->mac_table = NULL;
2232a77c 2107
d62a17ae 2108 /* Free the VNI hash entry and allocated memory. */
2109 tmp_zvni = hash_release(zvrf->vni_table, zvni);
2110 if (tmp_zvni)
2111 XFREE(MTYPE_ZVNI, tmp_zvni);
2232a77c 2112
d62a17ae 2113 return 0;
2232a77c 2114}
2115
2116/*
2117 * Inform BGP about local VNI addition.
2118 */
d62a17ae 2119static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni)
2232a77c 2120{
d62a17ae 2121 struct zserv *client;
2122 struct stream *s;
2232a77c 2123
d62a17ae 2124 client = zebra_find_client(ZEBRA_ROUTE_BGP);
2125 /* BGP may not be running. */
2126 if (!client)
2127 return 0;
2232a77c 2128
d62a17ae 2129 s = client->obuf;
2130 stream_reset(s);
2232a77c 2131
d62a17ae 2132 zserv_create_header(s, ZEBRA_VNI_ADD, zvrf_id(zvrf));
2133 stream_putl(s, zvni->vni);
2134 stream_put_in_addr(s, &zvni->local_vtep_ip);
2232a77c 2135
d62a17ae 2136 /* Write packet size. */
2137 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 2138
d62a17ae 2139 if (IS_ZEBRA_DEBUG_VXLAN)
2140 zlog_debug("%u:Send VNI_ADD %u %s to %s", zvrf_id(zvrf),
2141 zvni->vni, inet_ntoa(zvni->local_vtep_ip),
2142 zebra_route_string(client->proto));
2232a77c 2143
d62a17ae 2144 client->vniadd_cnt++;
2145 return zebra_server_send_message(client);
2232a77c 2146}
2147
2148/*
2149 * Inform BGP about local VNI deletion.
2150 */
d62a17ae 2151static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni)
2232a77c 2152{
d62a17ae 2153 struct zserv *client;
2154 struct stream *s;
2232a77c 2155
d62a17ae 2156 client = zebra_find_client(ZEBRA_ROUTE_BGP);
2157 /* BGP may not be running. */
2158 if (!client)
2159 return 0;
2232a77c 2160
d62a17ae 2161 s = client->obuf;
2162 stream_reset(s);
2232a77c 2163
d62a17ae 2164 zserv_create_header(s, ZEBRA_VNI_DEL, zvrf_id(zvrf));
2165 stream_putl(s, vni);
2232a77c 2166
d62a17ae 2167 /* Write packet size. */
2168 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 2169
d62a17ae 2170 if (IS_ZEBRA_DEBUG_VXLAN)
2171 zlog_debug("%u:Send VNI_DEL %u to %s", zvrf_id(zvrf), vni,
2172 zebra_route_string(client->proto));
2232a77c 2173
d62a17ae 2174 client->vnidel_cnt++;
2175 return zebra_server_send_message(client);
2232a77c 2176}
2177
2178/*
2179 * Build the VNI hash table by going over the VxLAN interfaces. This
2180 * is called when EVPN (advertise-all-vni) is enabled.
2181 */
d62a17ae 2182static void zvni_build_hash_table(struct zebra_vrf *zvrf)
2232a77c 2183{
d62a17ae 2184 struct listnode *node;
2185 struct interface *ifp;
2232a77c 2186
d62a17ae 2187 /* Walk VxLAN interfaces and create VNI hash. */
2188 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, ifp)) {
2189 struct zebra_if *zif;
2190 struct zebra_l2info_vxlan *vxl;
2191 zebra_vni_t *zvni;
2192 vni_t vni;
2232a77c 2193
d62a17ae 2194 zif = ifp->info;
2195 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2196 continue;
2197 vxl = &zif->l2info.vxl;
2232a77c 2198
d62a17ae 2199 vni = vxl->vni;
2232a77c 2200
d62a17ae 2201 if (IS_ZEBRA_DEBUG_VXLAN)
2202 zlog_debug(
2203 "%u:Create VNI hash for intf %s(%u) VNI %u local IP %s",
2204 zvrf_id(zvrf), ifp->name, ifp->ifindex, vni,
2205 inet_ntoa(vxl->vtep_ip));
2232a77c 2206
d62a17ae 2207 /* VNI hash entry is not expected to exist. */
2208 zvni = zvni_lookup(zvrf, vni);
2209 if (zvni) {
2210 zlog_err(
2211 "VNI hash already present for VRF %d IF %s(%u) VNI %u",
2212 zvrf_id(zvrf), ifp->name, ifp->ifindex, vni);
2213 continue;
2214 }
2232a77c 2215
d62a17ae 2216 zvni = zvni_add(zvrf, vni);
2217 if (!zvni) {
2218 zlog_err(
2219 "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u",
2220 zvrf_id(zvrf), ifp->name, ifp->ifindex, vni);
2221 return;
2222 }
2232a77c 2223
d62a17ae 2224 zvni->local_vtep_ip = vxl->vtep_ip;
2225 zvni->vxlan_if = ifp;
2232a77c 2226
d62a17ae 2227 /* Inform BGP if interface is up and mapped to bridge. */
2228 if (if_is_operative(ifp) && zif->brslave_info.br_if)
2229 zvni_send_add_to_client(zvrf, zvni);
2230 }
2232a77c 2231}
2232
2233/*
2234 * See if remote VTEP matches with prefix.
2235 */
d62a17ae 2236static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
2232a77c 2237{
d62a17ae 2238 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
2232a77c 2239}
2240
2241/*
2242 * Locate remote VTEP in VNI hash table.
2243 */
d62a17ae 2244static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2245{
d62a17ae 2246 zebra_vtep_t *zvtep;
2232a77c 2247
d62a17ae 2248 if (!zvni)
2249 return NULL;
2232a77c 2250
d62a17ae 2251 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2252 if (zvni_vtep_match(vtep_ip, zvtep))
2253 break;
2254 }
2232a77c 2255
d62a17ae 2256 return zvtep;
2232a77c 2257}
2258
2259/*
2260 * Add remote VTEP to VNI hash table.
2261 */
d62a17ae 2262static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2263{
d62a17ae 2264 zebra_vtep_t *zvtep;
2232a77c 2265
d62a17ae 2266 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
2267 if (!zvtep) {
2268 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni->vni);
2269 return NULL;
2270 }
2232a77c 2271
d62a17ae 2272 zvtep->vtep_ip = *vtep_ip;
2232a77c 2273
d62a17ae 2274 if (zvni->vteps)
2275 zvni->vteps->prev = zvtep;
2276 zvtep->next = zvni->vteps;
2277 zvni->vteps = zvtep;
2232a77c 2278
d62a17ae 2279 return zvtep;
2232a77c 2280}
2281
2282/*
2283 * Remove remote VTEP from VNI hash table.
2284 */
d62a17ae 2285static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
2232a77c 2286{
d62a17ae 2287 if (zvtep->next)
2288 zvtep->next->prev = zvtep->prev;
2289 if (zvtep->prev)
2290 zvtep->prev->next = zvtep->next;
2291 else
2292 zvni->vteps = zvtep->next;
2232a77c 2293
d62a17ae 2294 zvtep->prev = zvtep->next = NULL;
2295 XFREE(MTYPE_ZVNI_VTEP, zvtep);
2232a77c 2296
d62a17ae 2297 return 0;
2232a77c 2298}
2299
2300/*
2301 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2302 * uninstall from kernel if asked to.
2303 */
d62a17ae 2304static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
2232a77c 2305{
d62a17ae 2306 zebra_vtep_t *zvtep, *zvtep_next;
2232a77c 2307
d62a17ae 2308 if (!zvni)
2309 return -1;
2232a77c 2310
d62a17ae 2311 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
2312 zvtep_next = zvtep->next;
2313 if (uninstall)
2314 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
2315 zvni_vtep_del(zvni, zvtep);
2316 }
2232a77c 2317
d62a17ae 2318 return 0;
2232a77c 2319}
2320
2321/*
2322 * Install remote VTEP into the kernel.
2323 */
d62a17ae 2324static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2325{
d62a17ae 2326 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2327}
2328
2329/*
2330 * Uninstall remote VTEP from the kernel.
2331 */
d62a17ae 2332static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2333{
d62a17ae 2334 if (!zvni->vxlan_if) {
2335 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2336 zvni->vni, zvni);
2337 return -1;
2338 }
2232a77c 2339
d62a17ae 2340 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2341}
2342
2343/*
2344 * Cleanup VNI/VTEP and update kernel
2345 */
d62a17ae 2346static void zvni_cleanup_all(struct hash_backet *backet, void *zvrf)
2232a77c 2347{
d62a17ae 2348 zebra_vni_t *zvni;
2232a77c 2349
d62a17ae 2350 zvni = (zebra_vni_t *)backet->data;
2351 if (!zvni)
2352 return;
2232a77c 2353
d62a17ae 2354 /* Free up all neighbors and MACs, if any. */
2355 zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
2356 zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
2232a77c 2357
d62a17ae 2358 /* Free up all remote VTEPs, if any. */
2359 zvni_vtep_del_all(zvni, 1);
2232a77c 2360
d62a17ae 2361 /* Delete the hash entry. */
2362 zvni_del(zvrf, zvni);
2232a77c 2363}
2364
2365
2366/* Public functions */
2367
cec2e17d 2368/*
2369 * Display Neighbors for a VNI (VTY command handler).
2370 */
d62a17ae 2371void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 2372 vni_t vni, u_char use_json)
d62a17ae 2373{
2374 zebra_vni_t *zvni;
2375 u_int32_t num_neigh;
2376 struct neigh_walk_ctx wctx;
cd233079 2377 json_object *json = NULL;
d62a17ae 2378
2379 if (!EVPN_ENABLED(zvrf))
2380 return;
2381 zvni = zvni_lookup(zvrf, vni);
2382 if (!zvni) {
cd233079
CS
2383 if (use_json)
2384 vty_out(vty, "{}\n");
2385 else
2386 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2387 return;
2388 }
2389 num_neigh = hashcount(zvni->neigh_table);
2390 if (!num_neigh)
2391 return;
2392
cd233079
CS
2393 if (use_json)
2394 json = json_object_new_object();
2395
d62a17ae 2396 /* Since we have IPv6 addresses to deal with which can vary widely in
2397 * size, we try to be a bit more elegant in display by first computing
2398 * the maximum width.
2399 */
2400 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2401 wctx.zvni = zvni;
2402 wctx.vty = vty;
2403 wctx.addr_width = 15;
cd233079 2404 wctx.json = json;
d62a17ae 2405 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
2406
cd233079
CS
2407 if (!use_json) {
2408 vty_out(vty,
2409 "Number of ARPs (local and remote) known for this VNI: %u\n",
2410 num_neigh);
2411 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
2412 "Type", "MAC", "Remote VTEP");
2413 } else
2414 json_object_int_add(json, "numArpNd", num_neigh);
d62a17ae 2415
2416 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
2417 if (use_json) {
2418 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2419 json, JSON_C_TO_STRING_PRETTY));
2420 json_object_free(json);
2421 }
cec2e17d 2422}
2423
2424/*
2425 * Display neighbors across all VNIs (VTY command handler).
2426 */
cd233079
CS
2427void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
2428 u_char use_json)
cec2e17d 2429{
cd233079
CS
2430 json_object *json = NULL;
2431 void *args[2];
2432
d62a17ae 2433 if (!EVPN_ENABLED(zvrf))
2434 return;
cd233079
CS
2435
2436 if (use_json)
2437 json = json_object_new_object();
2438
2439 args[0] = vty;
2440 args[1] = json;
2441 hash_iterate(zvrf->vni_table,
2442 (void (*)(struct hash_backet *,
2443 void *))zvni_print_neigh_hash_all_vni,
2444 args);
2445 if (use_json) {
2446 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2447 json, JSON_C_TO_STRING_PRETTY));
2448 json_object_free(json);
2449 }
cec2e17d 2450}
2451
2452/*
2453 * Display specific neighbor for a VNI, if present (VTY command handler).
2454 */
d62a17ae 2455void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
2456 struct zebra_vrf *zvrf, vni_t vni,
cd233079 2457 struct ipaddr *ip, u_char use_json)
cec2e17d 2458{
d62a17ae 2459 zebra_vni_t *zvni;
2460 zebra_neigh_t *n;
cd233079 2461 json_object *json = NULL;
cec2e17d 2462
d62a17ae 2463 if (!EVPN_ENABLED(zvrf))
2464 return;
2465 zvni = zvni_lookup(zvrf, vni);
2466 if (!zvni) {
cd233079
CS
2467 if (use_json)
2468 vty_out(vty, "{}\n");
2469 else
2470 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2471 return;
2472 }
2473 n = zvni_neigh_lookup(zvni, ip);
2474 if (!n) {
cd233079
CS
2475 if (!use_json)
2476 vty_out(vty,
2477 "%% Requested neighbor does not exist in VNI %u\n",
2478 vni);
d62a17ae 2479 return;
2480 }
cd233079
CS
2481 if (use_json)
2482 json = json_object_new_object();
2483
2484 zvni_print_neigh(n, vty, json);
cec2e17d 2485
cd233079
CS
2486 if (use_json) {
2487 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2488 json, JSON_C_TO_STRING_PRETTY));
2489 json_object_free(json);
2490 }
cec2e17d 2491}
2492
2493/*
2494 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2495 * By definition, these are remote neighbors.
2496 */
d62a17ae 2497void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
2498 vni_t vni, struct in_addr vtep_ip,
2499 u_char use_json)
cec2e17d 2500{
d62a17ae 2501 zebra_vni_t *zvni;
2502 u_int32_t num_neigh;
2503 struct neigh_walk_ctx wctx;
cd233079 2504 json_object *json = NULL;
cec2e17d 2505
d62a17ae 2506 if (!EVPN_ENABLED(zvrf))
2507 return;
2508 zvni = zvni_lookup(zvrf, vni);
2509 if (!zvni) {
cd233079
CS
2510 if (use_json)
2511 vty_out(vty, "{}\n");
2512 else
2513 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2514 return;
2515 }
2516 num_neigh = hashcount(zvni->neigh_table);
2517 if (!num_neigh)
2518 return;
cec2e17d 2519
d62a17ae 2520 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2521 wctx.zvni = zvni;
2522 wctx.vty = vty;
2523 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
2524 wctx.r_vtep_ip = vtep_ip;
cd233079 2525 wctx.json = json;
d62a17ae 2526 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
2527
2528 if (use_json) {
2529 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2530 json, JSON_C_TO_STRING_PRETTY));
2531 json_object_free(json);
2532 }
cec2e17d 2533}
2534
2535/*
2536 * Display MACs for a VNI (VTY command handler).
2537 */
d62a17ae 2538void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 2539 vni_t vni, u_char use_json)
cec2e17d 2540{
d62a17ae 2541 zebra_vni_t *zvni;
2542 u_int32_t num_macs;
2543 struct mac_walk_ctx wctx;
cd233079
CS
2544 json_object *json = NULL;
2545 json_object *json_mac = NULL;
cec2e17d 2546
d62a17ae 2547 if (!EVPN_ENABLED(zvrf))
2548 return;
2549 zvni = zvni_lookup(zvrf, vni);
2550 if (!zvni) {
cd233079
CS
2551 if (use_json)
2552 vty_out(vty, "{}\n");
2553 else
2554 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2555 return;
2556 }
2557 num_macs = hashcount(zvni->mac_table);
2558 if (!num_macs)
2559 return;
cec2e17d 2560
cd233079
CS
2561 if (use_json) {
2562 json = json_object_new_object();
2563 json_mac = json_object_new_object();
2564 }
2565
d62a17ae 2566 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2567 wctx.zvni = zvni;
2568 wctx.vty = vty;
cd233079 2569 wctx.json = json_mac;
cec2e17d 2570
cd233079
CS
2571 if (!use_json) {
2572 vty_out(vty,
2573 "Number of MACs (local and remote) known for this VNI: %u\n",
2574 num_macs);
2575 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
2576 "Intf/Remote VTEP", "VLAN");
2577 } else
2578 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 2579
d62a17ae 2580 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
2581
2582 if (use_json) {
2583 json_object_object_add(json, "macs", json_mac);
2584 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2585 json, JSON_C_TO_STRING_PRETTY));
2586 json_object_free(json);
2587 }
cec2e17d 2588}
2589
2590/*
2591 * Display MACs for all VNIs (VTY command handler).
2592 */
cd233079
CS
2593void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
2594 u_char use_json)
cec2e17d 2595{
d62a17ae 2596 struct mac_walk_ctx wctx;
cd233079 2597 json_object *json = NULL;
cec2e17d 2598
cd233079
CS
2599 if (!EVPN_ENABLED(zvrf)) {
2600 if (use_json)
2601 vty_out(vty, "{}\n");
d62a17ae 2602 return;
cd233079
CS
2603 }
2604 if (use_json)
2605 json = json_object_new_object();
2606
d62a17ae 2607 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2608 wctx.vty = vty;
cd233079 2609 wctx.json = json;
d62a17ae 2610 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
2611
2612 if (use_json) {
2613 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2614 json, JSON_C_TO_STRING_PRETTY));
2615 json_object_free(json);
2616 }
cec2e17d 2617}
2618
2619/*
2620 * Display MACs for all VNIs (VTY command handler).
2621 */
d62a17ae 2622void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
2623 struct zebra_vrf *zvrf,
cd233079
CS
2624 struct in_addr vtep_ip,
2625 u_char use_json)
cec2e17d 2626{
d62a17ae 2627 struct mac_walk_ctx wctx;
cd233079 2628 json_object *json = NULL;
cec2e17d 2629
d62a17ae 2630 if (!EVPN_ENABLED(zvrf))
2631 return;
cd233079
CS
2632
2633 if (use_json)
2634 json = json_object_new_object();
2635
d62a17ae 2636 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2637 wctx.vty = vty;
2638 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
2639 wctx.r_vtep_ip = vtep_ip;
cd233079 2640 wctx.json = json;
d62a17ae 2641 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
2642
2643 if (use_json) {
2644 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2645 json, JSON_C_TO_STRING_PRETTY));
2646 json_object_free(json);
2647 }
cec2e17d 2648}
2649
2650/*
2651 * Display specific MAC for a VNI, if present (VTY command handler).
2652 */
d62a17ae 2653void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
2654 vni_t vni, struct ethaddr *macaddr)
cec2e17d 2655{
d62a17ae 2656 zebra_vni_t *zvni;
2657 zebra_mac_t *mac;
cec2e17d 2658
d62a17ae 2659 if (!EVPN_ENABLED(zvrf))
2660 return;
2661 zvni = zvni_lookup(zvrf, vni);
2662 if (!zvni) {
2663 vty_out(vty, "%% VNI %u does not exist\n", vni);
2664 return;
2665 }
2666 mac = zvni_mac_lookup(zvni, macaddr);
2667 if (!mac) {
2668 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
2669 vni);
2670 return;
2671 }
cec2e17d 2672
d62a17ae 2673 zvni_print_mac(mac, vty);
cec2e17d 2674}
2675
2676/*
2677 * Display MACs for a VNI from specific VTEP (VTY command handler).
2678 */
d62a17ae 2679void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
2680 vni_t vni, struct in_addr vtep_ip,
2681 u_char use_json)
cec2e17d 2682{
d62a17ae 2683 zebra_vni_t *zvni;
2684 u_int32_t num_macs;
2685 struct mac_walk_ctx wctx;
cd233079
CS
2686 json_object *json = NULL;
2687 json_object *json_mac = NULL;
cec2e17d 2688
d62a17ae 2689 if (!EVPN_ENABLED(zvrf))
2690 return;
2691 zvni = zvni_lookup(zvrf, vni);
2692 if (!zvni) {
cd233079
CS
2693 if (use_json)
2694 vty_out(vty, "{}\n");
2695 else
2696 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2697 return;
2698 }
2699 num_macs = hashcount(zvni->mac_table);
2700 if (!num_macs)
2701 return;
cd233079
CS
2702
2703 if (use_json) {
2704 json = json_object_new_object();
2705 json_mac = json_object_new_object();
2706 }
2707
d62a17ae 2708 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2709 wctx.zvni = zvni;
2710 wctx.vty = vty;
2711 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
2712 wctx.r_vtep_ip = vtep_ip;
cd233079 2713 wctx.json = json_mac;
d62a17ae 2714 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
2715
2716 if (use_json) {
2717 json_object_int_add(json, "numMacs", wctx.count);
2718 if (wctx.count)
2719 json_object_object_add(json, "macs", json_mac);
2720 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2721 json, JSON_C_TO_STRING_PRETTY));
2722 json_object_free(json);
2723 }
cec2e17d 2724}
2725
2726
2727/*
2728 * Display VNI information (VTY command handler).
2729 */
cd233079
CS
2730void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
2731 u_char use_json)
cec2e17d 2732{
d62a17ae 2733 zebra_vni_t *zvni;
cd233079
CS
2734 json_object *json = NULL;
2735 void *args[2];
cec2e17d 2736
d62a17ae 2737 if (!EVPN_ENABLED(zvrf))
2738 return;
2739 zvni = zvni_lookup(zvrf, vni);
2740 if (!zvni) {
cd233079
CS
2741 if (use_json)
2742 vty_out(vty, "{}\n");
2743 else
2744 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2745 return;
2746 }
cd233079
CS
2747 if (use_json)
2748 json = json_object_new_object();
2749 args[0] = vty;
2750 args[1] = json;
2751 zvni_print(zvni, (void *)args);
2752 if (use_json) {
2753 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2754 json, JSON_C_TO_STRING_PRETTY));
2755 json_object_free(json);
2756 }
cec2e17d 2757}
2758
2759/*
2760 * Display VNI hash table (VTY command handler).
2761 */
cd233079
CS
2762void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
2763 u_char use_json)
cec2e17d 2764{
d62a17ae 2765 u_int32_t num_vnis;
cd233079
CS
2766 json_object *json = NULL;
2767 void *args[2];
cec2e17d 2768
d62a17ae 2769 if (!EVPN_ENABLED(zvrf))
2770 return;
2771 num_vnis = hashcount(zvrf->vni_table);
cd233079
CS
2772 if (!num_vnis) {
2773 if (use_json)
2774 vty_out(vty, "{}\n");
d62a17ae 2775 return;
cd233079
CS
2776 }
2777 if (use_json) {
2778 json = json_object_new_object();
ddd16ed5
MK
2779 json_object_string_add(json, "advertiseGatewayMacip",
2780 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
2781 json_object_int_add(json, "numVnis", num_vnis);
2782 } else {
ddd16ed5
MK
2783 vty_out(vty, "Advertise gateway mac-ip: %s\n",
2784 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
2785 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
2786 vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s\n", "VNI",
2787 "VxLAN IF", "VTEP IP", "# MACs", "# ARPs",
2788 "# Remote VTEPs");
2789 }
2790 args[0] = vty;
2791 args[1] = json;
2792
2793 hash_iterate(zvrf->vni_table,
2794 (void (*)(struct hash_backet *, void *))zvni_print_hash,
2795 args);
2796
2797 if (use_json) {
2798 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2799 json, JSON_C_TO_STRING_PRETTY));
2800 json_object_free(json);
2801 }
cec2e17d 2802}
2803
2232a77c 2804/*
2805 * Handle neighbor delete (on a VLAN device / L3 interface) from the
2806 * kernel. This may result in either the neighbor getting deleted from
2807 * our database or being re-added to the kernel (if it is a valid
2808 * remote neighbor).
2809 */
d62a17ae 2810int zebra_vxlan_local_neigh_del(struct interface *ifp,
2811 struct interface *link_if, struct ipaddr *ip)
2812{
2813 zebra_vni_t *zvni;
2814 zebra_neigh_t *n;
2815 struct zebra_vrf *zvrf;
2816 char buf[INET6_ADDRSTRLEN];
b6938a74
MK
2817 char buf2[ETHER_ADDR_STRLEN];
2818 zebra_mac_t *zmac;
d62a17ae 2819
2820 /* We are only interested in neighbors on an SVI that resides on top
2821 * of a VxLAN bridge.
2822 */
2823 zvni = zvni_map_svi(ifp, link_if);
2824 if (!zvni)
2825 return 0;
2826 if (!zvni->vxlan_if) {
2827 zlog_err(
2828 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
2829 zvni->vni, zvni);
2830 return -1;
2831 }
2832
2833 if (IS_ZEBRA_DEBUG_VXLAN)
2834 zlog_debug("%u:Del neighbor %s intf %s(%u) -> VNI %u",
2835 ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)),
2836 ifp->name, ifp->ifindex, zvni->vni);
2837
2838 /* If entry doesn't exist, nothing to do. */
2839 n = zvni_neigh_lookup(zvni, ip);
2840 if (!n)
2841 return 0;
2842
b6938a74
MK
2843 zmac = zvni_mac_lookup(zvni, &n->emac);
2844 if (!zmac) {
2845 if (IS_ZEBRA_DEBUG_VXLAN)
2846 zlog_err(
2847 "%u: trying to del a neigh %s without a mac %s on VNI %u",
2848 ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)),
2849 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
2850 zvni->vni);
2851
2852 return 0;
2853 }
2854
d62a17ae 2855 /* If it is a remote entry, the kernel has aged this out or someone has
2856 * deleted it, it needs to be re-installed as Quagga is the owner.
2857 */
2858 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
2859 zvni_neigh_install(zvni, n);
2860 return 0;
2861 }
2862
2863 /* Locate VRF corresponding to interface. */
2864 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
2865 assert(zvrf);
2866
2867 /* Remove neighbor from BGP. */
b6938a74
MK
2868 if (IS_ZEBRA_NEIGH_ACTIVE(n))
2869 zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
2870 0);
d62a17ae 2871
2872 /* Delete this neighbor entry. */
2873 zvni_neigh_del(zvni, n);
2874
b6938a74
MK
2875 /* see if the AUTO mac needs to be deleted */
2876 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
f51d8a27 2877 && !listcount(zmac->neigh_list))
b6938a74
MK
2878 zvni_mac_del(zvni, zmac);
2879
d62a17ae 2880 return 0;
2232a77c 2881}
2882
2883/*
859b32c0
MK
2884 * Handle neighbor add or update (on a VLAN device / L3 interface)
2885 * from the kernel.
2232a77c 2886 */
d62a17ae 2887int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
2888 struct interface *link_if,
2889 struct ipaddr *ip,
2890 struct ethaddr *macaddr, u_int16_t state,
2891 u_char ext_learned)
2892{
2893 zebra_vni_t *zvni;
2894 zebra_neigh_t *n;
2895 struct zebra_vrf *zvrf;
b682f6de 2896 zebra_mac_t *zmac, *old_zmac;
d62a17ae 2897 char buf[ETHER_ADDR_STRLEN];
2898 char buf2[INET6_ADDRSTRLEN];
d62a17ae 2899
2900 /* We are only interested in neighbors on an SVI that resides on top
2901 * of a VxLAN bridge.
2902 */
2903 zvni = zvni_map_svi(ifp, link_if);
2904 if (!zvni)
2905 return 0;
2906
2907 /* Locate VRF corresponding to interface. */
2908 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
2909 assert(zvrf);
2910
2911 if (IS_ZEBRA_DEBUG_VXLAN)
2912 zlog_debug(
2913 "%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x "
2914 "%s-> VNI %u",
2915 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
2916 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
2917 ifp->ifindex, state, ext_learned ? "ext-learned " : "",
2918 zvni->vni);
2919
b6938a74
MK
2920 /* create a dummy MAC if the MAC is not already present */
2921 zmac = zvni_mac_lookup(zvni, macaddr);
2922 if (!zmac) {
2923 if (IS_ZEBRA_DEBUG_VXLAN)
2924 zlog_debug(
2925 "%u: AUTO MAC %s created for neigh %s on VNI %u",
2926 ifp->vrf_id,
2927 prefix_mac2str(macaddr, buf, sizeof(buf)),
2928 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
2929
2930 zmac = zvni_mac_add(zvni, macaddr);
2931 if (!zmac) {
2932 zlog_warn("%u:Failed to add MAC %s VNI %u",
2933 zvrf_id(zvrf),
2934 prefix_mac2str(macaddr, buf, sizeof(buf)),
2935 zvni->vni);
2936 return -1;
2937 }
2938
2939 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
2940 memset(&zmac->flags, 0, sizeof(u_int32_t));
2941 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
2942 }
2943
d62a17ae 2944 /* If same entry already exists, it might be a change or it might be a
2945 * move from remote to local.
2946 */
2947 n = zvni_neigh_lookup(zvni, ip);
2948 if (n) {
2949 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2950 if (memcmp(n->emac.octet, macaddr->octet,
ff8b7eb8 2951 ETH_ALEN)
d62a17ae 2952 == 0) {
b682f6de 2953 /* Update any params and return - client doesn't
2954 * care about a purely local change.
2955 */
2956 n->ifindex = ifp->ifindex;
2957 return 0;
57f7feb6 2958 }
b682f6de 2959
57f7feb6
MK
2960 /* If the MAC has changed,
2961 * need to issue a delete first
2962 * as this means a different MACIP route.
2963 * Also, need to do some unlinking/relinking.
2964 */
2965 zvni_neigh_send_del_to_client(zvrf, zvni->vni,
2966 &n->ip, &n->emac,
2967 0);
2968 old_zmac = zvni_mac_lookup(zvni, &n->emac);
2969 if (old_zmac) {
2970 listnode_delete(old_zmac->neigh_list,
2971 n);
2972 zvni_deref_ip2mac(zvni, old_zmac, 0);
b682f6de 2973 }
57f7feb6
MK
2974
2975 /* Set "local" forwarding info. */
2976 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2977 n->ifindex = ifp->ifindex;
2978 memcpy(&n->emac, macaddr, ETH_ALEN);
2979
2980 /* Link to new MAC */
2981 listnode_add_sort(zmac->neigh_list, n);
d62a17ae 2982 } else if (ext_learned)
2983 /* The neighbor is remote and that is the notification we got.
9d303b37 2984 */
d62a17ae 2985 {
859b32c0 2986 /* TODO: Evaluate if we need to do anything here. */
d62a17ae 2987 return 0;
2988 } else
2989 /* Neighbor has moved from remote to local. */
2990 {
2991 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
2992 n->r_vtep_ip.s_addr = 0;
b682f6de 2993 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2994 n->ifindex = ifp->ifindex;
d62a17ae 2995 }
2996 } else {
b6938a74 2997 n = zvni_neigh_add(zvni, ip, macaddr);
d62a17ae 2998 if (!n) {
2999 zlog_err(
3000 "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3001 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
3002 prefix_mac2str(macaddr, buf, sizeof(buf)),
3003 ifp->name, ifp->ifindex, zvni->vni);
3004 return -1;
3005 }
b682f6de 3006 /* Set "local" forwarding info. */
3007 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3008 n->ifindex = ifp->ifindex;
d62a17ae 3009 }
3010
b6938a74
MK
3011 /* Before we program this in BGP, we need to check if MAC is locally
3012 * learnt as well */
3013 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
3014 if (IS_ZEBRA_DEBUG_VXLAN)
3015 zlog_debug(
3016 "%u: Skipping neigh %s add to client as MAC %s is not local on VNI %u",
3017 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
3018 prefix_mac2str(macaddr, buf, sizeof(buf)),
3019 zvni->vni);
3020
3021 return 0;
3022 }
3023
b682f6de 3024 /* Inform BGP. */
3025 if (IS_ZEBRA_DEBUG_VXLAN)
3026 zlog_debug(
3027 "%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
3028 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
3029 prefix_mac2str(macaddr, buf, sizeof(buf)),
3030 zvni->vni);
d62a17ae 3031
b682f6de 3032 ZEBRA_NEIGH_SET_ACTIVE(n);
3033 return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
3034 macaddr, 0);
2232a77c 3035}
3036
b682f6de 3037
2232a77c 3038/*
3039 * Handle message from client to delete a remote MACIP for a VNI.
3040 */
d62a17ae 3041int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
3042 struct zebra_vrf *zvrf)
3043{
3044 struct stream *s;
3045 vni_t vni;
3046 struct ethaddr macaddr;
3047 struct ipaddr ip;
3048 struct in_addr vtep_ip;
3049 zebra_vni_t *zvni;
3050 zebra_mac_t *mac;
3051 zebra_neigh_t *n;
3052 u_short l = 0, ipa_len;
3053 char buf[ETHER_ADDR_STRLEN];
3054 char buf1[INET6_ADDRSTRLEN];
b5ebdc9b 3055 struct interface *ifp = NULL;
3056 struct zebra_if *zif = NULL;
d62a17ae 3057
3058 s = client->ibuf;
3059
3060 while (l < length) {
3061 /* Obtain each remote MACIP and process. */
3062 /* Message contains VNI, followed by MAC followed by IP (if any)
3063 * followed by remote VTEP IP.
3064 */
3065 mac = NULL;
3066 n = NULL;
3067 memset(&ip, 0, sizeof(ip));
3068 vni = (vni_t)stream_getl(s);
ff8b7eb8 3069 stream_get(&macaddr.octet, s, ETH_ALEN);
d62a17ae 3070 ipa_len = stream_getl(s);
3071 if (ipa_len) {
3072 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
3073 : IPADDR_V6;
3074 stream_get(&ip.ip.addr, s, ipa_len);
3075 }
ff8b7eb8 3076 l += 4 + ETH_ALEN + 4 + ipa_len;
d62a17ae 3077 vtep_ip.s_addr = stream_get_ipv4(s);
3078 l += IPV4_MAX_BYTELEN;
3079
3080 if (IS_ZEBRA_DEBUG_VXLAN)
3081 zlog_debug(
3082 "%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
3083 zvrf_id(zvrf),
3084 prefix_mac2str(&macaddr, buf, sizeof(buf)),
3085 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
3086 inet_ntoa(vtep_ip),
3087 zebra_route_string(client->proto));
3088
3089 /* Locate VNI hash entry - expected to exist. */
3090 zvni = zvni_lookup(zvrf, vni);
3091 if (!zvni) {
3092 if (IS_ZEBRA_DEBUG_VXLAN)
3093 zlog_debug(
3094 "Failed to locate VNI hash upon remote MACIP DEL, "
3095 "VRF %d VNI %u",
3096 zvrf_id(zvrf), vni);
3097 continue;
3098 }
b5ebdc9b 3099 ifp = zvni->vxlan_if;
af026ae4 3100 if (!ifp) {
d62a17ae 3101 zlog_err(
3102 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
3103 vni, zvni);
3104 continue;
3105 }
b5ebdc9b 3106 zif = ifp->info;
3107
3108 /* If down or not mapped to a bridge, we're done. */
b682f6de 3109 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 3110 continue;
d62a17ae 3111
3112 /* The remote VTEP specified is normally expected to exist, but
3113 * it is
3114 * possible that the peer may delete the VTEP before deleting
3115 * any MACs
3116 * referring to the VTEP, in which case the handler (see
3117 * remote_vtep_del)
3118 * would have already deleted the MACs.
3119 */
3120 if (!zvni_vtep_find(zvni, &vtep_ip))
3121 continue;
3122
d62a17ae 3123 mac = zvni_mac_lookup(zvni, &macaddr);
3124 if (ipa_len)
3125 n = zvni_neigh_lookup(zvni, &ip);
3126
3127 if (n && !mac) {
3128 zlog_err(
3129 "failed to locate MAC %s for neigh %s in VRF %u VNI %u",
3130 prefix_mac2str(&macaddr, buf, sizeof(buf)),
3131 ipaddr2str(&ip, buf1, sizeof(buf1)),
3132 zvrf_id(zvrf), vni);
3133 continue;
3134 }
3135
3136 /* If the remote mac or neighbor doesn't exist there is nothing
3137 * more
3138 * to do. Otherwise, uninstall the entry and then remove it.
3139 */
3140 if (!mac && !n)
3141 continue;
3142
3143 /* Uninstall remote neighbor or MAC. */
3144 if (n) {
3145 /* When the MAC changes for an IP, it is possible the
3146 * client may
3147 * update the new MAC before trying to delete the "old"
3148 * neighbor
3149 * (as these are two different MACIP routes). Do the
3150 * delete only
3151 * if the MAC matches.
3152 */
3153 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
3154 && (memcmp(n->emac.octet, macaddr.octet,
ff8b7eb8 3155 ETH_ALEN)
d62a17ae 3156 == 0)) {
3157 zvni_neigh_uninstall(zvni, n);
3158 zvni_neigh_del(zvni, n);
3159 zvni_deref_ip2mac(zvni, mac, 1);
3160 }
3161 } else {
3162 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
b6938a74
MK
3163 zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
3164 mac);
3165
0a97666d 3166 if (list_isempty(mac->neigh_list)) {
d62a17ae 3167 zvni_mac_uninstall(zvni, mac, 0);
3168 zvni_mac_del(zvni, mac);
3169 } else
3170 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3171 }
3172 }
3173 }
3174
3175 return 0;
2232a77c 3176}
3177
3178/*
3179 * Handle message from client to add a remote MACIP for a VNI. This
3180 * could be just the add of a MAC address or the add of a neighbor
3181 * (IP+MAC).
3182 */
d62a17ae 3183int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
3184 struct zebra_vrf *zvrf)
3185{
3186 struct stream *s;
3187 vni_t vni;
3188 struct ethaddr macaddr;
3189 struct ipaddr ip;
3190 struct in_addr vtep_ip;
3191 zebra_vni_t *zvni;
3192 zebra_vtep_t *zvtep;
3193 zebra_mac_t *mac, *old_mac;
3194 zebra_neigh_t *n;
3195 u_short l = 0, ipa_len;
3196 int update_mac = 0, update_neigh = 0;
3197 char buf[ETHER_ADDR_STRLEN];
3198 char buf1[INET6_ADDRSTRLEN];
3199 u_char sticky;
b5ebdc9b 3200 struct interface *ifp = NULL;
3201 struct zebra_if *zif = NULL;
d62a17ae 3202
3203 assert(EVPN_ENABLED(zvrf));
3204
3205 s = client->ibuf;
3206
3207 while (l < length) {
3208 /* Obtain each remote MACIP and process. */
3209 /* Message contains VNI, followed by MAC followed by IP (if any)
3210 * followed by remote VTEP IP.
3211 */
3212 update_mac = update_neigh = 0;
3213 mac = NULL;
3214 n = NULL;
3215 memset(&ip, 0, sizeof(ip));
3216 vni = (vni_t)stream_getl(s);
ff8b7eb8 3217 stream_get(&macaddr.octet, s, ETH_ALEN);
d62a17ae 3218 ipa_len = stream_getl(s);
3219 if (ipa_len) {
3220 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
3221 : IPADDR_V6;
3222 stream_get(&ip.ip.addr, s, ipa_len);
3223 }
ff8b7eb8 3224 l += 4 + ETH_ALEN + 4 + ipa_len;
d62a17ae 3225 vtep_ip.s_addr = stream_get_ipv4(s);
3226 l += IPV4_MAX_BYTELEN;
3227
3228 /* Get 'sticky' flag. */
3229 sticky = stream_getc(s);
3230 l++;
3231
3232 if (IS_ZEBRA_DEBUG_VXLAN)
3233 zlog_debug(
3234 "%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
3235 zvrf_id(zvrf), sticky ? "sticky " : "",
3236 prefix_mac2str(&macaddr, buf, sizeof(buf)),
3237 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
3238 inet_ntoa(vtep_ip),
3239 zebra_route_string(client->proto));
3240
3241 /* Locate VNI hash entry - expected to exist. */
3242 zvni = zvni_lookup(zvrf, vni);
3243 if (!zvni) {
3244 zlog_err(
3245 "Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u",
3246 zvrf_id(zvrf), vni);
3247 continue;
3248 }
b5ebdc9b 3249 ifp = zvni->vxlan_if;
3250 if (!ifp) {
d62a17ae 3251 zlog_err(
3252 "VNI %u hash %p doesn't have intf upon remote MACIP add",
3253 vni, zvni);
3254 continue;
3255 }
b5ebdc9b 3256 zif = ifp->info;
3257
3258 /* If down or not mapped to a bridge, we're done. */
b682f6de 3259 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 3260 continue;
3261
3262 /* The remote VTEP specified should normally exist, but it is
3263 * possible
3264 * that when peering comes up, peer may advertise MACIP routes
3265 * before
3266 * advertising type-3 routes.
3267 */
3268 zvtep = zvni_vtep_find(zvni, &vtep_ip);
3269 if (!zvtep) {
3270 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
3271 zlog_err(
3272 "Failed to add remote VTEP, VRF %d VNI %u zvni %p",
3273 zvrf_id(zvrf), vni, zvni);
3274 continue;
3275 }
3276
3277 zvni_vtep_install(zvni, &vtep_ip);
3278 }
3279
3280 /* First, check if the remote MAC is unknown or has a change. If
3281 * so,
3282 * that needs to be updated first. Note that client could
3283 * install
3284 * MAC and MACIP separately or just install the latter.
3285 */
3286 mac = zvni_mac_lookup(zvni, &macaddr);
3287 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
3288 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
3289 != sticky
3290 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
3291 update_mac = 1;
3292
3293 if (update_mac) {
3294 if (!mac) {
3295 mac = zvni_mac_add(zvni, &macaddr);
3296 if (!mac) {
3297 zlog_warn(
3298 "%u:Failed to add MAC %s VNI %u Remote VTEP %s",
3299 zvrf_id(zvrf),
3300 prefix_mac2str(&macaddr, buf,
3301 sizeof(buf)),
3302 vni, inet_ntoa(vtep_ip));
3303 return -1;
3304 }
3305
3306 /* Is this MAC created for a MACIP? */
3307 if (ipa_len)
3308 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 3309 }
3310
3311 /* Set "auto" and "remote" forwarding info. */
3312 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
3313 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
3314 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
3315 mac->fwd_info.r_vtep_ip = vtep_ip;
3316
3317 if (sticky)
3318 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3319 else
3320 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3321
b6938a74
MK
3322 zvni_process_neigh_on_remote_mac_add(zvrf, zvni, mac);
3323
d62a17ae 3324 /* Install the entry. */
3325 zvni_mac_install(zvni, mac);
3326 }
3327
3328 /* If there is no IP, continue - after clearing AUTO flag of
3329 * MAC. */
3330 if (!ipa_len) {
3331 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3332 continue;
3333 }
3334
3335 /* Check if the remote neighbor itself is unknown or has a
3336 * change.
3337 * If so, create or update and then install the entry.
3338 */
3339 n = zvni_neigh_lookup(zvni, &ip);
3340 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
3341 || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0)
3342 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip))
3343 update_neigh = 1;
3344
3345 if (update_neigh) {
3346 if (!n) {
b6938a74 3347 n = zvni_neigh_add(zvni, &ip, &macaddr);
d62a17ae 3348 if (!n) {
3349 zlog_warn(
3350 "%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
3351 zvrf_id(zvrf),
3352 ipaddr2str(&ip, buf1,
3353 sizeof(buf1)),
3354 prefix_mac2str(&macaddr, buf,
3355 sizeof(buf)),
3356 vni, inet_ntoa(vtep_ip));
3357 return -1;
3358 }
3359
d62a17ae 3360 } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
3361 != 0) {
0a97666d
MK
3362 /* MAC change, update neigh list for old and new
3363 * mac */
d62a17ae 3364 old_mac = zvni_mac_lookup(zvni, &n->emac);
0a97666d
MK
3365 if (old_mac) {
3366 listnode_delete(old_mac->neigh_list, n);
d62a17ae 3367 zvni_deref_ip2mac(zvni, old_mac, 1);
0a97666d
MK
3368 }
3369 listnode_add_sort(mac->neigh_list, n);
b6938a74 3370 memcpy(&n->emac, &macaddr, ETH_ALEN);
d62a17ae 3371 }
3372
3373 /* Set "remote" forwarding info. */
3374 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3375 /* TODO: Handle MAC change. */
d62a17ae 3376 n->r_vtep_ip = vtep_ip;
3377 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3378
3379 /* Install the entry. */
3380 zvni_neigh_install(zvni, n);
3381 }
3382 }
3383
3384 return 0;
13d60d35 3385}
3386
3387/*
2232a77c 3388 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
3389 * us, this must involve a multihoming scenario. Treat this as implicit delete
3390 * of any prior local MAC.
13d60d35 3391 */
d62a17ae 3392int zebra_vxlan_check_del_local_mac(struct interface *ifp,
3393 struct interface *br_if,
3394 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 3395{
d62a17ae 3396 struct zebra_if *zif;
3397 struct zebra_vrf *zvrf;
3398 struct zebra_l2info_vxlan *vxl;
3399 vni_t vni;
3400 zebra_vni_t *zvni;
3401 zebra_mac_t *mac;
3402 char buf[ETHER_ADDR_STRLEN];
3403 u_char sticky;
13d60d35 3404
d62a17ae 3405 zif = ifp->info;
3406 assert(zif);
3407 vxl = &zif->l2info.vxl;
3408 vni = vxl->vni;
13d60d35 3409
d62a17ae 3410 /* Locate VRF corresponding to interface. */
3411 zvrf = vrf_info_lookup(ifp->vrf_id);
3412 assert(zvrf);
13d60d35 3413
d62a17ae 3414 /* If EVPN is not enabled, nothing to do. */
3415 if (!EVPN_ENABLED(zvrf))
3416 return 0;
13d60d35 3417
d62a17ae 3418 /* Locate hash entry; it is expected to exist. */
3419 zvni = zvni_lookup(zvrf, vni);
3420 if (!zvni)
3421 return 0;
13d60d35 3422
d62a17ae 3423 /* If entry doesn't exist, nothing to do. */
3424 mac = zvni_mac_lookup(zvni, macaddr);
3425 if (!mac)
3426 return 0;
13d60d35 3427
d62a17ae 3428 /* Is it a local entry? */
3429 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
3430 return 0;
13d60d35 3431
d62a17ae 3432 if (IS_ZEBRA_DEBUG_VXLAN)
3433 zlog_debug(
3434 "%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local",
3435 ifp->vrf_id, prefix_mac2str(macaddr, buf, sizeof(buf)),
3436 ifp->name, ifp->ifindex, vni);
13d60d35 3437
d62a17ae 3438 /* Remove MAC from BGP. */
3439 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
1a98c087
MK
3440 zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
3441 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
13d60d35 3442
b6938a74
MK
3443 /*
3444 * If there are no neigh associated with the mac delete the mac
3445 * else mark it as AUTO for forward reference
3446 */
3447 if (!listcount(mac->neigh_list)) {
3448 zvni_mac_del(zvni, mac);
3449 } else {
3450 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
3451 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3452 }
13d60d35 3453
d62a17ae 3454 return 0;
13d60d35 3455}
3456
3457/*
2232a77c 3458 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
3459 * This can happen because the remote MAC entries are also added as "dynamic",
3460 * so the kernel can ageout the entry.
13d60d35 3461 */
d62a17ae 3462int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
3463 struct interface *br_if,
3464 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 3465{
d62a17ae 3466 struct zebra_if *zif;
3467 struct zebra_vrf *zvrf;
3468 struct zebra_l2info_vxlan *vxl;
3469 vni_t vni;
3470 zebra_vni_t *zvni;
3471 zebra_mac_t *mac;
3472 char buf[ETHER_ADDR_STRLEN];
2232a77c 3473
d62a17ae 3474 zif = ifp->info;
3475 assert(zif);
3476 vxl = &zif->l2info.vxl;
3477 vni = vxl->vni;
2232a77c 3478
d62a17ae 3479 /* Locate VRF corresponding to interface. */
3480 zvrf = vrf_info_lookup(ifp->vrf_id);
3481 assert(zvrf);
13d60d35 3482
d62a17ae 3483 /* If EVPN is not enabled, nothing to do. */
3484 if (!EVPN_ENABLED(zvrf))
3485 return 0;
2232a77c 3486
d62a17ae 3487 /* Locate hash entry; it is expected to exist. */
3488 zvni = zvni_lookup(zvrf, vni);
3489 if (!zvni)
3490 return 0;
13d60d35 3491
d62a17ae 3492 /* If entry doesn't exist, nothing to do. */
3493 mac = zvni_mac_lookup(zvni, macaddr);
3494 if (!mac)
3495 return 0;
2232a77c 3496
d62a17ae 3497 /* Is it a remote entry? */
3498 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
3499 return 0;
2232a77c 3500
d62a17ae 3501 if (IS_ZEBRA_DEBUG_VXLAN)
3502 zlog_debug("%u:Del remote MAC %s intf %s(%u) VNI %u - readd",
3503 ifp->vrf_id,
3504 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
3505 ifp->ifindex, vni);
13d60d35 3506
d62a17ae 3507 zvni_mac_install(zvni, mac);
3508 return 0;
13d60d35 3509}
3510
3511/*
2232a77c 3512 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 3513 */
d62a17ae 3514int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
3515 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 3516{
d62a17ae 3517 zebra_vni_t *zvni;
3518 zebra_mac_t *mac;
3519 struct zebra_vrf *zvrf;
3520 char buf[ETHER_ADDR_STRLEN];
3521 u_char sticky;
13d60d35 3522
d62a17ae 3523 /* We are interested in MACs only on ports or (port, VLAN) that
3524 * map to a VNI.
3525 */
3526 zvni = zvni_map_vlan(ifp, br_if, vid);
3527 if (!zvni)
3528 return 0;
3529 if (!zvni->vxlan_if) {
3530 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
3531 zvni->vni, zvni);
3532 return -1;
3533 }
13d60d35 3534
d62a17ae 3535 if (IS_ZEBRA_DEBUG_VXLAN)
3536 zlog_debug("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u",
3537 ifp->vrf_id,
3538 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
3539 ifp->ifindex, vid, zvni->vni);
2232a77c 3540
d62a17ae 3541 /* If entry doesn't exist, nothing to do. */
3542 mac = zvni_mac_lookup(zvni, macaddr);
3543 if (!mac)
3544 return 0;
2232a77c 3545
d62a17ae 3546 /* Is it a local entry? */
3547 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
3548 return 0;
2232a77c 3549
d62a17ae 3550 /* Locate VRF corresponding to interface. */
3551 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
3552 assert(zvrf);
2232a77c 3553
d62a17ae 3554 /* Remove MAC from BGP. */
3555 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
1a98c087
MK
3556 zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
3557 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
2232a77c 3558
b6938a74
MK
3559 /* Update all the neigh entries associated with this mac */
3560 zvni_process_neigh_on_local_mac_del(zvrf, zvni, mac);
3561
3562 /*
3563 * If there are no neigh associated with the mac delete the mac
3564 * else mark it as AUTO for forward reference
3565 */
3566 if (!listcount(mac->neigh_list)) {
3567 zvni_mac_del(zvni, mac);
3568 } else {
3569 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
3570 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3571 }
2232a77c 3572
d62a17ae 3573 return 0;
13d60d35 3574}
3575
3576/*
2232a77c 3577 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 3578 */
d62a17ae 3579int zebra_vxlan_local_mac_add_update(struct interface *ifp,
3580 struct interface *br_if,
3581 struct ethaddr *macaddr, vlanid_t vid,
3582 u_char sticky)
3583{
3584 zebra_vni_t *zvni;
3585 zebra_mac_t *mac;
3586 struct zebra_vrf *zvrf;
3587 char buf[ETHER_ADDR_STRLEN];
3588 int add = 1;
3589 u_char mac_sticky;
3590
3591 /* We are interested in MACs only on ports or (port, VLAN) that
3592 * map to a VNI.
3593 */
3594 zvni = zvni_map_vlan(ifp, br_if, vid);
3595 if (!zvni) {
3596 if (IS_ZEBRA_DEBUG_VXLAN)
3597 zlog_debug(
3598 "%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
3599 ifp->vrf_id, sticky ? "sticky " : "",
3600 prefix_mac2str(macaddr, buf, sizeof(buf)),
3601 ifp->name, ifp->ifindex, vid);
3602 return 0;
3603 }
3604
3605 if (!zvni->vxlan_if) {
3606 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
3607 zvni->vni, zvni);
3608 return -1;
3609 }
3610
3611 if (IS_ZEBRA_DEBUG_VXLAN)
3612 zlog_debug(
3613 "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
3614 ifp->vrf_id, sticky ? "sticky " : "",
3615 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
3616 ifp->ifindex, vid, zvni->vni);
3617
3618 /* If same entry already exists, nothing to do. */
3619 mac = zvni_mac_lookup(zvni, macaddr);
3620 if (mac) {
3621 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
3622 mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
3623 ? 1
3624 : 0;
3625
b6938a74 3626
b8ce75a5
MK
3627 /*
3628 * return if nothing has changed.
3629 * inform bgp if sticky flag has changed
3630 * update locally and do not inform bgp if local
3631 * parameters like interface has changed
3632 */
d62a17ae 3633 if (mac_sticky == sticky
3634 && mac->fwd_info.local.ifindex == ifp->ifindex
3635 && mac->fwd_info.local.vid == vid) {
3636 if (IS_ZEBRA_DEBUG_VXLAN)
3637 zlog_debug(
3638 "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
3639 "entry exists and has not changed ",
3640 ifp->vrf_id,
3641 sticky ? "sticky " : "",
3642 prefix_mac2str(macaddr, buf,
3643 sizeof(buf)),
3644 ifp->name, ifp->ifindex, vid,
3645 zvni->vni);
3646 return 0;
b6938a74 3647 } else if (mac_sticky != sticky) {
b8ce75a5 3648 add = 1;
b6938a74 3649 } else {
b8ce75a5
MK
3650 add = 0; /* This is an update of local
3651 interface. */
b6938a74 3652 }
421bb26a
MK
3653 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
3654 /*
3655 * If we have already learned the MAC as a remote sticky
3656 * MAC,
3657 * this is a operator error and we must log a warning
3658 */
8f4b98ee 3659 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
421bb26a
MK
3660 zlog_warn(
3661 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
3662 prefix_mac2str(macaddr, buf,
3663 sizeof(buf)),
3664 inet_ntoa(mac->fwd_info.r_vtep_ip),
3665 zvni->vni);
8f4b98ee
MK
3666 return 0;
3667 }
d62a17ae 3668 }
3669 }
3670
3671 /* Locate VRF corresponding to interface. */
3672 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
3673 assert(zvrf);
3674
3675 if (!mac) {
3676 mac = zvni_mac_add(zvni, macaddr);
3677 if (!mac) {
3678 zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u",
3679 ifp->vrf_id,
3680 prefix_mac2str(macaddr, buf, sizeof(buf)),
3681 ifp->name, ifp->ifindex, vid);
3682 return -1;
3683 }
3684 }
3685
3686 /* Set "local" forwarding info. */
3687 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
b6938a74 3688 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 3689 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
b6938a74 3690 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
d62a17ae 3691 mac->fwd_info.local.ifindex = ifp->ifindex;
3692 mac->fwd_info.local.vid = vid;
3693
3694 if (sticky)
3695 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3696 else
3697 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3698
3699 /* Inform BGP if required. */
b6938a74
MK
3700 if (add) {
3701 zvni_process_neigh_on_local_mac_add(zvrf, zvni, mac);
3702 return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr,
3703 sticky);
3704 }
d62a17ae 3705
3706 return 0;
2232a77c 3707}
13d60d35 3708
3709/*
3710 * Handle message from client to delete a remote VTEP for a VNI.
3711 */
d62a17ae 3712int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
3713 struct zebra_vrf *zvrf)
3714{
3715 struct stream *s;
3716 u_short l = 0;
3717 vni_t vni;
3718 struct in_addr vtep_ip;
3719 zebra_vni_t *zvni;
3720 zebra_vtep_t *zvtep;
b5ebdc9b 3721 struct interface *ifp;
3722 struct zebra_if *zif;
d62a17ae 3723
3724 s = client->ibuf;
3725
3726 while (l < length) {
3727 /* Obtain each remote VTEP and process. */
3728 vni = (vni_t)stream_getl(s);
3729 l += 4;
3730 vtep_ip.s_addr = stream_get_ipv4(s);
3731 l += IPV4_MAX_BYTELEN;
3732
3733 if (IS_ZEBRA_DEBUG_VXLAN)
3734 zlog_debug("%u:Recv VTEP_DEL %s VNI %u from %s",
3735 zvrf_id(zvrf), inet_ntoa(vtep_ip), vni,
3736 zebra_route_string(client->proto));
3737
3738 /* Locate VNI hash entry - expected to exist. */
3739 zvni = zvni_lookup(zvrf, vni);
3740 if (!zvni) {
3741 if (IS_ZEBRA_DEBUG_VXLAN)
3742 zlog_debug(
3743 "Failed to locate VNI hash upon remote VTEP DEL, "
3744 "VRF %d VNI %u",
3745 zvrf_id(zvrf), vni);
3746 continue;
3747 }
3748
b5ebdc9b 3749 ifp = zvni->vxlan_if;
3750 if (!ifp) {
b682f6de 3751 zlog_err("VNI %u hash %p doesn't have intf upon remote VTEP DEL",
3752 zvni->vni, zvni);
3753 continue;
b5ebdc9b 3754 }
3755 zif = ifp->info;
3756
3757 /* If down or not mapped to a bridge, we're done. */
b682f6de 3758 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 3759 continue;
3760
d62a17ae 3761 /* If the remote VTEP does not exist, there's nothing more to
3762 * do.
3763 * Otherwise, uninstall any remote MACs pointing to this VTEP
3764 * and
3765 * then, the VTEP entry itself and remove it.
3766 */
3767 zvtep = zvni_vtep_find(zvni, &vtep_ip);
3768 if (!zvtep)
3769 continue;
3770
3771 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
3772 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
3773 zvni_vtep_uninstall(zvni, &vtep_ip);
3774 zvni_vtep_del(zvni, zvtep);
3775 }
3776
3777 return 0;
13d60d35 3778}
3779
3780/*
3781 * Handle message from client to add a remote VTEP for a VNI.
3782 */
d62a17ae 3783int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
3784 struct zebra_vrf *zvrf)
3785{
3786 struct stream *s;
3787 u_short l = 0;
3788 vni_t vni;
3789 struct in_addr vtep_ip;
3790 zebra_vni_t *zvni;
b5ebdc9b 3791 struct interface *ifp;
3792 struct zebra_if *zif;
d62a17ae 3793
3794 assert(EVPN_ENABLED(zvrf));
3795
3796 s = client->ibuf;
3797
3798 while (l < length) {
3799 /* Obtain each remote VTEP and process. */
3800 vni = (vni_t)stream_getl(s);
3801 l += 4;
3802 vtep_ip.s_addr = stream_get_ipv4(s);
3803 l += IPV4_MAX_BYTELEN;
3804
3805 if (IS_ZEBRA_DEBUG_VXLAN)
3806 zlog_debug("%u:Recv VTEP_ADD %s VNI %u from %s",
3807 zvrf_id(zvrf), inet_ntoa(vtep_ip), vni,
3808 zebra_route_string(client->proto));
3809
3810 /* Locate VNI hash entry - expected to exist. */
3811 zvni = zvni_lookup(zvrf, vni);
3812 if (!zvni) {
3813 zlog_err(
3814 "Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u",
3815 zvrf_id(zvrf), vni);
3816 continue;
3817 }
b5ebdc9b 3818
3819 ifp = zvni->vxlan_if;
3820 if (!ifp) {
d62a17ae 3821 zlog_err(
3822 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
3823 zvni->vni, zvni);
3824 continue;
3825 }
3826
b5ebdc9b 3827 zif = ifp->info;
d62a17ae 3828
b5ebdc9b 3829 /* If down or not mapped to a bridge, we're done. */
b682f6de 3830 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 3831 continue;
3832
b682f6de 3833 /* If the remote VTEP already exists,
3834 there's nothing more to do. */
b5ebdc9b 3835 if (zvni_vtep_find(zvni, &vtep_ip))
d62a17ae 3836 continue;
3837
3838 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
3839 zlog_err(
3840 "Failed to add remote VTEP, VRF %d VNI %u zvni %p",
3841 zvrf_id(zvrf), vni, zvni);
3842 continue;
3843 }
3844
3845 zvni_vtep_install(zvni, &vtep_ip);
3846 }
3847
3848 return 0;
13d60d35 3849}
3850
1a98c087
MK
3851/*
3852 * Add/Del gateway macip to evpn
3853 * g/w can be:
3854 * 1. SVI interface on a vlan aware bridge
3855 * 2. SVI interface on a vlan unaware bridge
3856 * 3. vrr interface (MACVLAN) associated to a SVI
3857 * We advertise macip routes for an interface if it is associated to VxLan vlan
3858 */
3859int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
3860 int add)
3861{
3862 struct ipaddr ip;
3863 struct ethaddr macaddr;
3864 zebra_vni_t *zvni = NULL;
3865 struct zebra_vrf *zvrf = NULL;
3866
3867 memset(&ip, 0, sizeof(struct ipaddr));
3868 memset(&macaddr, 0, sizeof(struct ethaddr));
3869
297a21b6
MK
3870 zvrf = vrf_info_lookup(ifp->vrf_id);
3871 if (!zvrf)
3872 return -1;
3873
3874 if (!EVPN_ENABLED(zvrf))
3875 return 0;
3876
1a98c087
MK
3877 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
3878 struct interface *svi_if =
3879 NULL; /* SVI corresponding to the MACVLAN */
3880 struct zebra_if *ifp_zif =
3881 NULL; /* Zebra daemon specific info for MACVLAN */
3882 struct zebra_if *svi_if_zif =
3883 NULL; /* Zebra daemon specific info for SVI*/
3884
3885 ifp_zif = ifp->info;
3886 if (!ifp_zif)
3887 return -1;
3888
3889 svi_if = ifp_zif->link;
3890 if (!svi_if) {
3891 zlog_err("%u:MACVLAN %s(%u) without link information",
3892 ifp->vrf_id, ifp->name, ifp->ifindex);
3893 return -1;
3894 }
3895
3896 if (IS_ZEBRA_IF_VLAN(svi_if)) {
3897 svi_if_zif = svi_if->info;
3898 if (svi_if_zif)
3899 zvni = zvni_map_svi(svi_if, svi_if_zif->link);
3900 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
3901 zvni = zvni_map_svi(svi_if, svi_if);
3902 }
3903 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
3904 struct zebra_if *svi_if_zif =
3905 NULL; /* Zebra daemon specific info for SVI*/
3906
3907 svi_if_zif = ifp->info;
3908 if (svi_if_zif)
3909 zvni = zvni_map_svi(ifp, svi_if_zif->link);
3910 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
3911 zvni = zvni_map_svi(ifp, ifp);
3912 }
3913
3914 if (!zvni)
3915 return 0;
3916
3917 if (!zvni->vxlan_if) {
3918 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
3919 zvni->vni, zvni);
3920 return -1;
3921 }
3922
1a98c087
MK
3923
3924 /* check if we are advertising gw macip routes */
3925 if (!advertise_gw_macip_enabled(zvrf, zvni))
3926 return 0;
3927
3928 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
3929
3930 if (p->family == AF_INET) {
3931 ip.ipa_type = IPADDR_V4;
3932 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
3933 sizeof(struct in_addr));
3934 } else if (p->family == AF_INET6) {
3935 ip.ipa_type = IPADDR_V6;
3936 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
3937 sizeof(struct in6_addr));
3938 }
3939
3940
3941 if (add)
3942 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
3943 else
3944 zvni_gw_macip_del(ifp, zvni, &ip);
3945
3946 return 0;
3947}
3948
2232a77c 3949/*
3950 * Handle SVI interface going down. At this point, this is a NOP since
3951 * the kernel deletes the neighbor entries on this SVI (if any).
3952 */
d62a17ae 3953int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 3954{
d62a17ae 3955 return 0;
2232a77c 3956}
3957
3958/*
3959 * Handle SVI interface coming up. This may or may not be of interest,
3960 * but if this is a SVI on a VxLAN bridge, we need to install any remote
3961 * neighbor entries (which will be used for EVPN ARP suppression).
3962 */
d62a17ae 3963int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 3964{
d62a17ae 3965 zebra_vni_t *zvni;
3966 struct neigh_walk_ctx n_wctx;
2232a77c 3967
d62a17ae 3968 zvni = zvni_map_svi(ifp, link_if);
3969 if (!zvni)
3970 return 0;
2232a77c 3971
d62a17ae 3972 if (!zvni->vxlan_if) {
3973 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
3974 zvni->vni, zvni);
3975 return -1;
3976 }
2232a77c 3977
d62a17ae 3978 if (IS_ZEBRA_DEBUG_VXLAN)
3979 zlog_debug("%u:SVI %s(%u) VNI %u is UP, installing neighbors",
3980 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni);
2232a77c 3981
d62a17ae 3982 /* Install any remote neighbors for this VNI. */
3983 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
3984 n_wctx.zvni = zvni;
3985 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx);
2232a77c 3986
d62a17ae 3987 return 0;
2232a77c 3988}
3989
13d60d35 3990/*
3991 * Handle VxLAN interface down - update BGP if required, and do
3992 * internal cleanup.
3993 */
d62a17ae 3994int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 3995{
d62a17ae 3996 struct zebra_if *zif;
3997 struct zebra_vrf *zvrf;
3998 zebra_vni_t *zvni;
3999 struct zebra_l2info_vxlan *vxl;
4000 vni_t vni;
13d60d35 4001
d62a17ae 4002 /* Locate VRF corresponding to interface. */
4003 zvrf = vrf_info_lookup(ifp->vrf_id);
4004 assert(zvrf);
13d60d35 4005
d62a17ae 4006 /* If EVPN is not enabled, nothing further to be done. */
4007 if (!EVPN_ENABLED(zvrf))
4008 return 0;
13d60d35 4009
d62a17ae 4010 zif = ifp->info;
4011 assert(zif);
4012 vxl = &zif->l2info.vxl;
4013 vni = vxl->vni;
13d60d35 4014
d62a17ae 4015 if (IS_ZEBRA_DEBUG_VXLAN)
4016 zlog_debug("%u:Intf %s(%u) VNI %u is DOWN", ifp->vrf_id,
4017 ifp->name, ifp->ifindex, vni);
13d60d35 4018
d62a17ae 4019 /* Locate hash entry; it is expected to exist. */
4020 zvni = zvni_lookup(zvrf, vni);
4021 if (!zvni) {
4022 zlog_err(
4023 "Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u",
4024 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4025 return -1;
4026 }
13d60d35 4027
d62a17ae 4028 assert(zvni->vxlan_if == ifp);
13d60d35 4029
d62a17ae 4030 /* Delete this VNI from BGP. */
4031 zvni_send_del_to_client(zvrf, zvni->vni);
13d60d35 4032
d62a17ae 4033 /* Free up all neighbors and MACs, if any. */
4034 zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
4035 zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
2232a77c 4036
d62a17ae 4037 /* Free up all remote VTEPs, if any. */
4038 zvni_vtep_del_all(zvni, 1);
13d60d35 4039
d62a17ae 4040 return 0;
13d60d35 4041}
4042
4043/*
4044 * Handle VxLAN interface up - update BGP if required.
4045 */
d62a17ae 4046int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 4047{
d62a17ae 4048 struct zebra_if *zif;
4049 struct zebra_vrf *zvrf;
4050 zebra_vni_t *zvni;
4051 struct zebra_l2info_vxlan *vxl;
4052 vni_t vni;
13d60d35 4053
d62a17ae 4054 /* Locate VRF corresponding to interface. */
4055 zvrf = vrf_info_lookup(ifp->vrf_id);
4056 assert(zvrf);
13d60d35 4057
d62a17ae 4058 /* If EVPN is not enabled, nothing further to be done. */
4059 if (!EVPN_ENABLED(zvrf))
4060 return 0;
13d60d35 4061
d62a17ae 4062 zif = ifp->info;
4063 assert(zif);
4064 vxl = &zif->l2info.vxl;
4065 vni = vxl->vni;
13d60d35 4066
d62a17ae 4067 if (IS_ZEBRA_DEBUG_VXLAN)
4068 zlog_debug("%u:Intf %s(%u) VNI %u is UP", ifp->vrf_id,
4069 ifp->name, ifp->ifindex, vni);
13d60d35 4070
d62a17ae 4071 /* Locate hash entry; it is expected to exist. */
4072 zvni = zvni_lookup(zvrf, vni);
4073 if (!zvni) {
4074 zlog_err(
4075 "Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u",
4076 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4077 return -1;
4078 }
13d60d35 4079
d62a17ae 4080 assert(zvni->vxlan_if == ifp);
13d60d35 4081
d62a17ae 4082 /* If part of a bridge, inform BGP about this VNI. */
4083 /* Also, read and populate local MACs and neighbors. */
4084 if (zif->brslave_info.br_if) {
4085 zvni_send_add_to_client(zvrf, zvni);
4086 zvni_read_mac_neigh(zvrf, zvni, ifp);
4087 }
13d60d35 4088
d62a17ae 4089 return 0;
13d60d35 4090}
4091
4092/*
4093 * Handle VxLAN interface delete. Locate and remove entry in hash table
4094 * and update BGP, if required.
4095 */
d62a17ae 4096int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 4097{
d62a17ae 4098 struct zebra_if *zif;
4099 struct zebra_vrf *zvrf;
4100 zebra_vni_t *zvni;
4101 struct zebra_l2info_vxlan *vxl;
4102 vni_t vni;
13d60d35 4103
d62a17ae 4104 /* Locate VRF corresponding to interface. */
4105 zvrf = vrf_info_lookup(ifp->vrf_id);
4106 assert(zvrf);
13d60d35 4107
d62a17ae 4108 /* If EVPN is not enabled, nothing further to be done. */
4109 if (!EVPN_ENABLED(zvrf))
4110 return 0;
13d60d35 4111
d62a17ae 4112 zif = ifp->info;
4113 assert(zif);
4114 vxl = &zif->l2info.vxl;
4115 vni = vxl->vni;
13d60d35 4116
d62a17ae 4117 if (IS_ZEBRA_DEBUG_VXLAN)
4118 zlog_debug("%u:Del VNI %u intf %s(%u)", ifp->vrf_id, vni,
4119 ifp->name, ifp->ifindex);
13d60d35 4120
d62a17ae 4121 /* Locate hash entry; it is expected to exist. */
4122 zvni = zvni_lookup(zvrf, vni);
4123 if (!zvni) {
4124 zlog_err(
4125 "Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u",
4126 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4127 return 0;
4128 }
13d60d35 4129
d62a17ae 4130 /* Delete VNI from BGP. */
4131 zvni_send_del_to_client(zvrf, zvni->vni);
13d60d35 4132
d62a17ae 4133 /* Free up all neighbors and MAC, if any. */
4134 zvni_neigh_del_all(zvrf, zvni, 0, 0, DEL_ALL_NEIGH);
4135 zvni_mac_del_all(zvrf, zvni, 0, 0, DEL_ALL_MAC);
2232a77c 4136
d62a17ae 4137 /* Free up all remote VTEPs, if any. */
4138 zvni_vtep_del_all(zvni, 0);
13d60d35 4139
d62a17ae 4140 /* Delete the hash entry. */
4141 if (zvni_del(zvrf, zvni)) {
4142 zlog_err("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u",
4143 zvni, ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni);
4144 return -1;
4145 }
13d60d35 4146
d62a17ae 4147 return 0;
13d60d35 4148}
4149
4150/*
4151 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
4152 */
d62a17ae 4153int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
4154{
4155 struct zebra_if *zif;
4156 struct zebra_vrf *zvrf;
4157 zebra_vni_t *zvni;
4158 struct zebra_l2info_vxlan *vxl;
4159 vni_t vni;
4160
4161 /* Locate VRF corresponding to interface. */
4162 zvrf = vrf_info_lookup(ifp->vrf_id);
4163 assert(zvrf);
4164
4165 /* If EVPN is not enabled, nothing further to be done. */
4166 if (!EVPN_ENABLED(zvrf))
4167 return 0;
4168
4169 zif = ifp->info;
4170 assert(zif);
4171 vxl = &zif->l2info.vxl;
4172 vni = vxl->vni;
4173
4174 /* Update VNI hash. */
4175 zvni = zvni_lookup(zvrf, vni);
4176 if (!zvni) {
4177 zlog_err(
4178 "Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u",
4179 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4180 return -1;
4181 }
4182
4183 if (IS_ZEBRA_DEBUG_VXLAN)
4184 zlog_debug(
4185 "%u:Update VNI %u intf %s(%u) VLAN %u local IP %s "
4186 "master %u chg 0x%x",
4187 ifp->vrf_id, vni, ifp->name, ifp->ifindex,
4188 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
4189 zif->brslave_info.bridge_ifindex, chgflags);
4190
af026ae4 4191 /* Removed from bridge? Cleanup and return */
d62a17ae 4192 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
4193 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
4194 /* Delete from client, remove all remote VTEPs */
4195 /* Also, free up all MACs and neighbors. */
4196 zvni_send_del_to_client(zvrf, zvni->vni);
4197 zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
4198 zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
4199 zvni_vtep_del_all(zvni, 1);
af026ae4 4200 return 0;
4201 }
4202
4203 /* Handle other changes. */
4204 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
d62a17ae 4205 /* Remove all existing local neighbors and MACs for this VNI
4206 * (including from BGP)
4207 */
4208 zvni_neigh_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC);
4209 zvni_mac_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC);
4210 }
4211
4212 zvni->local_vtep_ip = vxl->vtep_ip;
4213 zvni->vxlan_if = ifp;
4214
4215 /* Take further actions needed. Note that if we are here, there is a
4216 * change of interest.
4217 */
4218 /* If down or not mapped to a bridge, we're done. */
4219 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4220 return 0;
4221
4222 /* Inform BGP, if there is a change of interest. */
4223 if (chgflags
4224 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
4225 zvni_send_add_to_client(zvrf, zvni);
4226
4227 /* If there is a valid new master or a VLAN mapping change, read and
4228 * populate local MACs and neighbors. Also, reinstall any remote MACs
4229 * and neighbors for this VNI (based on new VLAN).
4230 */
4231 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
4232 zvni_read_mac_neigh(zvrf, zvni, ifp);
4233 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
4234 struct mac_walk_ctx m_wctx;
4235 struct neigh_walk_ctx n_wctx;
4236
4237 zvni_read_mac_neigh(zvrf, zvni, ifp);
4238
4239 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
4240 m_wctx.zvni = zvni;
4241 hash_iterate(zvni->mac_table, zvni_install_mac_hash, &m_wctx);
4242
4243 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
4244 n_wctx.zvni = zvni;
4245 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
4246 &n_wctx);
4247 }
4248
4249 return 0;
13d60d35 4250}
4251
4252/*
4253 * Handle VxLAN interface add.
4254 */
d62a17ae 4255int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 4256{
d62a17ae 4257 struct zebra_if *zif;
4258 struct zebra_vrf *zvrf;
4259 zebra_vni_t *zvni;
4260 struct zebra_l2info_vxlan *vxl;
4261 vni_t vni;
13d60d35 4262
d62a17ae 4263 /* Locate VRF corresponding to interface. */
4264 zvrf = vrf_info_lookup(ifp->vrf_id);
4265 assert(zvrf);
13d60d35 4266
d62a17ae 4267 /* If EVPN is not enabled, nothing further to be done. */
4268 if (!EVPN_ENABLED(zvrf))
4269 return 0;
13d60d35 4270
d62a17ae 4271 zif = ifp->info;
4272 assert(zif);
4273 vxl = &zif->l2info.vxl;
4274 vni = vxl->vni;
13d60d35 4275
d62a17ae 4276 if (IS_ZEBRA_DEBUG_VXLAN)
4277 zlog_debug(
4278 "%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u",
4279 ifp->vrf_id, vni, ifp->name, ifp->ifindex,
4280 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
4281 zif->brslave_info.bridge_ifindex);
13d60d35 4282
d62a17ae 4283 /* Create or update VNI hash. */
4284 zvni = zvni_lookup(zvrf, vni);
4285 if (!zvni) {
4286 zvni = zvni_add(zvrf, vni);
4287 if (!zvni) {
4288 zlog_err(
4289 "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u",
4290 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4291 return -1;
4292 }
4293 }
13d60d35 4294
d62a17ae 4295 zvni->local_vtep_ip = vxl->vtep_ip;
4296 zvni->vxlan_if = ifp;
13d60d35 4297
d62a17ae 4298 /* If down or not mapped to a bridge, we're done. */
4299 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4300 return 0;
13d60d35 4301
d62a17ae 4302 /* Inform BGP */
4303 zvni_send_add_to_client(zvrf, zvni);
13d60d35 4304
d62a17ae 4305 /* Read and populate local MACs and neighbors */
4306 zvni_read_mac_neigh(zvrf, zvni, ifp);
2232a77c 4307
d62a17ae 4308 return 0;
13d60d35 4309}
4310
1a98c087
MK
4311/*
4312 * Handle message from client to enable/disable advertisement of g/w macip
4313 * routes
4314 */
4315int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
4316 u_short length, struct zebra_vrf *zvrf)
4317{
4318 struct stream *s;
4319 int advertise;
4320 vni_t vni = 0;
4321 zebra_vni_t *zvni = NULL;
b5ebdc9b 4322 struct interface *ifp = NULL;
1a98c087
MK
4323
4324 s = client->ibuf;
4325 advertise = stream_getc(s);
4326 vni = stream_get3(s);
4327
4328 if (!vni) {
4329 if (IS_ZEBRA_DEBUG_VXLAN)
4330 zlog_debug("%u:EVPN gateway macip Adv %s, currently %s",
4331 zvrf_id(zvrf),
4332 advertise ? "enabled" : "disabled",
4333 advertise_gw_macip_enabled(zvrf, NULL)
4334 ? "enabled"
4335 : "disabled");
4336
4337 if (zvrf->advertise_gw_macip == advertise)
4338 return 0;
4339
4340 zvrf->advertise_gw_macip = advertise;
4341
4342 if (advertise_gw_macip_enabled(zvrf, zvni))
4343 hash_iterate(zvrf->vni_table,
4344 zvni_gw_macip_add_for_vni_hash, zvrf);
4345 else
4346 hash_iterate(zvrf->vni_table,
4347 zvni_gw_macip_del_for_vni_hash, zvrf);
4348
4349 } else {
4350 struct zebra_if *zif = NULL;
4351 struct zebra_l2info_vxlan zl2_info;
4352 struct interface *vlan_if = NULL;
4353 struct interface *vrr_if = NULL;
4354
4355 if (IS_ZEBRA_DEBUG_VXLAN)
4356 zlog_debug(
4357 "%u:EVPN gateway macip Adv %s on VNI %d , currently %s",
4358 zvrf_id(zvrf),
4359 advertise ? "enabled" : "disabled", vni,
4360 advertise_gw_macip_enabled(zvrf, zvni)
4361 ? "enabled"
4362 : "disabled");
4363
4364 zvni = zvni_lookup(zvrf, vni);
4365 if (!zvni)
4366 return 0;
4367
4368 if (zvni->advertise_gw_macip == advertise)
4369 return 0;
4370
4371 zvni->advertise_gw_macip = advertise;
4372
b5ebdc9b 4373 ifp = zvni->vxlan_if;
4374 if (!ifp)
4375 return 0;
4376
4377 zif = ifp->info;
4378
4379 /* If down or not mapped to a bridge, we're done. */
b682f6de 4380 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 4381 return 0;
4382
1a98c087
MK
4383 zl2_info = zif->l2info.vxl;
4384
4385 vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
4386 zif->brslave_info.br_if);
4387 if (!vlan_if)
4388 return 0;
4389
4390 if (advertise_gw_macip_enabled(zvrf, zvni)) {
4391 /* Add primary SVI MAC-IP */
4392 zvni_add_macip_for_intf(vlan_if, zvni);
4393
4394 /* Add VRR MAC-IP - if any*/
4395 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
4396 if (vrr_if)
4397 zvni_add_macip_for_intf(vrr_if, zvni);
4398 } else {
4399 /* Del primary MAC-IP */
4400 zvni_del_macip_for_intf(vlan_if, zvni);
4401
4402 /* Del VRR MAC-IP - if any*/
4403 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
4404 if (vrr_if)
4405 zvni_del_macip_for_intf(vrr_if, zvni);
4406 }
4407 }
4408
4409 return 0;
4410}
4411
4412
13d60d35 4413/*
4414 * Handle message from client to learn (or stop learning) about VNIs and MACs.
4415 * When enabled, the VNI hash table will be built and MAC FDB table read;
4416 * when disabled, the entries should be deleted and remote VTEPs and MACs
4417 * uninstalled from the kernel.
4418 */
d62a17ae 4419int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock,
4420 u_short length, struct zebra_vrf *zvrf)
13d60d35 4421{
d62a17ae 4422 struct stream *s;
4423 int advertise;
13d60d35 4424
d62a17ae 4425 s = client->ibuf;
4426 advertise = stream_getc(s);
13d60d35 4427
d62a17ae 4428 if (IS_ZEBRA_DEBUG_VXLAN)
4429 zlog_debug("%u:EVPN VNI Adv %s, currently %s", zvrf_id(zvrf),
4430 advertise ? "enabled" : "disabled",
4431 EVPN_ENABLED(zvrf) ? "enabled" : "disabled");
13d60d35 4432
d62a17ae 4433 if (zvrf->advertise_all_vni == advertise)
4434 return 0;
13d60d35 4435
d62a17ae 4436 zvrf->advertise_all_vni = advertise;
4437 if (EVPN_ENABLED(zvrf)) {
4438 /* Build VNI hash table and inform BGP. */
4439 zvni_build_hash_table(zvrf);
2232a77c 4440
1a98c087
MK
4441 /* Add all SVI (L3 GW) MACs to BGP*/
4442 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
4443 zvrf);
4444
d62a17ae 4445 /* Read the MAC FDB */
4446 macfdb_read(zvrf->zns);
2232a77c 4447
d62a17ae 4448 /* Read neighbors */
4449 neigh_read(zvrf->zns);
4450 } else {
4451 /* Cleanup VTEPs for all VNIs - uninstall from
4452 * kernel and free entries.
4453 */
4454 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
4455 }
13d60d35 4456
d62a17ae 4457 return 0;
13d60d35 4458}
4459
4460/*
4461 * Allocate VNI hash table for this VRF and do other initialization.
4462 * NOTE: Currently supported only for default VRF.
4463 */
d62a17ae 4464void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 4465{
d62a17ae 4466 if (!zvrf)
4467 return;
4468 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
4469 "Zebra VRF VNI Table");
13d60d35 4470}
4471
4472/* Close all VNI handling */
d62a17ae 4473void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 4474{
d62a17ae 4475 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9b67b514 4476 hash_free(zvrf->vni_table);
13d60d35 4477}