]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
Merge pull request #1059 from opensourcerouting/oldbits-1
[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
71349e03
MK
1780 if (!br_if)
1781 return NULL;
1782
d62a17ae 1783 /* Make sure the linked interface is a bridge. */
1784 if (!IS_ZEBRA_IF_BRIDGE(br_if))
1785 return NULL;
1786
1787 /* Locate VRF corresponding to interface. */
1788 zvrf = vrf_info_lookup(ifp->vrf_id);
1789 assert(zvrf);
1790
1791 /* Determine if bridge is VLAN-aware or not */
1792 zif = br_if->info;
1793 assert(zif);
1794 br = &zif->l2info.br;
1795 bridge_vlan_aware = br->vlan_aware;
1796 if (bridge_vlan_aware) {
1797 struct zebra_l2info_vlan *vl;
1798
1799 if (!IS_ZEBRA_IF_VLAN(ifp))
1800 return NULL;
1801
1802 zif = ifp->info;
1803 assert(zif);
1804 vl = &zif->l2info.vl;
1805 vid = vl->vid;
1806 }
1807
1808 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1809 /* TODO: Optimize with a hash. */
1810 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
1811 zif = tmp_if->info;
1812 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1813 continue;
1814 if (!if_is_operative(tmp_if))
1815 continue;
1816 vxl = &zif->l2info.vxl;
1817
1818 if (zif->brslave_info.br_if != br_if)
1819 continue;
1820
1821 if (!bridge_vlan_aware)
1822 break;
1823
1824 if (vxl->access_vlan == vid)
1825 break;
1826 }
1827
1828 if (!tmp_if)
1829 return NULL;
1830
1831 zvni = zvni_lookup(zvrf, vxl->vni);
1832 return zvni;
2232a77c 1833}
1834
1835/* Map to SVI on bridge corresponding to specified VLAN. This can be one
1836 * of two cases:
1837 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
1838 * linked to the bridge
1839 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
1840 * itself
1841 */
d62a17ae 1842static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid,
1843 struct interface *br_if)
1844{
1845 struct listnode *node;
1846 struct interface *tmp_if;
1847 struct zebra_if *zif;
1848 struct zebra_l2info_bridge *br;
1849 struct zebra_l2info_vlan *vl;
1850 u_char bridge_vlan_aware;
1851
b5ebdc9b 1852 /* Defensive check, caller expected to invoke only with valid bridge. */
1853 if (!br_if)
1854 return NULL;
1855
d62a17ae 1856 /* Determine if bridge is VLAN-aware or not */
1857 zif = br_if->info;
1858 assert(zif);
1859 br = &zif->l2info.br;
1860 bridge_vlan_aware = br->vlan_aware;
1861
1862 /* Check oper status of the SVI. */
1863 if (!bridge_vlan_aware)
1864 return if_is_operative(br_if) ? br_if : NULL;
1865
1866 /* Identify corresponding VLAN interface. */
1867 /* TODO: Optimize with a hash. */
1868 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) {
1869 /* Check oper status of the SVI. */
1870 if (!if_is_operative(tmp_if))
1871 continue;
1872 zif = tmp_if->info;
1873 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
1874 || zif->link != br_if)
1875 continue;
1876 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
1877
1878 if (vl->vid == vid)
1879 break;
1880 }
1881
1882 return tmp_if;
2232a77c 1883}
1884
1885/*
1886 * Install remote MAC into the kernel.
1887 */
d62a17ae 1888static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
2232a77c 1889{
d62a17ae 1890 struct zebra_if *zif;
1891 struct zebra_l2info_vxlan *vxl;
1892 u_char sticky;
2232a77c 1893
d62a17ae 1894 if (!(mac->flags & ZEBRA_MAC_REMOTE))
1895 return 0;
2232a77c 1896
d62a17ae 1897 zif = zvni->vxlan_if->info;
1898 if (!zif)
1899 return -1;
1900 vxl = &zif->l2info.vxl;
2232a77c 1901
d62a17ae 1902 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
c85c03c7 1903
d62a17ae 1904 return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
1905 mac->fwd_info.r_vtep_ip, sticky);
2232a77c 1906}
1907
1908/*
1909 * Uninstall remote MAC from the kernel. In the scenario where the MAC
1910 * moves to remote, we have to uninstall any existing local entry first.
1911 */
d62a17ae 1912static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local)
2232a77c 1913{
d62a17ae 1914 struct zebra_if *zif;
1915 struct zebra_l2info_vxlan *vxl;
1916 struct in_addr vtep_ip = {.s_addr = 0};
1917 struct zebra_ns *zns;
1918 struct interface *ifp;
2232a77c 1919
d62a17ae 1920 if (!local && !(mac->flags & ZEBRA_MAC_REMOTE))
1921 return 0;
2232a77c 1922
d62a17ae 1923 if (!zvni->vxlan_if) {
1924 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1925 zvni->vni, zvni);
1926 return -1;
1927 }
2232a77c 1928
d62a17ae 1929 zif = zvni->vxlan_if->info;
1930 if (!zif)
1931 return -1;
1932 vxl = &zif->l2info.vxl;
2232a77c 1933
d62a17ae 1934 if (local) {
1935 zns = zebra_ns_lookup(NS_DEFAULT);
1936 ifp = if_lookup_by_index_per_ns(zns,
1937 mac->fwd_info.local.ifindex);
1938 if (!ifp) // unexpected
1939 return -1;
1940 } else {
1941 ifp = zvni->vxlan_if;
1942 vtep_ip = mac->fwd_info.r_vtep_ip;
1943 }
2232a77c 1944
d62a17ae 1945 return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip,
1946 local);
2232a77c 1947}
1948
1949/*
1950 * Install MAC hash entry - called upon access VLAN change.
1951 */
d62a17ae 1952static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
2232a77c 1953{
d62a17ae 1954 zebra_mac_t *mac;
1955 struct mac_walk_ctx *wctx = ctxt;
2232a77c 1956
d62a17ae 1957 mac = (zebra_mac_t *)backet->data;
1958 if (!mac)
1959 return;
2232a77c 1960
d62a17ae 1961 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
1962 zvni_mac_install(wctx->zvni, mac);
2232a77c 1963}
1964
1965/*
1966 * Decrement neighbor refcount of MAC; uninstall and free it if
1967 * appropriate.
1968 */
d62a17ae 1969static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
1970 int uninstall)
2232a77c 1971{
0a97666d
MK
1972 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ||
1973 !list_isempty(mac->neigh_list))
d62a17ae 1974 return;
2232a77c 1975
d62a17ae 1976 if (uninstall)
1977 zvni_mac_uninstall(zvni, mac, 0);
2232a77c 1978
d62a17ae 1979 zvni_mac_del(zvni, mac);
2232a77c 1980}
1981
1982/*
1983 * Read and populate local MACs and neighbors corresponding to this VNI.
1984 */
d62a17ae 1985static void zvni_read_mac_neigh(struct zebra_vrf *zvrf, zebra_vni_t *zvni,
1986 struct interface *ifp)
2232a77c 1987{
d62a17ae 1988 struct zebra_if *zif;
1989 struct interface *vlan_if;
1990 struct zebra_l2info_vxlan *vxl;
1a98c087 1991 struct interface *vrr_if;
2232a77c 1992
d62a17ae 1993 zif = ifp->info;
1994 vxl = &zif->l2info.vxl;
2232a77c 1995
d62a17ae 1996 if (IS_ZEBRA_DEBUG_VXLAN)
1997 zlog_debug(
1998 "%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
1999 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
2000 zif->brslave_info.bridge_ifindex);
2232a77c 2001
d62a17ae 2002 macfdb_read_for_bridge(zvrf->zns, ifp, zif->brslave_info.br_if);
2003 vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan,
2004 zif->brslave_info.br_if);
1a98c087
MK
2005 if (vlan_if) {
2006
2007 if (advertise_gw_macip_enabled(zvrf, zvni)) {
2008 /* Add SVI MAC-IP */
2009 zvni_add_macip_for_intf(vlan_if, zvni);
2010
2011 /* Add VRR MAC-IP - if any*/
2012 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2013 if (vrr_if)
2014 zvni_add_macip_for_intf(vrr_if, zvni);
2015 }
2016
d62a17ae 2017 neigh_read_for_vlan(zvrf->zns, vlan_if);
1a98c087 2018 }
2232a77c 2019}
2020
2021/*
2022 * Hash function for VNI.
2023 */
d62a17ae 2024static unsigned int vni_hash_keymake(void *p)
2232a77c 2025{
d62a17ae 2026 const zebra_vni_t *zvni = p;
2232a77c 2027
d62a17ae 2028 return (jhash_1word(zvni->vni, 0));
2232a77c 2029}
2030
2031/*
2032 * Compare 2 VNI hash entries.
2033 */
d62a17ae 2034static int vni_hash_cmp(const void *p1, const void *p2)
2232a77c 2035{
d62a17ae 2036 const zebra_vni_t *zvni1 = p1;
2037 const zebra_vni_t *zvni2 = p2;
2232a77c 2038
d62a17ae 2039 return (zvni1->vni == zvni2->vni);
2232a77c 2040}
2041
2042/*
2043 * Callback to allocate VNI hash entry.
2044 */
d62a17ae 2045static void *zvni_alloc(void *p)
2232a77c 2046{
d62a17ae 2047 const zebra_vni_t *tmp_vni = p;
2048 zebra_vni_t *zvni;
2232a77c 2049
d62a17ae 2050 zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t));
2051 zvni->vni = tmp_vni->vni;
2052 return ((void *)zvni);
2232a77c 2053}
2054
2055/*
2056 * Look up VNI hash entry.
2057 */
d62a17ae 2058static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni)
2232a77c 2059{
d62a17ae 2060 zebra_vni_t tmp_vni;
2061 zebra_vni_t *zvni = NULL;
2232a77c 2062
d62a17ae 2063 memset(&tmp_vni, 0, sizeof(zebra_vni_t));
2064 tmp_vni.vni = vni;
2065 zvni = hash_lookup(zvrf->vni_table, &tmp_vni);
2232a77c 2066
d62a17ae 2067 return zvni;
2232a77c 2068}
2069
2070/*
2071 * Add VNI hash entry.
2072 */
d62a17ae 2073static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni)
2232a77c 2074{
d62a17ae 2075 zebra_vni_t tmp_zvni;
2076 zebra_vni_t *zvni = NULL;
2232a77c 2077
d62a17ae 2078 memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
2079 tmp_zvni.vni = vni;
2080 zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc);
2081 assert(zvni);
2232a77c 2082
d62a17ae 2083 /* Create hash table for MAC */
2084 zvni->mac_table =
2085 hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table");
2232a77c 2086
d62a17ae 2087 /* Create hash table for neighbors */
2088 zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp,
2089 "Zebra VNI Neighbor Table");
2232a77c 2090
d62a17ae 2091 return zvni;
2232a77c 2092}
2093
2094/*
2095 * Delete VNI hash entry.
2096 */
d62a17ae 2097static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni)
2232a77c 2098{
d62a17ae 2099 zebra_vni_t *tmp_zvni;
2232a77c 2100
d62a17ae 2101 zvni->vxlan_if = NULL;
2232a77c 2102
d62a17ae 2103 /* Free the neighbor hash table. */
2104 hash_free(zvni->neigh_table);
2105 zvni->neigh_table = NULL;
2232a77c 2106
d62a17ae 2107 /* Free the MAC hash table. */
2108 hash_free(zvni->mac_table);
2109 zvni->mac_table = NULL;
2232a77c 2110
d62a17ae 2111 /* Free the VNI hash entry and allocated memory. */
2112 tmp_zvni = hash_release(zvrf->vni_table, zvni);
2113 if (tmp_zvni)
2114 XFREE(MTYPE_ZVNI, tmp_zvni);
2232a77c 2115
d62a17ae 2116 return 0;
2232a77c 2117}
2118
2119/*
2120 * Inform BGP about local VNI addition.
2121 */
d62a17ae 2122static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni)
2232a77c 2123{
d62a17ae 2124 struct zserv *client;
2125 struct stream *s;
2232a77c 2126
d62a17ae 2127 client = zebra_find_client(ZEBRA_ROUTE_BGP);
2128 /* BGP may not be running. */
2129 if (!client)
2130 return 0;
2232a77c 2131
d62a17ae 2132 s = client->obuf;
2133 stream_reset(s);
2232a77c 2134
d62a17ae 2135 zserv_create_header(s, ZEBRA_VNI_ADD, zvrf_id(zvrf));
2136 stream_putl(s, zvni->vni);
2137 stream_put_in_addr(s, &zvni->local_vtep_ip);
2232a77c 2138
d62a17ae 2139 /* Write packet size. */
2140 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 2141
d62a17ae 2142 if (IS_ZEBRA_DEBUG_VXLAN)
2143 zlog_debug("%u:Send VNI_ADD %u %s to %s", zvrf_id(zvrf),
2144 zvni->vni, inet_ntoa(zvni->local_vtep_ip),
2145 zebra_route_string(client->proto));
2232a77c 2146
d62a17ae 2147 client->vniadd_cnt++;
2148 return zebra_server_send_message(client);
2232a77c 2149}
2150
2151/*
2152 * Inform BGP about local VNI deletion.
2153 */
d62a17ae 2154static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni)
2232a77c 2155{
d62a17ae 2156 struct zserv *client;
2157 struct stream *s;
2232a77c 2158
d62a17ae 2159 client = zebra_find_client(ZEBRA_ROUTE_BGP);
2160 /* BGP may not be running. */
2161 if (!client)
2162 return 0;
2232a77c 2163
d62a17ae 2164 s = client->obuf;
2165 stream_reset(s);
2232a77c 2166
d62a17ae 2167 zserv_create_header(s, ZEBRA_VNI_DEL, zvrf_id(zvrf));
2168 stream_putl(s, vni);
2232a77c 2169
d62a17ae 2170 /* Write packet size. */
2171 stream_putw_at(s, 0, stream_get_endp(s));
2232a77c 2172
d62a17ae 2173 if (IS_ZEBRA_DEBUG_VXLAN)
2174 zlog_debug("%u:Send VNI_DEL %u to %s", zvrf_id(zvrf), vni,
2175 zebra_route_string(client->proto));
2232a77c 2176
d62a17ae 2177 client->vnidel_cnt++;
2178 return zebra_server_send_message(client);
2232a77c 2179}
2180
2181/*
2182 * Build the VNI hash table by going over the VxLAN interfaces. This
2183 * is called when EVPN (advertise-all-vni) is enabled.
2184 */
d62a17ae 2185static void zvni_build_hash_table(struct zebra_vrf *zvrf)
2232a77c 2186{
d62a17ae 2187 struct listnode *node;
2188 struct interface *ifp;
2232a77c 2189
d62a17ae 2190 /* Walk VxLAN interfaces and create VNI hash. */
2191 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, ifp)) {
2192 struct zebra_if *zif;
2193 struct zebra_l2info_vxlan *vxl;
2194 zebra_vni_t *zvni;
2195 vni_t vni;
2232a77c 2196
d62a17ae 2197 zif = ifp->info;
2198 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2199 continue;
2200 vxl = &zif->l2info.vxl;
2232a77c 2201
d62a17ae 2202 vni = vxl->vni;
2232a77c 2203
d62a17ae 2204 if (IS_ZEBRA_DEBUG_VXLAN)
2205 zlog_debug(
2206 "%u:Create VNI hash for intf %s(%u) VNI %u local IP %s",
2207 zvrf_id(zvrf), ifp->name, ifp->ifindex, vni,
2208 inet_ntoa(vxl->vtep_ip));
2232a77c 2209
d62a17ae 2210 /* VNI hash entry is not expected to exist. */
2211 zvni = zvni_lookup(zvrf, vni);
2212 if (zvni) {
2213 zlog_err(
2214 "VNI hash already present for VRF %d IF %s(%u) VNI %u",
2215 zvrf_id(zvrf), ifp->name, ifp->ifindex, vni);
2216 continue;
2217 }
2232a77c 2218
d62a17ae 2219 zvni = zvni_add(zvrf, vni);
2220 if (!zvni) {
2221 zlog_err(
2222 "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u",
2223 zvrf_id(zvrf), ifp->name, ifp->ifindex, vni);
2224 return;
2225 }
2232a77c 2226
d62a17ae 2227 zvni->local_vtep_ip = vxl->vtep_ip;
2228 zvni->vxlan_if = ifp;
2232a77c 2229
d62a17ae 2230 /* Inform BGP if interface is up and mapped to bridge. */
2231 if (if_is_operative(ifp) && zif->brslave_info.br_if)
2232 zvni_send_add_to_client(zvrf, zvni);
2233 }
2232a77c 2234}
2235
2236/*
2237 * See if remote VTEP matches with prefix.
2238 */
d62a17ae 2239static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
2232a77c 2240{
d62a17ae 2241 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
2232a77c 2242}
2243
2244/*
2245 * Locate remote VTEP in VNI hash table.
2246 */
d62a17ae 2247static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2248{
d62a17ae 2249 zebra_vtep_t *zvtep;
2232a77c 2250
d62a17ae 2251 if (!zvni)
2252 return NULL;
2232a77c 2253
d62a17ae 2254 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2255 if (zvni_vtep_match(vtep_ip, zvtep))
2256 break;
2257 }
2232a77c 2258
d62a17ae 2259 return zvtep;
2232a77c 2260}
2261
2262/*
2263 * Add remote VTEP to VNI hash table.
2264 */
d62a17ae 2265static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2266{
d62a17ae 2267 zebra_vtep_t *zvtep;
2232a77c 2268
d62a17ae 2269 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
2270 if (!zvtep) {
2271 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni->vni);
2272 return NULL;
2273 }
2232a77c 2274
d62a17ae 2275 zvtep->vtep_ip = *vtep_ip;
2232a77c 2276
d62a17ae 2277 if (zvni->vteps)
2278 zvni->vteps->prev = zvtep;
2279 zvtep->next = zvni->vteps;
2280 zvni->vteps = zvtep;
2232a77c 2281
d62a17ae 2282 return zvtep;
2232a77c 2283}
2284
2285/*
2286 * Remove remote VTEP from VNI hash table.
2287 */
d62a17ae 2288static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
2232a77c 2289{
d62a17ae 2290 if (zvtep->next)
2291 zvtep->next->prev = zvtep->prev;
2292 if (zvtep->prev)
2293 zvtep->prev->next = zvtep->next;
2294 else
2295 zvni->vteps = zvtep->next;
2232a77c 2296
d62a17ae 2297 zvtep->prev = zvtep->next = NULL;
2298 XFREE(MTYPE_ZVNI_VTEP, zvtep);
2232a77c 2299
d62a17ae 2300 return 0;
2232a77c 2301}
2302
2303/*
2304 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2305 * uninstall from kernel if asked to.
2306 */
d62a17ae 2307static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
2232a77c 2308{
d62a17ae 2309 zebra_vtep_t *zvtep, *zvtep_next;
2232a77c 2310
d62a17ae 2311 if (!zvni)
2312 return -1;
2232a77c 2313
d62a17ae 2314 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
2315 zvtep_next = zvtep->next;
2316 if (uninstall)
2317 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
2318 zvni_vtep_del(zvni, zvtep);
2319 }
2232a77c 2320
d62a17ae 2321 return 0;
2232a77c 2322}
2323
2324/*
2325 * Install remote VTEP into the kernel.
2326 */
d62a17ae 2327static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2328{
d62a17ae 2329 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2330}
2331
2332/*
2333 * Uninstall remote VTEP from the kernel.
2334 */
d62a17ae 2335static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2232a77c 2336{
d62a17ae 2337 if (!zvni->vxlan_if) {
2338 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2339 zvni->vni, zvni);
2340 return -1;
2341 }
2232a77c 2342
d62a17ae 2343 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
2232a77c 2344}
2345
2346/*
2347 * Cleanup VNI/VTEP and update kernel
2348 */
d62a17ae 2349static void zvni_cleanup_all(struct hash_backet *backet, void *zvrf)
2232a77c 2350{
d62a17ae 2351 zebra_vni_t *zvni;
2232a77c 2352
d62a17ae 2353 zvni = (zebra_vni_t *)backet->data;
2354 if (!zvni)
2355 return;
2232a77c 2356
d62a17ae 2357 /* Free up all neighbors and MACs, if any. */
2358 zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
2359 zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
2232a77c 2360
d62a17ae 2361 /* Free up all remote VTEPs, if any. */
2362 zvni_vtep_del_all(zvni, 1);
2232a77c 2363
d62a17ae 2364 /* Delete the hash entry. */
2365 zvni_del(zvrf, zvni);
2232a77c 2366}
2367
2368
2369/* Public functions */
2370
cec2e17d 2371/*
2372 * Display Neighbors for a VNI (VTY command handler).
2373 */
d62a17ae 2374void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 2375 vni_t vni, u_char use_json)
d62a17ae 2376{
2377 zebra_vni_t *zvni;
2378 u_int32_t num_neigh;
2379 struct neigh_walk_ctx wctx;
cd233079 2380 json_object *json = NULL;
d62a17ae 2381
2382 if (!EVPN_ENABLED(zvrf))
2383 return;
2384 zvni = zvni_lookup(zvrf, vni);
2385 if (!zvni) {
cd233079
CS
2386 if (use_json)
2387 vty_out(vty, "{}\n");
2388 else
2389 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2390 return;
2391 }
2392 num_neigh = hashcount(zvni->neigh_table);
2393 if (!num_neigh)
2394 return;
2395
cd233079
CS
2396 if (use_json)
2397 json = json_object_new_object();
2398
d62a17ae 2399 /* Since we have IPv6 addresses to deal with which can vary widely in
2400 * size, we try to be a bit more elegant in display by first computing
2401 * the maximum width.
2402 */
2403 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2404 wctx.zvni = zvni;
2405 wctx.vty = vty;
2406 wctx.addr_width = 15;
cd233079 2407 wctx.json = json;
d62a17ae 2408 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
2409
cd233079
CS
2410 if (!use_json) {
2411 vty_out(vty,
2412 "Number of ARPs (local and remote) known for this VNI: %u\n",
2413 num_neigh);
2414 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
2415 "Type", "MAC", "Remote VTEP");
2416 } else
2417 json_object_int_add(json, "numArpNd", num_neigh);
d62a17ae 2418
2419 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
2420 if (use_json) {
2421 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2422 json, JSON_C_TO_STRING_PRETTY));
2423 json_object_free(json);
2424 }
cec2e17d 2425}
2426
2427/*
2428 * Display neighbors across all VNIs (VTY command handler).
2429 */
cd233079
CS
2430void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
2431 u_char use_json)
cec2e17d 2432{
cd233079
CS
2433 json_object *json = NULL;
2434 void *args[2];
2435
d62a17ae 2436 if (!EVPN_ENABLED(zvrf))
2437 return;
cd233079
CS
2438
2439 if (use_json)
2440 json = json_object_new_object();
2441
2442 args[0] = vty;
2443 args[1] = json;
2444 hash_iterate(zvrf->vni_table,
2445 (void (*)(struct hash_backet *,
2446 void *))zvni_print_neigh_hash_all_vni,
2447 args);
2448 if (use_json) {
2449 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2450 json, JSON_C_TO_STRING_PRETTY));
2451 json_object_free(json);
2452 }
cec2e17d 2453}
2454
2455/*
2456 * Display specific neighbor for a VNI, if present (VTY command handler).
2457 */
d62a17ae 2458void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
2459 struct zebra_vrf *zvrf, vni_t vni,
cd233079 2460 struct ipaddr *ip, u_char use_json)
cec2e17d 2461{
d62a17ae 2462 zebra_vni_t *zvni;
2463 zebra_neigh_t *n;
cd233079 2464 json_object *json = NULL;
cec2e17d 2465
d62a17ae 2466 if (!EVPN_ENABLED(zvrf))
2467 return;
2468 zvni = zvni_lookup(zvrf, vni);
2469 if (!zvni) {
cd233079
CS
2470 if (use_json)
2471 vty_out(vty, "{}\n");
2472 else
2473 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2474 return;
2475 }
2476 n = zvni_neigh_lookup(zvni, ip);
2477 if (!n) {
cd233079
CS
2478 if (!use_json)
2479 vty_out(vty,
2480 "%% Requested neighbor does not exist in VNI %u\n",
2481 vni);
d62a17ae 2482 return;
2483 }
cd233079
CS
2484 if (use_json)
2485 json = json_object_new_object();
2486
2487 zvni_print_neigh(n, vty, json);
cec2e17d 2488
cd233079
CS
2489 if (use_json) {
2490 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2491 json, JSON_C_TO_STRING_PRETTY));
2492 json_object_free(json);
2493 }
cec2e17d 2494}
2495
2496/*
2497 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2498 * By definition, these are remote neighbors.
2499 */
d62a17ae 2500void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
2501 vni_t vni, struct in_addr vtep_ip,
2502 u_char use_json)
cec2e17d 2503{
d62a17ae 2504 zebra_vni_t *zvni;
2505 u_int32_t num_neigh;
2506 struct neigh_walk_ctx wctx;
cd233079 2507 json_object *json = NULL;
cec2e17d 2508
d62a17ae 2509 if (!EVPN_ENABLED(zvrf))
2510 return;
2511 zvni = zvni_lookup(zvrf, vni);
2512 if (!zvni) {
cd233079
CS
2513 if (use_json)
2514 vty_out(vty, "{}\n");
2515 else
2516 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2517 return;
2518 }
2519 num_neigh = hashcount(zvni->neigh_table);
2520 if (!num_neigh)
2521 return;
cec2e17d 2522
d62a17ae 2523 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2524 wctx.zvni = zvni;
2525 wctx.vty = vty;
2526 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
2527 wctx.r_vtep_ip = vtep_ip;
cd233079 2528 wctx.json = json;
d62a17ae 2529 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
cd233079
CS
2530
2531 if (use_json) {
2532 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2533 json, JSON_C_TO_STRING_PRETTY));
2534 json_object_free(json);
2535 }
cec2e17d 2536}
2537
2538/*
2539 * Display MACs for a VNI (VTY command handler).
2540 */
d62a17ae 2541void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 2542 vni_t vni, u_char use_json)
cec2e17d 2543{
d62a17ae 2544 zebra_vni_t *zvni;
2545 u_int32_t num_macs;
2546 struct mac_walk_ctx wctx;
cd233079
CS
2547 json_object *json = NULL;
2548 json_object *json_mac = NULL;
cec2e17d 2549
d62a17ae 2550 if (!EVPN_ENABLED(zvrf))
2551 return;
2552 zvni = zvni_lookup(zvrf, vni);
2553 if (!zvni) {
cd233079
CS
2554 if (use_json)
2555 vty_out(vty, "{}\n");
2556 else
2557 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2558 return;
2559 }
2560 num_macs = hashcount(zvni->mac_table);
2561 if (!num_macs)
2562 return;
cec2e17d 2563
cd233079
CS
2564 if (use_json) {
2565 json = json_object_new_object();
2566 json_mac = json_object_new_object();
2567 }
2568
d62a17ae 2569 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2570 wctx.zvni = zvni;
2571 wctx.vty = vty;
cd233079 2572 wctx.json = json_mac;
cec2e17d 2573
cd233079
CS
2574 if (!use_json) {
2575 vty_out(vty,
2576 "Number of MACs (local and remote) known for this VNI: %u\n",
2577 num_macs);
2578 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
2579 "Intf/Remote VTEP", "VLAN");
2580 } else
2581 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 2582
d62a17ae 2583 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
2584
2585 if (use_json) {
2586 json_object_object_add(json, "macs", json_mac);
2587 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2588 json, JSON_C_TO_STRING_PRETTY));
2589 json_object_free(json);
2590 }
cec2e17d 2591}
2592
2593/*
2594 * Display MACs for all VNIs (VTY command handler).
2595 */
cd233079
CS
2596void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
2597 u_char use_json)
cec2e17d 2598{
d62a17ae 2599 struct mac_walk_ctx wctx;
cd233079 2600 json_object *json = NULL;
cec2e17d 2601
cd233079
CS
2602 if (!EVPN_ENABLED(zvrf)) {
2603 if (use_json)
2604 vty_out(vty, "{}\n");
d62a17ae 2605 return;
cd233079
CS
2606 }
2607 if (use_json)
2608 json = json_object_new_object();
2609
d62a17ae 2610 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2611 wctx.vty = vty;
cd233079 2612 wctx.json = json;
d62a17ae 2613 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
2614
2615 if (use_json) {
2616 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2617 json, JSON_C_TO_STRING_PRETTY));
2618 json_object_free(json);
2619 }
cec2e17d 2620}
2621
2622/*
2623 * Display MACs for all VNIs (VTY command handler).
2624 */
d62a17ae 2625void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
2626 struct zebra_vrf *zvrf,
cd233079
CS
2627 struct in_addr vtep_ip,
2628 u_char use_json)
cec2e17d 2629{
d62a17ae 2630 struct mac_walk_ctx wctx;
cd233079 2631 json_object *json = NULL;
cec2e17d 2632
d62a17ae 2633 if (!EVPN_ENABLED(zvrf))
2634 return;
cd233079
CS
2635
2636 if (use_json)
2637 json = json_object_new_object();
2638
d62a17ae 2639 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2640 wctx.vty = vty;
2641 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
2642 wctx.r_vtep_ip = vtep_ip;
cd233079 2643 wctx.json = json;
d62a17ae 2644 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
cd233079
CS
2645
2646 if (use_json) {
2647 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2648 json, JSON_C_TO_STRING_PRETTY));
2649 json_object_free(json);
2650 }
cec2e17d 2651}
2652
2653/*
2654 * Display specific MAC for a VNI, if present (VTY command handler).
2655 */
d62a17ae 2656void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
2657 vni_t vni, struct ethaddr *macaddr)
cec2e17d 2658{
d62a17ae 2659 zebra_vni_t *zvni;
2660 zebra_mac_t *mac;
cec2e17d 2661
d62a17ae 2662 if (!EVPN_ENABLED(zvrf))
2663 return;
2664 zvni = zvni_lookup(zvrf, vni);
2665 if (!zvni) {
2666 vty_out(vty, "%% VNI %u does not exist\n", vni);
2667 return;
2668 }
2669 mac = zvni_mac_lookup(zvni, macaddr);
2670 if (!mac) {
2671 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
2672 vni);
2673 return;
2674 }
cec2e17d 2675
d62a17ae 2676 zvni_print_mac(mac, vty);
cec2e17d 2677}
2678
2679/*
2680 * Display MACs for a VNI from specific VTEP (VTY command handler).
2681 */
d62a17ae 2682void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079
CS
2683 vni_t vni, struct in_addr vtep_ip,
2684 u_char use_json)
cec2e17d 2685{
d62a17ae 2686 zebra_vni_t *zvni;
2687 u_int32_t num_macs;
2688 struct mac_walk_ctx wctx;
cd233079
CS
2689 json_object *json = NULL;
2690 json_object *json_mac = NULL;
cec2e17d 2691
d62a17ae 2692 if (!EVPN_ENABLED(zvrf))
2693 return;
2694 zvni = zvni_lookup(zvrf, vni);
2695 if (!zvni) {
cd233079
CS
2696 if (use_json)
2697 vty_out(vty, "{}\n");
2698 else
2699 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2700 return;
2701 }
2702 num_macs = hashcount(zvni->mac_table);
2703 if (!num_macs)
2704 return;
cd233079
CS
2705
2706 if (use_json) {
2707 json = json_object_new_object();
2708 json_mac = json_object_new_object();
2709 }
2710
d62a17ae 2711 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2712 wctx.zvni = zvni;
2713 wctx.vty = vty;
2714 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
2715 wctx.r_vtep_ip = vtep_ip;
cd233079 2716 wctx.json = json_mac;
d62a17ae 2717 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
cd233079
CS
2718
2719 if (use_json) {
2720 json_object_int_add(json, "numMacs", wctx.count);
2721 if (wctx.count)
2722 json_object_object_add(json, "macs", json_mac);
2723 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2724 json, JSON_C_TO_STRING_PRETTY));
2725 json_object_free(json);
2726 }
cec2e17d 2727}
2728
2729
2730/*
2731 * Display VNI information (VTY command handler).
2732 */
cd233079
CS
2733void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
2734 u_char use_json)
cec2e17d 2735{
d62a17ae 2736 zebra_vni_t *zvni;
cd233079
CS
2737 json_object *json = NULL;
2738 void *args[2];
cec2e17d 2739
d62a17ae 2740 if (!EVPN_ENABLED(zvrf))
2741 return;
2742 zvni = zvni_lookup(zvrf, vni);
2743 if (!zvni) {
cd233079
CS
2744 if (use_json)
2745 vty_out(vty, "{}\n");
2746 else
2747 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2748 return;
2749 }
cd233079
CS
2750 if (use_json)
2751 json = json_object_new_object();
2752 args[0] = vty;
2753 args[1] = json;
2754 zvni_print(zvni, (void *)args);
2755 if (use_json) {
2756 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2757 json, JSON_C_TO_STRING_PRETTY));
2758 json_object_free(json);
2759 }
cec2e17d 2760}
2761
2762/*
2763 * Display VNI hash table (VTY command handler).
2764 */
cd233079
CS
2765void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
2766 u_char use_json)
cec2e17d 2767{
d62a17ae 2768 u_int32_t num_vnis;
cd233079
CS
2769 json_object *json = NULL;
2770 void *args[2];
cec2e17d 2771
d62a17ae 2772 if (!EVPN_ENABLED(zvrf))
2773 return;
2774 num_vnis = hashcount(zvrf->vni_table);
cd233079
CS
2775 if (!num_vnis) {
2776 if (use_json)
2777 vty_out(vty, "{}\n");
d62a17ae 2778 return;
cd233079
CS
2779 }
2780 if (use_json) {
2781 json = json_object_new_object();
ddd16ed5
MK
2782 json_object_string_add(json, "advertiseGatewayMacip",
2783 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
2784 json_object_int_add(json, "numVnis", num_vnis);
2785 } else {
ddd16ed5
MK
2786 vty_out(vty, "Advertise gateway mac-ip: %s\n",
2787 zvrf->advertise_gw_macip ? "Yes" : "No");
cd233079
CS
2788 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
2789 vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s\n", "VNI",
2790 "VxLAN IF", "VTEP IP", "# MACs", "# ARPs",
2791 "# Remote VTEPs");
2792 }
2793 args[0] = vty;
2794 args[1] = json;
2795
2796 hash_iterate(zvrf->vni_table,
2797 (void (*)(struct hash_backet *, void *))zvni_print_hash,
2798 args);
2799
2800 if (use_json) {
2801 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2802 json, JSON_C_TO_STRING_PRETTY));
2803 json_object_free(json);
2804 }
cec2e17d 2805}
2806
2232a77c 2807/*
2808 * Handle neighbor delete (on a VLAN device / L3 interface) from the
2809 * kernel. This may result in either the neighbor getting deleted from
2810 * our database or being re-added to the kernel (if it is a valid
2811 * remote neighbor).
2812 */
d62a17ae 2813int zebra_vxlan_local_neigh_del(struct interface *ifp,
2814 struct interface *link_if, struct ipaddr *ip)
2815{
2816 zebra_vni_t *zvni;
2817 zebra_neigh_t *n;
2818 struct zebra_vrf *zvrf;
2819 char buf[INET6_ADDRSTRLEN];
b6938a74
MK
2820 char buf2[ETHER_ADDR_STRLEN];
2821 zebra_mac_t *zmac;
d62a17ae 2822
2823 /* We are only interested in neighbors on an SVI that resides on top
2824 * of a VxLAN bridge.
2825 */
2826 zvni = zvni_map_svi(ifp, link_if);
2827 if (!zvni)
2828 return 0;
2829 if (!zvni->vxlan_if) {
2830 zlog_err(
2831 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
2832 zvni->vni, zvni);
2833 return -1;
2834 }
2835
2836 if (IS_ZEBRA_DEBUG_VXLAN)
2837 zlog_debug("%u:Del neighbor %s intf %s(%u) -> VNI %u",
2838 ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)),
2839 ifp->name, ifp->ifindex, zvni->vni);
2840
2841 /* If entry doesn't exist, nothing to do. */
2842 n = zvni_neigh_lookup(zvni, ip);
2843 if (!n)
2844 return 0;
2845
b6938a74
MK
2846 zmac = zvni_mac_lookup(zvni, &n->emac);
2847 if (!zmac) {
2848 if (IS_ZEBRA_DEBUG_VXLAN)
2849 zlog_err(
2850 "%u: trying to del a neigh %s without a mac %s on VNI %u",
2851 ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)),
2852 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
2853 zvni->vni);
2854
2855 return 0;
2856 }
2857
d62a17ae 2858 /* If it is a remote entry, the kernel has aged this out or someone has
2859 * deleted it, it needs to be re-installed as Quagga is the owner.
2860 */
2861 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
2862 zvni_neigh_install(zvni, n);
2863 return 0;
2864 }
2865
2866 /* Locate VRF corresponding to interface. */
2867 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
2868 assert(zvrf);
2869
2870 /* Remove neighbor from BGP. */
b6938a74
MK
2871 if (IS_ZEBRA_NEIGH_ACTIVE(n))
2872 zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
2873 0);
d62a17ae 2874
2875 /* Delete this neighbor entry. */
2876 zvni_neigh_del(zvni, n);
2877
b6938a74
MK
2878 /* see if the AUTO mac needs to be deleted */
2879 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
f51d8a27 2880 && !listcount(zmac->neigh_list))
b6938a74
MK
2881 zvni_mac_del(zvni, zmac);
2882
d62a17ae 2883 return 0;
2232a77c 2884}
2885
2886/*
859b32c0
MK
2887 * Handle neighbor add or update (on a VLAN device / L3 interface)
2888 * from the kernel.
2232a77c 2889 */
d62a17ae 2890int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
2891 struct interface *link_if,
2892 struct ipaddr *ip,
2893 struct ethaddr *macaddr, u_int16_t state,
2894 u_char ext_learned)
2895{
2896 zebra_vni_t *zvni;
2897 zebra_neigh_t *n;
2898 struct zebra_vrf *zvrf;
b682f6de 2899 zebra_mac_t *zmac, *old_zmac;
d62a17ae 2900 char buf[ETHER_ADDR_STRLEN];
2901 char buf2[INET6_ADDRSTRLEN];
d62a17ae 2902
2903 /* We are only interested in neighbors on an SVI that resides on top
2904 * of a VxLAN bridge.
2905 */
2906 zvni = zvni_map_svi(ifp, link_if);
2907 if (!zvni)
2908 return 0;
2909
2910 /* Locate VRF corresponding to interface. */
2911 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
2912 assert(zvrf);
2913
2914 if (IS_ZEBRA_DEBUG_VXLAN)
2915 zlog_debug(
2916 "%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x "
2917 "%s-> VNI %u",
2918 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
2919 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
2920 ifp->ifindex, state, ext_learned ? "ext-learned " : "",
2921 zvni->vni);
2922
b6938a74
MK
2923 /* create a dummy MAC if the MAC is not already present */
2924 zmac = zvni_mac_lookup(zvni, macaddr);
2925 if (!zmac) {
2926 if (IS_ZEBRA_DEBUG_VXLAN)
2927 zlog_debug(
2928 "%u: AUTO MAC %s created for neigh %s on VNI %u",
2929 ifp->vrf_id,
2930 prefix_mac2str(macaddr, buf, sizeof(buf)),
2931 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
2932
2933 zmac = zvni_mac_add(zvni, macaddr);
2934 if (!zmac) {
2935 zlog_warn("%u:Failed to add MAC %s VNI %u",
2936 zvrf_id(zvrf),
2937 prefix_mac2str(macaddr, buf, sizeof(buf)),
2938 zvni->vni);
2939 return -1;
2940 }
2941
2942 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
2943 memset(&zmac->flags, 0, sizeof(u_int32_t));
2944 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
2945 }
2946
d62a17ae 2947 /* If same entry already exists, it might be a change or it might be a
2948 * move from remote to local.
2949 */
2950 n = zvni_neigh_lookup(zvni, ip);
2951 if (n) {
2952 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2953 if (memcmp(n->emac.octet, macaddr->octet,
ff8b7eb8 2954 ETH_ALEN)
d62a17ae 2955 == 0) {
b682f6de 2956 /* Update any params and return - client doesn't
2957 * care about a purely local change.
2958 */
2959 n->ifindex = ifp->ifindex;
2960 return 0;
57f7feb6 2961 }
b682f6de 2962
57f7feb6
MK
2963 /* If the MAC has changed,
2964 * need to issue a delete first
2965 * as this means a different MACIP route.
2966 * Also, need to do some unlinking/relinking.
2967 */
2968 zvni_neigh_send_del_to_client(zvrf, zvni->vni,
2969 &n->ip, &n->emac,
2970 0);
2971 old_zmac = zvni_mac_lookup(zvni, &n->emac);
2972 if (old_zmac) {
2973 listnode_delete(old_zmac->neigh_list,
2974 n);
2975 zvni_deref_ip2mac(zvni, old_zmac, 0);
b682f6de 2976 }
57f7feb6
MK
2977
2978 /* Set "local" forwarding info. */
2979 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2980 n->ifindex = ifp->ifindex;
2981 memcpy(&n->emac, macaddr, ETH_ALEN);
2982
2983 /* Link to new MAC */
2984 listnode_add_sort(zmac->neigh_list, n);
d62a17ae 2985 } else if (ext_learned)
2986 /* The neighbor is remote and that is the notification we got.
9d303b37 2987 */
d62a17ae 2988 {
859b32c0 2989 /* TODO: Evaluate if we need to do anything here. */
d62a17ae 2990 return 0;
2991 } else
2992 /* Neighbor has moved from remote to local. */
2993 {
2994 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
2995 n->r_vtep_ip.s_addr = 0;
b682f6de 2996 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2997 n->ifindex = ifp->ifindex;
d62a17ae 2998 }
2999 } else {
b6938a74 3000 n = zvni_neigh_add(zvni, ip, macaddr);
d62a17ae 3001 if (!n) {
3002 zlog_err(
3003 "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3004 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
3005 prefix_mac2str(macaddr, buf, sizeof(buf)),
3006 ifp->name, ifp->ifindex, zvni->vni);
3007 return -1;
3008 }
b682f6de 3009 /* Set "local" forwarding info. */
3010 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3011 n->ifindex = ifp->ifindex;
d62a17ae 3012 }
3013
b6938a74
MK
3014 /* Before we program this in BGP, we need to check if MAC is locally
3015 * learnt as well */
3016 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
3017 if (IS_ZEBRA_DEBUG_VXLAN)
3018 zlog_debug(
3019 "%u: Skipping neigh %s add to client as MAC %s is not local on VNI %u",
3020 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
3021 prefix_mac2str(macaddr, buf, sizeof(buf)),
3022 zvni->vni);
3023
3024 return 0;
3025 }
3026
b682f6de 3027 /* Inform BGP. */
3028 if (IS_ZEBRA_DEBUG_VXLAN)
3029 zlog_debug(
3030 "%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
3031 ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
3032 prefix_mac2str(macaddr, buf, sizeof(buf)),
3033 zvni->vni);
d62a17ae 3034
b682f6de 3035 ZEBRA_NEIGH_SET_ACTIVE(n);
3036 return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
3037 macaddr, 0);
2232a77c 3038}
3039
b682f6de 3040
2232a77c 3041/*
3042 * Handle message from client to delete a remote MACIP for a VNI.
3043 */
d62a17ae 3044int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
3045 struct zebra_vrf *zvrf)
3046{
3047 struct stream *s;
3048 vni_t vni;
3049 struct ethaddr macaddr;
3050 struct ipaddr ip;
3051 struct in_addr vtep_ip;
3052 zebra_vni_t *zvni;
3053 zebra_mac_t *mac;
3054 zebra_neigh_t *n;
3055 u_short l = 0, ipa_len;
3056 char buf[ETHER_ADDR_STRLEN];
3057 char buf1[INET6_ADDRSTRLEN];
b5ebdc9b 3058 struct interface *ifp = NULL;
3059 struct zebra_if *zif = NULL;
d62a17ae 3060
3061 s = client->ibuf;
3062
3063 while (l < length) {
3064 /* Obtain each remote MACIP and process. */
3065 /* Message contains VNI, followed by MAC followed by IP (if any)
3066 * followed by remote VTEP IP.
3067 */
3068 mac = NULL;
3069 n = NULL;
3070 memset(&ip, 0, sizeof(ip));
3071 vni = (vni_t)stream_getl(s);
ff8b7eb8 3072 stream_get(&macaddr.octet, s, ETH_ALEN);
d62a17ae 3073 ipa_len = stream_getl(s);
3074 if (ipa_len) {
3075 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
3076 : IPADDR_V6;
3077 stream_get(&ip.ip.addr, s, ipa_len);
3078 }
ff8b7eb8 3079 l += 4 + ETH_ALEN + 4 + ipa_len;
d62a17ae 3080 vtep_ip.s_addr = stream_get_ipv4(s);
3081 l += IPV4_MAX_BYTELEN;
3082
3083 if (IS_ZEBRA_DEBUG_VXLAN)
3084 zlog_debug(
3085 "%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
3086 zvrf_id(zvrf),
3087 prefix_mac2str(&macaddr, buf, sizeof(buf)),
3088 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
3089 inet_ntoa(vtep_ip),
3090 zebra_route_string(client->proto));
3091
3092 /* Locate VNI hash entry - expected to exist. */
3093 zvni = zvni_lookup(zvrf, vni);
3094 if (!zvni) {
3095 if (IS_ZEBRA_DEBUG_VXLAN)
3096 zlog_debug(
3097 "Failed to locate VNI hash upon remote MACIP DEL, "
3098 "VRF %d VNI %u",
3099 zvrf_id(zvrf), vni);
3100 continue;
3101 }
b5ebdc9b 3102 ifp = zvni->vxlan_if;
af026ae4 3103 if (!ifp) {
d62a17ae 3104 zlog_err(
3105 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
3106 vni, zvni);
3107 continue;
3108 }
b5ebdc9b 3109 zif = ifp->info;
3110
3111 /* If down or not mapped to a bridge, we're done. */
b682f6de 3112 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 3113 continue;
d62a17ae 3114
3115 /* The remote VTEP specified is normally expected to exist, but
3116 * it is
3117 * possible that the peer may delete the VTEP before deleting
3118 * any MACs
3119 * referring to the VTEP, in which case the handler (see
3120 * remote_vtep_del)
3121 * would have already deleted the MACs.
3122 */
3123 if (!zvni_vtep_find(zvni, &vtep_ip))
3124 continue;
3125
d62a17ae 3126 mac = zvni_mac_lookup(zvni, &macaddr);
3127 if (ipa_len)
3128 n = zvni_neigh_lookup(zvni, &ip);
3129
3130 if (n && !mac) {
3131 zlog_err(
3132 "failed to locate MAC %s for neigh %s in VRF %u VNI %u",
3133 prefix_mac2str(&macaddr, buf, sizeof(buf)),
3134 ipaddr2str(&ip, buf1, sizeof(buf1)),
3135 zvrf_id(zvrf), vni);
3136 continue;
3137 }
3138
3139 /* If the remote mac or neighbor doesn't exist there is nothing
3140 * more
3141 * to do. Otherwise, uninstall the entry and then remove it.
3142 */
3143 if (!mac && !n)
3144 continue;
3145
3146 /* Uninstall remote neighbor or MAC. */
3147 if (n) {
3148 /* When the MAC changes for an IP, it is possible the
3149 * client may
3150 * update the new MAC before trying to delete the "old"
3151 * neighbor
3152 * (as these are two different MACIP routes). Do the
3153 * delete only
3154 * if the MAC matches.
3155 */
3156 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
3157 && (memcmp(n->emac.octet, macaddr.octet,
ff8b7eb8 3158 ETH_ALEN)
d62a17ae 3159 == 0)) {
3160 zvni_neigh_uninstall(zvni, n);
3161 zvni_neigh_del(zvni, n);
3162 zvni_deref_ip2mac(zvni, mac, 1);
3163 }
3164 } else {
3165 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
b6938a74
MK
3166 zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
3167 mac);
3168
0a97666d 3169 if (list_isempty(mac->neigh_list)) {
d62a17ae 3170 zvni_mac_uninstall(zvni, mac, 0);
3171 zvni_mac_del(zvni, mac);
3172 } else
3173 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3174 }
3175 }
3176 }
3177
3178 return 0;
2232a77c 3179}
3180
3181/*
3182 * Handle message from client to add a remote MACIP for a VNI. This
3183 * could be just the add of a MAC address or the add of a neighbor
3184 * (IP+MAC).
3185 */
d62a17ae 3186int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
3187 struct zebra_vrf *zvrf)
3188{
3189 struct stream *s;
3190 vni_t vni;
3191 struct ethaddr macaddr;
3192 struct ipaddr ip;
3193 struct in_addr vtep_ip;
3194 zebra_vni_t *zvni;
3195 zebra_vtep_t *zvtep;
3196 zebra_mac_t *mac, *old_mac;
3197 zebra_neigh_t *n;
3198 u_short l = 0, ipa_len;
3199 int update_mac = 0, update_neigh = 0;
3200 char buf[ETHER_ADDR_STRLEN];
3201 char buf1[INET6_ADDRSTRLEN];
3202 u_char sticky;
b5ebdc9b 3203 struct interface *ifp = NULL;
3204 struct zebra_if *zif = NULL;
d62a17ae 3205
3206 assert(EVPN_ENABLED(zvrf));
3207
3208 s = client->ibuf;
3209
3210 while (l < length) {
3211 /* Obtain each remote MACIP and process. */
3212 /* Message contains VNI, followed by MAC followed by IP (if any)
3213 * followed by remote VTEP IP.
3214 */
3215 update_mac = update_neigh = 0;
3216 mac = NULL;
3217 n = NULL;
3218 memset(&ip, 0, sizeof(ip));
3219 vni = (vni_t)stream_getl(s);
ff8b7eb8 3220 stream_get(&macaddr.octet, s, ETH_ALEN);
d62a17ae 3221 ipa_len = stream_getl(s);
3222 if (ipa_len) {
3223 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
3224 : IPADDR_V6;
3225 stream_get(&ip.ip.addr, s, ipa_len);
3226 }
ff8b7eb8 3227 l += 4 + ETH_ALEN + 4 + ipa_len;
d62a17ae 3228 vtep_ip.s_addr = stream_get_ipv4(s);
3229 l += IPV4_MAX_BYTELEN;
3230
3231 /* Get 'sticky' flag. */
3232 sticky = stream_getc(s);
3233 l++;
3234
3235 if (IS_ZEBRA_DEBUG_VXLAN)
3236 zlog_debug(
3237 "%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
3238 zvrf_id(zvrf), sticky ? "sticky " : "",
3239 prefix_mac2str(&macaddr, buf, sizeof(buf)),
3240 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
3241 inet_ntoa(vtep_ip),
3242 zebra_route_string(client->proto));
3243
3244 /* Locate VNI hash entry - expected to exist. */
3245 zvni = zvni_lookup(zvrf, vni);
3246 if (!zvni) {
3247 zlog_err(
3248 "Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u",
3249 zvrf_id(zvrf), vni);
3250 continue;
3251 }
b5ebdc9b 3252 ifp = zvni->vxlan_if;
3253 if (!ifp) {
d62a17ae 3254 zlog_err(
3255 "VNI %u hash %p doesn't have intf upon remote MACIP add",
3256 vni, zvni);
3257 continue;
3258 }
b5ebdc9b 3259 zif = ifp->info;
3260
3261 /* If down or not mapped to a bridge, we're done. */
b682f6de 3262 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 3263 continue;
3264
3265 /* The remote VTEP specified should normally exist, but it is
3266 * possible
3267 * that when peering comes up, peer may advertise MACIP routes
3268 * before
3269 * advertising type-3 routes.
3270 */
3271 zvtep = zvni_vtep_find(zvni, &vtep_ip);
3272 if (!zvtep) {
3273 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
3274 zlog_err(
3275 "Failed to add remote VTEP, VRF %d VNI %u zvni %p",
3276 zvrf_id(zvrf), vni, zvni);
3277 continue;
3278 }
3279
3280 zvni_vtep_install(zvni, &vtep_ip);
3281 }
3282
3283 /* First, check if the remote MAC is unknown or has a change. If
3284 * so,
3285 * that needs to be updated first. Note that client could
3286 * install
3287 * MAC and MACIP separately or just install the latter.
3288 */
3289 mac = zvni_mac_lookup(zvni, &macaddr);
3290 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
3291 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
3292 != sticky
3293 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
3294 update_mac = 1;
3295
3296 if (update_mac) {
3297 if (!mac) {
3298 mac = zvni_mac_add(zvni, &macaddr);
3299 if (!mac) {
3300 zlog_warn(
3301 "%u:Failed to add MAC %s VNI %u Remote VTEP %s",
3302 zvrf_id(zvrf),
3303 prefix_mac2str(&macaddr, buf,
3304 sizeof(buf)),
3305 vni, inet_ntoa(vtep_ip));
3306 return -1;
3307 }
3308
3309 /* Is this MAC created for a MACIP? */
3310 if (ipa_len)
3311 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 3312 }
3313
3314 /* Set "auto" and "remote" forwarding info. */
3315 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
3316 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
3317 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
3318 mac->fwd_info.r_vtep_ip = vtep_ip;
3319
3320 if (sticky)
3321 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3322 else
3323 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3324
b6938a74
MK
3325 zvni_process_neigh_on_remote_mac_add(zvrf, zvni, mac);
3326
d62a17ae 3327 /* Install the entry. */
3328 zvni_mac_install(zvni, mac);
3329 }
3330
3331 /* If there is no IP, continue - after clearing AUTO flag of
3332 * MAC. */
3333 if (!ipa_len) {
3334 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3335 continue;
3336 }
3337
3338 /* Check if the remote neighbor itself is unknown or has a
3339 * change.
3340 * If so, create or update and then install the entry.
3341 */
3342 n = zvni_neigh_lookup(zvni, &ip);
3343 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
3344 || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0)
3345 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip))
3346 update_neigh = 1;
3347
3348 if (update_neigh) {
3349 if (!n) {
b6938a74 3350 n = zvni_neigh_add(zvni, &ip, &macaddr);
d62a17ae 3351 if (!n) {
3352 zlog_warn(
3353 "%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
3354 zvrf_id(zvrf),
3355 ipaddr2str(&ip, buf1,
3356 sizeof(buf1)),
3357 prefix_mac2str(&macaddr, buf,
3358 sizeof(buf)),
3359 vni, inet_ntoa(vtep_ip));
3360 return -1;
3361 }
3362
d62a17ae 3363 } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
3364 != 0) {
0a97666d
MK
3365 /* MAC change, update neigh list for old and new
3366 * mac */
d62a17ae 3367 old_mac = zvni_mac_lookup(zvni, &n->emac);
0a97666d
MK
3368 if (old_mac) {
3369 listnode_delete(old_mac->neigh_list, n);
d62a17ae 3370 zvni_deref_ip2mac(zvni, old_mac, 1);
0a97666d
MK
3371 }
3372 listnode_add_sort(mac->neigh_list, n);
b6938a74 3373 memcpy(&n->emac, &macaddr, ETH_ALEN);
d62a17ae 3374 }
3375
3376 /* Set "remote" forwarding info. */
3377 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3378 /* TODO: Handle MAC change. */
d62a17ae 3379 n->r_vtep_ip = vtep_ip;
3380 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3381
3382 /* Install the entry. */
3383 zvni_neigh_install(zvni, n);
3384 }
3385 }
3386
3387 return 0;
13d60d35 3388}
3389
3390/*
2232a77c 3391 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
3392 * us, this must involve a multihoming scenario. Treat this as implicit delete
3393 * of any prior local MAC.
13d60d35 3394 */
d62a17ae 3395int zebra_vxlan_check_del_local_mac(struct interface *ifp,
3396 struct interface *br_if,
3397 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 3398{
d62a17ae 3399 struct zebra_if *zif;
3400 struct zebra_vrf *zvrf;
3401 struct zebra_l2info_vxlan *vxl;
3402 vni_t vni;
3403 zebra_vni_t *zvni;
3404 zebra_mac_t *mac;
3405 char buf[ETHER_ADDR_STRLEN];
3406 u_char sticky;
13d60d35 3407
d62a17ae 3408 zif = ifp->info;
3409 assert(zif);
3410 vxl = &zif->l2info.vxl;
3411 vni = vxl->vni;
13d60d35 3412
d62a17ae 3413 /* Locate VRF corresponding to interface. */
3414 zvrf = vrf_info_lookup(ifp->vrf_id);
3415 assert(zvrf);
13d60d35 3416
d62a17ae 3417 /* If EVPN is not enabled, nothing to do. */
3418 if (!EVPN_ENABLED(zvrf))
3419 return 0;
13d60d35 3420
d62a17ae 3421 /* Locate hash entry; it is expected to exist. */
3422 zvni = zvni_lookup(zvrf, vni);
3423 if (!zvni)
3424 return 0;
13d60d35 3425
d62a17ae 3426 /* If entry doesn't exist, nothing to do. */
3427 mac = zvni_mac_lookup(zvni, macaddr);
3428 if (!mac)
3429 return 0;
13d60d35 3430
d62a17ae 3431 /* Is it a local entry? */
3432 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
3433 return 0;
13d60d35 3434
d62a17ae 3435 if (IS_ZEBRA_DEBUG_VXLAN)
3436 zlog_debug(
3437 "%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local",
3438 ifp->vrf_id, prefix_mac2str(macaddr, buf, sizeof(buf)),
3439 ifp->name, ifp->ifindex, vni);
13d60d35 3440
d62a17ae 3441 /* Remove MAC from BGP. */
3442 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
1a98c087
MK
3443 zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
3444 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
13d60d35 3445
b6938a74
MK
3446 /*
3447 * If there are no neigh associated with the mac delete the mac
3448 * else mark it as AUTO for forward reference
3449 */
3450 if (!listcount(mac->neigh_list)) {
3451 zvni_mac_del(zvni, mac);
3452 } else {
3453 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
3454 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3455 }
13d60d35 3456
d62a17ae 3457 return 0;
13d60d35 3458}
3459
3460/*
2232a77c 3461 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
3462 * This can happen because the remote MAC entries are also added as "dynamic",
3463 * so the kernel can ageout the entry.
13d60d35 3464 */
d62a17ae 3465int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
3466 struct interface *br_if,
3467 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 3468{
d62a17ae 3469 struct zebra_if *zif;
3470 struct zebra_vrf *zvrf;
3471 struct zebra_l2info_vxlan *vxl;
3472 vni_t vni;
3473 zebra_vni_t *zvni;
3474 zebra_mac_t *mac;
3475 char buf[ETHER_ADDR_STRLEN];
2232a77c 3476
d62a17ae 3477 zif = ifp->info;
3478 assert(zif);
3479 vxl = &zif->l2info.vxl;
3480 vni = vxl->vni;
2232a77c 3481
d62a17ae 3482 /* Locate VRF corresponding to interface. */
3483 zvrf = vrf_info_lookup(ifp->vrf_id);
3484 assert(zvrf);
13d60d35 3485
d62a17ae 3486 /* If EVPN is not enabled, nothing to do. */
3487 if (!EVPN_ENABLED(zvrf))
3488 return 0;
2232a77c 3489
d62a17ae 3490 /* Locate hash entry; it is expected to exist. */
3491 zvni = zvni_lookup(zvrf, vni);
3492 if (!zvni)
3493 return 0;
13d60d35 3494
d62a17ae 3495 /* If entry doesn't exist, nothing to do. */
3496 mac = zvni_mac_lookup(zvni, macaddr);
3497 if (!mac)
3498 return 0;
2232a77c 3499
d62a17ae 3500 /* Is it a remote entry? */
3501 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
3502 return 0;
2232a77c 3503
d62a17ae 3504 if (IS_ZEBRA_DEBUG_VXLAN)
3505 zlog_debug("%u:Del remote MAC %s intf %s(%u) VNI %u - readd",
3506 ifp->vrf_id,
3507 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
3508 ifp->ifindex, vni);
13d60d35 3509
d62a17ae 3510 zvni_mac_install(zvni, mac);
3511 return 0;
13d60d35 3512}
3513
3514/*
2232a77c 3515 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 3516 */
d62a17ae 3517int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
3518 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 3519{
d62a17ae 3520 zebra_vni_t *zvni;
3521 zebra_mac_t *mac;
3522 struct zebra_vrf *zvrf;
3523 char buf[ETHER_ADDR_STRLEN];
3524 u_char sticky;
13d60d35 3525
d62a17ae 3526 /* We are interested in MACs only on ports or (port, VLAN) that
3527 * map to a VNI.
3528 */
3529 zvni = zvni_map_vlan(ifp, br_if, vid);
3530 if (!zvni)
3531 return 0;
3532 if (!zvni->vxlan_if) {
3533 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
3534 zvni->vni, zvni);
3535 return -1;
3536 }
13d60d35 3537
d62a17ae 3538 if (IS_ZEBRA_DEBUG_VXLAN)
3539 zlog_debug("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u",
3540 ifp->vrf_id,
3541 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
3542 ifp->ifindex, vid, zvni->vni);
2232a77c 3543
d62a17ae 3544 /* If entry doesn't exist, nothing to do. */
3545 mac = zvni_mac_lookup(zvni, macaddr);
3546 if (!mac)
3547 return 0;
2232a77c 3548
d62a17ae 3549 /* Is it a local entry? */
3550 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
3551 return 0;
2232a77c 3552
d62a17ae 3553 /* Locate VRF corresponding to interface. */
3554 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
3555 assert(zvrf);
2232a77c 3556
d62a17ae 3557 /* Remove MAC from BGP. */
3558 sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
1a98c087
MK
3559 zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
3560 (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
2232a77c 3561
b6938a74
MK
3562 /* Update all the neigh entries associated with this mac */
3563 zvni_process_neigh_on_local_mac_del(zvrf, zvni, mac);
3564
3565 /*
3566 * If there are no neigh associated with the mac delete the mac
3567 * else mark it as AUTO for forward reference
3568 */
3569 if (!listcount(mac->neigh_list)) {
3570 zvni_mac_del(zvni, mac);
3571 } else {
3572 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
3573 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
3574 }
2232a77c 3575
d62a17ae 3576 return 0;
13d60d35 3577}
3578
3579/*
2232a77c 3580 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 3581 */
d62a17ae 3582int zebra_vxlan_local_mac_add_update(struct interface *ifp,
3583 struct interface *br_if,
3584 struct ethaddr *macaddr, vlanid_t vid,
3585 u_char sticky)
3586{
3587 zebra_vni_t *zvni;
3588 zebra_mac_t *mac;
3589 struct zebra_vrf *zvrf;
3590 char buf[ETHER_ADDR_STRLEN];
3591 int add = 1;
3592 u_char mac_sticky;
3593
3594 /* We are interested in MACs only on ports or (port, VLAN) that
3595 * map to a VNI.
3596 */
3597 zvni = zvni_map_vlan(ifp, br_if, vid);
3598 if (!zvni) {
3599 if (IS_ZEBRA_DEBUG_VXLAN)
3600 zlog_debug(
3601 "%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
3602 ifp->vrf_id, sticky ? "sticky " : "",
3603 prefix_mac2str(macaddr, buf, sizeof(buf)),
3604 ifp->name, ifp->ifindex, vid);
3605 return 0;
3606 }
3607
3608 if (!zvni->vxlan_if) {
3609 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
3610 zvni->vni, zvni);
3611 return -1;
3612 }
3613
3614 if (IS_ZEBRA_DEBUG_VXLAN)
3615 zlog_debug(
3616 "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
3617 ifp->vrf_id, sticky ? "sticky " : "",
3618 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
3619 ifp->ifindex, vid, zvni->vni);
3620
3621 /* If same entry already exists, nothing to do. */
3622 mac = zvni_mac_lookup(zvni, macaddr);
3623 if (mac) {
3624 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
3625 mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
3626 ? 1
3627 : 0;
3628
b6938a74 3629
b8ce75a5
MK
3630 /*
3631 * return if nothing has changed.
3632 * inform bgp if sticky flag has changed
3633 * update locally and do not inform bgp if local
3634 * parameters like interface has changed
3635 */
d62a17ae 3636 if (mac_sticky == sticky
3637 && mac->fwd_info.local.ifindex == ifp->ifindex
3638 && mac->fwd_info.local.vid == vid) {
3639 if (IS_ZEBRA_DEBUG_VXLAN)
3640 zlog_debug(
3641 "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
3642 "entry exists and has not changed ",
3643 ifp->vrf_id,
3644 sticky ? "sticky " : "",
3645 prefix_mac2str(macaddr, buf,
3646 sizeof(buf)),
3647 ifp->name, ifp->ifindex, vid,
3648 zvni->vni);
3649 return 0;
b6938a74 3650 } else if (mac_sticky != sticky) {
b8ce75a5 3651 add = 1;
b6938a74 3652 } else {
b8ce75a5
MK
3653 add = 0; /* This is an update of local
3654 interface. */
b6938a74 3655 }
421bb26a
MK
3656 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
3657 /*
3658 * If we have already learned the MAC as a remote sticky
3659 * MAC,
3660 * this is a operator error and we must log a warning
3661 */
8f4b98ee 3662 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
421bb26a
MK
3663 zlog_warn(
3664 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
3665 prefix_mac2str(macaddr, buf,
3666 sizeof(buf)),
3667 inet_ntoa(mac->fwd_info.r_vtep_ip),
3668 zvni->vni);
8f4b98ee
MK
3669 return 0;
3670 }
d62a17ae 3671 }
3672 }
3673
3674 /* Locate VRF corresponding to interface. */
3675 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
3676 assert(zvrf);
3677
3678 if (!mac) {
3679 mac = zvni_mac_add(zvni, macaddr);
3680 if (!mac) {
3681 zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u",
3682 ifp->vrf_id,
3683 prefix_mac2str(macaddr, buf, sizeof(buf)),
3684 ifp->name, ifp->ifindex, vid);
3685 return -1;
3686 }
3687 }
3688
3689 /* Set "local" forwarding info. */
3690 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
b6938a74 3691 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
d62a17ae 3692 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
b6938a74 3693 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
d62a17ae 3694 mac->fwd_info.local.ifindex = ifp->ifindex;
3695 mac->fwd_info.local.vid = vid;
3696
3697 if (sticky)
3698 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3699 else
3700 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
3701
3702 /* Inform BGP if required. */
b6938a74
MK
3703 if (add) {
3704 zvni_process_neigh_on_local_mac_add(zvrf, zvni, mac);
3705 return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr,
3706 sticky);
3707 }
d62a17ae 3708
3709 return 0;
2232a77c 3710}
13d60d35 3711
3712/*
3713 * Handle message from client to delete a remote VTEP for a VNI.
3714 */
d62a17ae 3715int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
3716 struct zebra_vrf *zvrf)
3717{
3718 struct stream *s;
3719 u_short l = 0;
3720 vni_t vni;
3721 struct in_addr vtep_ip;
3722 zebra_vni_t *zvni;
3723 zebra_vtep_t *zvtep;
b5ebdc9b 3724 struct interface *ifp;
3725 struct zebra_if *zif;
d62a17ae 3726
3727 s = client->ibuf;
3728
3729 while (l < length) {
3730 /* Obtain each remote VTEP and process. */
3731 vni = (vni_t)stream_getl(s);
3732 l += 4;
3733 vtep_ip.s_addr = stream_get_ipv4(s);
3734 l += IPV4_MAX_BYTELEN;
3735
3736 if (IS_ZEBRA_DEBUG_VXLAN)
3737 zlog_debug("%u:Recv VTEP_DEL %s VNI %u from %s",
3738 zvrf_id(zvrf), inet_ntoa(vtep_ip), vni,
3739 zebra_route_string(client->proto));
3740
3741 /* Locate VNI hash entry - expected to exist. */
3742 zvni = zvni_lookup(zvrf, vni);
3743 if (!zvni) {
3744 if (IS_ZEBRA_DEBUG_VXLAN)
3745 zlog_debug(
3746 "Failed to locate VNI hash upon remote VTEP DEL, "
3747 "VRF %d VNI %u",
3748 zvrf_id(zvrf), vni);
3749 continue;
3750 }
3751
b5ebdc9b 3752 ifp = zvni->vxlan_if;
3753 if (!ifp) {
b682f6de 3754 zlog_err("VNI %u hash %p doesn't have intf upon remote VTEP DEL",
3755 zvni->vni, zvni);
3756 continue;
b5ebdc9b 3757 }
3758 zif = ifp->info;
3759
3760 /* If down or not mapped to a bridge, we're done. */
b682f6de 3761 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 3762 continue;
3763
d62a17ae 3764 /* If the remote VTEP does not exist, there's nothing more to
3765 * do.
3766 * Otherwise, uninstall any remote MACs pointing to this VTEP
3767 * and
3768 * then, the VTEP entry itself and remove it.
3769 */
3770 zvtep = zvni_vtep_find(zvni, &vtep_ip);
3771 if (!zvtep)
3772 continue;
3773
3774 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
3775 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
3776 zvni_vtep_uninstall(zvni, &vtep_ip);
3777 zvni_vtep_del(zvni, zvtep);
3778 }
3779
3780 return 0;
13d60d35 3781}
3782
3783/*
3784 * Handle message from client to add a remote VTEP for a VNI.
3785 */
d62a17ae 3786int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
3787 struct zebra_vrf *zvrf)
3788{
3789 struct stream *s;
3790 u_short l = 0;
3791 vni_t vni;
3792 struct in_addr vtep_ip;
3793 zebra_vni_t *zvni;
b5ebdc9b 3794 struct interface *ifp;
3795 struct zebra_if *zif;
d62a17ae 3796
3797 assert(EVPN_ENABLED(zvrf));
3798
3799 s = client->ibuf;
3800
3801 while (l < length) {
3802 /* Obtain each remote VTEP and process. */
3803 vni = (vni_t)stream_getl(s);
3804 l += 4;
3805 vtep_ip.s_addr = stream_get_ipv4(s);
3806 l += IPV4_MAX_BYTELEN;
3807
3808 if (IS_ZEBRA_DEBUG_VXLAN)
3809 zlog_debug("%u:Recv VTEP_ADD %s VNI %u from %s",
3810 zvrf_id(zvrf), inet_ntoa(vtep_ip), vni,
3811 zebra_route_string(client->proto));
3812
3813 /* Locate VNI hash entry - expected to exist. */
3814 zvni = zvni_lookup(zvrf, vni);
3815 if (!zvni) {
3816 zlog_err(
3817 "Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u",
3818 zvrf_id(zvrf), vni);
3819 continue;
3820 }
b5ebdc9b 3821
3822 ifp = zvni->vxlan_if;
3823 if (!ifp) {
d62a17ae 3824 zlog_err(
3825 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
3826 zvni->vni, zvni);
3827 continue;
3828 }
3829
b5ebdc9b 3830 zif = ifp->info;
d62a17ae 3831
b5ebdc9b 3832 /* If down or not mapped to a bridge, we're done. */
b682f6de 3833 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
d62a17ae 3834 continue;
3835
b682f6de 3836 /* If the remote VTEP already exists,
3837 there's nothing more to do. */
b5ebdc9b 3838 if (zvni_vtep_find(zvni, &vtep_ip))
d62a17ae 3839 continue;
3840
3841 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
3842 zlog_err(
3843 "Failed to add remote VTEP, VRF %d VNI %u zvni %p",
3844 zvrf_id(zvrf), vni, zvni);
3845 continue;
3846 }
3847
3848 zvni_vtep_install(zvni, &vtep_ip);
3849 }
3850
3851 return 0;
13d60d35 3852}
3853
1a98c087
MK
3854/*
3855 * Add/Del gateway macip to evpn
3856 * g/w can be:
3857 * 1. SVI interface on a vlan aware bridge
3858 * 2. SVI interface on a vlan unaware bridge
3859 * 3. vrr interface (MACVLAN) associated to a SVI
3860 * We advertise macip routes for an interface if it is associated to VxLan vlan
3861 */
3862int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
3863 int add)
3864{
3865 struct ipaddr ip;
3866 struct ethaddr macaddr;
3867 zebra_vni_t *zvni = NULL;
3868 struct zebra_vrf *zvrf = NULL;
3869
3870 memset(&ip, 0, sizeof(struct ipaddr));
3871 memset(&macaddr, 0, sizeof(struct ethaddr));
3872
297a21b6
MK
3873 zvrf = vrf_info_lookup(ifp->vrf_id);
3874 if (!zvrf)
3875 return -1;
3876
3877 if (!EVPN_ENABLED(zvrf))
3878 return 0;
3879
1a98c087
MK
3880 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
3881 struct interface *svi_if =
3882 NULL; /* SVI corresponding to the MACVLAN */
3883 struct zebra_if *ifp_zif =
3884 NULL; /* Zebra daemon specific info for MACVLAN */
3885 struct zebra_if *svi_if_zif =
3886 NULL; /* Zebra daemon specific info for SVI*/
3887
3888 ifp_zif = ifp->info;
3889 if (!ifp_zif)
3890 return -1;
3891
71349e03
MK
3892 /*
3893 * for a MACVLAN interface the link represents the svi_if
3894 */
3895 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
3896 ifp_zif->link_ifindex);
1a98c087
MK
3897 if (!svi_if) {
3898 zlog_err("%u:MACVLAN %s(%u) without link information",
3899 ifp->vrf_id, ifp->name, ifp->ifindex);
3900 return -1;
3901 }
3902
3903 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
3904 /*
3905 * If it is a vlan aware bridge then the link gives the
3906 * bridge information
3907 */
3908 struct interface *svi_if_link = NULL;
3909
1a98c087 3910 svi_if_zif = svi_if->info;
71349e03
MK
3911 if (svi_if_zif) {
3912 svi_if_link = if_lookup_by_index_per_ns(
3913 zebra_ns_lookup(
3914 NS_DEFAULT),
3915 svi_if_zif->link_ifindex);
3916 zvni = zvni_map_svi(svi_if, svi_if_link);
3917 }
1a98c087 3918 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
3919 /*
3920 * If it is a vlan unaware bridge then svi is the bridge
3921 * itself
3922 */
1a98c087
MK
3923 zvni = zvni_map_svi(svi_if, svi_if);
3924 }
3925 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
3926 struct zebra_if *svi_if_zif =
71349e03
MK
3927 NULL; /* Zebra daemon specific info for SVI */
3928 struct interface *svi_if_link =
3929 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
3930
3931 svi_if_zif = ifp->info;
71349e03
MK
3932 svi_if_link =
3933 if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
3934 svi_if_zif->link_ifindex);
3935 if (svi_if_zif && svi_if_link)
3936 zvni = zvni_map_svi(ifp, svi_if_link);
1a98c087
MK
3937 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
3938 zvni = zvni_map_svi(ifp, ifp);
3939 }
3940
3941 if (!zvni)
3942 return 0;
3943
3944 if (!zvni->vxlan_if) {
3945 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
3946 zvni->vni, zvni);
3947 return -1;
3948 }
3949
1a98c087
MK
3950
3951 /* check if we are advertising gw macip routes */
3952 if (!advertise_gw_macip_enabled(zvrf, zvni))
3953 return 0;
3954
3955 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
3956
3957 if (p->family == AF_INET) {
3958 ip.ipa_type = IPADDR_V4;
3959 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
3960 sizeof(struct in_addr));
3961 } else if (p->family == AF_INET6) {
3962 ip.ipa_type = IPADDR_V6;
3963 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
3964 sizeof(struct in6_addr));
3965 }
3966
3967
3968 if (add)
3969 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
3970 else
3971 zvni_gw_macip_del(ifp, zvni, &ip);
3972
3973 return 0;
3974}
3975
2232a77c 3976/*
3977 * Handle SVI interface going down. At this point, this is a NOP since
3978 * the kernel deletes the neighbor entries on this SVI (if any).
3979 */
d62a17ae 3980int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 3981{
d62a17ae 3982 return 0;
2232a77c 3983}
3984
3985/*
3986 * Handle SVI interface coming up. This may or may not be of interest,
3987 * but if this is a SVI on a VxLAN bridge, we need to install any remote
3988 * neighbor entries (which will be used for EVPN ARP suppression).
3989 */
d62a17ae 3990int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 3991{
d62a17ae 3992 zebra_vni_t *zvni;
3993 struct neigh_walk_ctx n_wctx;
2232a77c 3994
d62a17ae 3995 zvni = zvni_map_svi(ifp, link_if);
3996 if (!zvni)
3997 return 0;
2232a77c 3998
d62a17ae 3999 if (!zvni->vxlan_if) {
4000 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
4001 zvni->vni, zvni);
4002 return -1;
4003 }
2232a77c 4004
d62a17ae 4005 if (IS_ZEBRA_DEBUG_VXLAN)
4006 zlog_debug("%u:SVI %s(%u) VNI %u is UP, installing neighbors",
4007 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni);
2232a77c 4008
d62a17ae 4009 /* Install any remote neighbors for this VNI. */
4010 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
4011 n_wctx.zvni = zvni;
4012 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx);
2232a77c 4013
d62a17ae 4014 return 0;
2232a77c 4015}
4016
13d60d35 4017/*
4018 * Handle VxLAN interface down - update BGP if required, and do
4019 * internal cleanup.
4020 */
d62a17ae 4021int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 4022{
d62a17ae 4023 struct zebra_if *zif;
4024 struct zebra_vrf *zvrf;
4025 zebra_vni_t *zvni;
4026 struct zebra_l2info_vxlan *vxl;
4027 vni_t vni;
13d60d35 4028
d62a17ae 4029 /* Locate VRF corresponding to interface. */
4030 zvrf = vrf_info_lookup(ifp->vrf_id);
4031 assert(zvrf);
13d60d35 4032
d62a17ae 4033 /* If EVPN is not enabled, nothing further to be done. */
4034 if (!EVPN_ENABLED(zvrf))
4035 return 0;
13d60d35 4036
d62a17ae 4037 zif = ifp->info;
4038 assert(zif);
4039 vxl = &zif->l2info.vxl;
4040 vni = vxl->vni;
13d60d35 4041
d62a17ae 4042 if (IS_ZEBRA_DEBUG_VXLAN)
4043 zlog_debug("%u:Intf %s(%u) VNI %u is DOWN", ifp->vrf_id,
4044 ifp->name, ifp->ifindex, vni);
13d60d35 4045
d62a17ae 4046 /* Locate hash entry; it is expected to exist. */
4047 zvni = zvni_lookup(zvrf, vni);
4048 if (!zvni) {
4049 zlog_err(
4050 "Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u",
4051 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4052 return -1;
4053 }
13d60d35 4054
d62a17ae 4055 assert(zvni->vxlan_if == ifp);
13d60d35 4056
d62a17ae 4057 /* Delete this VNI from BGP. */
4058 zvni_send_del_to_client(zvrf, zvni->vni);
13d60d35 4059
d62a17ae 4060 /* Free up all neighbors and MACs, if any. */
4061 zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
4062 zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
2232a77c 4063
d62a17ae 4064 /* Free up all remote VTEPs, if any. */
4065 zvni_vtep_del_all(zvni, 1);
13d60d35 4066
d62a17ae 4067 return 0;
13d60d35 4068}
4069
4070/*
4071 * Handle VxLAN interface up - update BGP if required.
4072 */
d62a17ae 4073int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 4074{
d62a17ae 4075 struct zebra_if *zif;
4076 struct zebra_vrf *zvrf;
4077 zebra_vni_t *zvni;
4078 struct zebra_l2info_vxlan *vxl;
4079 vni_t vni;
13d60d35 4080
d62a17ae 4081 /* Locate VRF corresponding to interface. */
4082 zvrf = vrf_info_lookup(ifp->vrf_id);
4083 assert(zvrf);
13d60d35 4084
d62a17ae 4085 /* If EVPN is not enabled, nothing further to be done. */
4086 if (!EVPN_ENABLED(zvrf))
4087 return 0;
13d60d35 4088
d62a17ae 4089 zif = ifp->info;
4090 assert(zif);
4091 vxl = &zif->l2info.vxl;
4092 vni = vxl->vni;
13d60d35 4093
d62a17ae 4094 if (IS_ZEBRA_DEBUG_VXLAN)
4095 zlog_debug("%u:Intf %s(%u) VNI %u is UP", ifp->vrf_id,
4096 ifp->name, ifp->ifindex, vni);
13d60d35 4097
d62a17ae 4098 /* Locate hash entry; it is expected to exist. */
4099 zvni = zvni_lookup(zvrf, vni);
4100 if (!zvni) {
4101 zlog_err(
4102 "Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u",
4103 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4104 return -1;
4105 }
13d60d35 4106
d62a17ae 4107 assert(zvni->vxlan_if == ifp);
13d60d35 4108
d62a17ae 4109 /* If part of a bridge, inform BGP about this VNI. */
4110 /* Also, read and populate local MACs and neighbors. */
4111 if (zif->brslave_info.br_if) {
4112 zvni_send_add_to_client(zvrf, zvni);
4113 zvni_read_mac_neigh(zvrf, zvni, ifp);
4114 }
13d60d35 4115
d62a17ae 4116 return 0;
13d60d35 4117}
4118
4119/*
4120 * Handle VxLAN interface delete. Locate and remove entry in hash table
4121 * and update BGP, if required.
4122 */
d62a17ae 4123int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 4124{
d62a17ae 4125 struct zebra_if *zif;
4126 struct zebra_vrf *zvrf;
4127 zebra_vni_t *zvni;
4128 struct zebra_l2info_vxlan *vxl;
4129 vni_t vni;
13d60d35 4130
d62a17ae 4131 /* Locate VRF corresponding to interface. */
4132 zvrf = vrf_info_lookup(ifp->vrf_id);
4133 assert(zvrf);
13d60d35 4134
d62a17ae 4135 /* If EVPN is not enabled, nothing further to be done. */
4136 if (!EVPN_ENABLED(zvrf))
4137 return 0;
13d60d35 4138
d62a17ae 4139 zif = ifp->info;
4140 assert(zif);
4141 vxl = &zif->l2info.vxl;
4142 vni = vxl->vni;
13d60d35 4143
d62a17ae 4144 if (IS_ZEBRA_DEBUG_VXLAN)
4145 zlog_debug("%u:Del VNI %u intf %s(%u)", ifp->vrf_id, vni,
4146 ifp->name, ifp->ifindex);
13d60d35 4147
d62a17ae 4148 /* Locate hash entry; it is expected to exist. */
4149 zvni = zvni_lookup(zvrf, vni);
4150 if (!zvni) {
4151 zlog_err(
4152 "Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u",
4153 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4154 return 0;
4155 }
13d60d35 4156
d62a17ae 4157 /* Delete VNI from BGP. */
4158 zvni_send_del_to_client(zvrf, zvni->vni);
13d60d35 4159
d62a17ae 4160 /* Free up all neighbors and MAC, if any. */
4161 zvni_neigh_del_all(zvrf, zvni, 0, 0, DEL_ALL_NEIGH);
4162 zvni_mac_del_all(zvrf, zvni, 0, 0, DEL_ALL_MAC);
2232a77c 4163
d62a17ae 4164 /* Free up all remote VTEPs, if any. */
4165 zvni_vtep_del_all(zvni, 0);
13d60d35 4166
d62a17ae 4167 /* Delete the hash entry. */
4168 if (zvni_del(zvrf, zvni)) {
4169 zlog_err("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u",
4170 zvni, ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni);
4171 return -1;
4172 }
13d60d35 4173
d62a17ae 4174 return 0;
13d60d35 4175}
4176
4177/*
4178 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
4179 */
d62a17ae 4180int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
4181{
4182 struct zebra_if *zif;
4183 struct zebra_vrf *zvrf;
4184 zebra_vni_t *zvni;
4185 struct zebra_l2info_vxlan *vxl;
4186 vni_t vni;
4187
4188 /* Locate VRF corresponding to interface. */
4189 zvrf = vrf_info_lookup(ifp->vrf_id);
4190 assert(zvrf);
4191
4192 /* If EVPN is not enabled, nothing further to be done. */
4193 if (!EVPN_ENABLED(zvrf))
4194 return 0;
4195
4196 zif = ifp->info;
4197 assert(zif);
4198 vxl = &zif->l2info.vxl;
4199 vni = vxl->vni;
4200
4201 /* Update VNI hash. */
4202 zvni = zvni_lookup(zvrf, vni);
4203 if (!zvni) {
4204 zlog_err(
4205 "Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u",
4206 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4207 return -1;
4208 }
4209
4210 if (IS_ZEBRA_DEBUG_VXLAN)
4211 zlog_debug(
4212 "%u:Update VNI %u intf %s(%u) VLAN %u local IP %s "
4213 "master %u chg 0x%x",
4214 ifp->vrf_id, vni, ifp->name, ifp->ifindex,
4215 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
4216 zif->brslave_info.bridge_ifindex, chgflags);
4217
af026ae4 4218 /* Removed from bridge? Cleanup and return */
d62a17ae 4219 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
4220 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
4221 /* Delete from client, remove all remote VTEPs */
4222 /* Also, free up all MACs and neighbors. */
4223 zvni_send_del_to_client(zvrf, zvni->vni);
4224 zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
4225 zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
4226 zvni_vtep_del_all(zvni, 1);
af026ae4 4227 return 0;
4228 }
4229
4230 /* Handle other changes. */
4231 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
d62a17ae 4232 /* Remove all existing local neighbors and MACs for this VNI
4233 * (including from BGP)
4234 */
4235 zvni_neigh_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC);
4236 zvni_mac_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC);
4237 }
4238
4239 zvni->local_vtep_ip = vxl->vtep_ip;
4240 zvni->vxlan_if = ifp;
4241
4242 /* Take further actions needed. Note that if we are here, there is a
4243 * change of interest.
4244 */
4245 /* If down or not mapped to a bridge, we're done. */
4246 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4247 return 0;
4248
4249 /* Inform BGP, if there is a change of interest. */
4250 if (chgflags
4251 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
4252 zvni_send_add_to_client(zvrf, zvni);
4253
4254 /* If there is a valid new master or a VLAN mapping change, read and
4255 * populate local MACs and neighbors. Also, reinstall any remote MACs
4256 * and neighbors for this VNI (based on new VLAN).
4257 */
4258 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
4259 zvni_read_mac_neigh(zvrf, zvni, ifp);
4260 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
4261 struct mac_walk_ctx m_wctx;
4262 struct neigh_walk_ctx n_wctx;
4263
4264 zvni_read_mac_neigh(zvrf, zvni, ifp);
4265
4266 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
4267 m_wctx.zvni = zvni;
4268 hash_iterate(zvni->mac_table, zvni_install_mac_hash, &m_wctx);
4269
4270 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
4271 n_wctx.zvni = zvni;
4272 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
4273 &n_wctx);
4274 }
4275
4276 return 0;
13d60d35 4277}
4278
4279/*
4280 * Handle VxLAN interface add.
4281 */
d62a17ae 4282int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 4283{
d62a17ae 4284 struct zebra_if *zif;
4285 struct zebra_vrf *zvrf;
4286 zebra_vni_t *zvni;
4287 struct zebra_l2info_vxlan *vxl;
4288 vni_t vni;
13d60d35 4289
d62a17ae 4290 /* Locate VRF corresponding to interface. */
4291 zvrf = vrf_info_lookup(ifp->vrf_id);
4292 assert(zvrf);
13d60d35 4293
d62a17ae 4294 /* If EVPN is not enabled, nothing further to be done. */
4295 if (!EVPN_ENABLED(zvrf))
4296 return 0;
13d60d35 4297
d62a17ae 4298 zif = ifp->info;
4299 assert(zif);
4300 vxl = &zif->l2info.vxl;
4301 vni = vxl->vni;
13d60d35 4302
d62a17ae 4303 if (IS_ZEBRA_DEBUG_VXLAN)
4304 zlog_debug(
4305 "%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u",
4306 ifp->vrf_id, vni, ifp->name, ifp->ifindex,
4307 vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
4308 zif->brslave_info.bridge_ifindex);
13d60d35 4309
d62a17ae 4310 /* Create or update VNI hash. */
4311 zvni = zvni_lookup(zvrf, vni);
4312 if (!zvni) {
4313 zvni = zvni_add(zvrf, vni);
4314 if (!zvni) {
4315 zlog_err(
4316 "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u",
4317 ifp->vrf_id, ifp->name, ifp->ifindex, vni);
4318 return -1;
4319 }
4320 }
13d60d35 4321
d62a17ae 4322 zvni->local_vtep_ip = vxl->vtep_ip;
4323 zvni->vxlan_if = ifp;
13d60d35 4324
d62a17ae 4325 /* If down or not mapped to a bridge, we're done. */
4326 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4327 return 0;
13d60d35 4328
d62a17ae 4329 /* Inform BGP */
4330 zvni_send_add_to_client(zvrf, zvni);
13d60d35 4331
d62a17ae 4332 /* Read and populate local MACs and neighbors */
4333 zvni_read_mac_neigh(zvrf, zvni, ifp);
2232a77c 4334
d62a17ae 4335 return 0;
13d60d35 4336}
4337
1a98c087
MK
4338/*
4339 * Handle message from client to enable/disable advertisement of g/w macip
4340 * routes
4341 */
4342int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
4343 u_short length, struct zebra_vrf *zvrf)
4344{
4345 struct stream *s;
4346 int advertise;
4347 vni_t vni = 0;
4348 zebra_vni_t *zvni = NULL;
b5ebdc9b 4349 struct interface *ifp = NULL;
1a98c087
MK
4350
4351 s = client->ibuf;
4352 advertise = stream_getc(s);
4353 vni = stream_get3(s);
4354
4355 if (!vni) {
4356 if (IS_ZEBRA_DEBUG_VXLAN)
4357 zlog_debug("%u:EVPN gateway macip Adv %s, currently %s",
4358 zvrf_id(zvrf),
4359 advertise ? "enabled" : "disabled",
4360 advertise_gw_macip_enabled(zvrf, NULL)
4361 ? "enabled"
4362 : "disabled");
4363
4364 if (zvrf->advertise_gw_macip == advertise)
4365 return 0;
4366
4367 zvrf->advertise_gw_macip = advertise;
4368
4369 if (advertise_gw_macip_enabled(zvrf, zvni))
4370 hash_iterate(zvrf->vni_table,
4371 zvni_gw_macip_add_for_vni_hash, zvrf);
4372 else
4373 hash_iterate(zvrf->vni_table,
4374 zvni_gw_macip_del_for_vni_hash, zvrf);
4375
4376 } else {
4377 struct zebra_if *zif = NULL;
4378 struct zebra_l2info_vxlan zl2_info;
4379 struct interface *vlan_if = NULL;
4380 struct interface *vrr_if = NULL;
4381
4382 if (IS_ZEBRA_DEBUG_VXLAN)
4383 zlog_debug(
4384 "%u:EVPN gateway macip Adv %s on VNI %d , currently %s",
4385 zvrf_id(zvrf),
4386 advertise ? "enabled" : "disabled", vni,
4387 advertise_gw_macip_enabled(zvrf, zvni)
4388 ? "enabled"
4389 : "disabled");
4390
4391 zvni = zvni_lookup(zvrf, vni);
4392 if (!zvni)
4393 return 0;
4394
4395 if (zvni->advertise_gw_macip == advertise)
4396 return 0;
4397
4398 zvni->advertise_gw_macip = advertise;
4399
b5ebdc9b 4400 ifp = zvni->vxlan_if;
4401 if (!ifp)
4402 return 0;
4403
4404 zif = ifp->info;
4405
4406 /* If down or not mapped to a bridge, we're done. */
b682f6de 4407 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
b5ebdc9b 4408 return 0;
4409
1a98c087
MK
4410 zl2_info = zif->l2info.vxl;
4411
4412 vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
4413 zif->brslave_info.br_if);
4414 if (!vlan_if)
4415 return 0;
4416
4417 if (advertise_gw_macip_enabled(zvrf, zvni)) {
4418 /* Add primary SVI MAC-IP */
4419 zvni_add_macip_for_intf(vlan_if, zvni);
4420
4421 /* Add VRR MAC-IP - if any*/
4422 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
4423 if (vrr_if)
4424 zvni_add_macip_for_intf(vrr_if, zvni);
4425 } else {
4426 /* Del primary MAC-IP */
4427 zvni_del_macip_for_intf(vlan_if, zvni);
4428
4429 /* Del VRR MAC-IP - if any*/
4430 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
4431 if (vrr_if)
4432 zvni_del_macip_for_intf(vrr_if, zvni);
4433 }
4434 }
4435
4436 return 0;
4437}
4438
4439
13d60d35 4440/*
4441 * Handle message from client to learn (or stop learning) about VNIs and MACs.
4442 * When enabled, the VNI hash table will be built and MAC FDB table read;
4443 * when disabled, the entries should be deleted and remote VTEPs and MACs
4444 * uninstalled from the kernel.
4445 */
d62a17ae 4446int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock,
4447 u_short length, struct zebra_vrf *zvrf)
13d60d35 4448{
d62a17ae 4449 struct stream *s;
4450 int advertise;
13d60d35 4451
d62a17ae 4452 s = client->ibuf;
4453 advertise = stream_getc(s);
13d60d35 4454
d62a17ae 4455 if (IS_ZEBRA_DEBUG_VXLAN)
4456 zlog_debug("%u:EVPN VNI Adv %s, currently %s", zvrf_id(zvrf),
4457 advertise ? "enabled" : "disabled",
4458 EVPN_ENABLED(zvrf) ? "enabled" : "disabled");
13d60d35 4459
d62a17ae 4460 if (zvrf->advertise_all_vni == advertise)
4461 return 0;
13d60d35 4462
d62a17ae 4463 zvrf->advertise_all_vni = advertise;
4464 if (EVPN_ENABLED(zvrf)) {
4465 /* Build VNI hash table and inform BGP. */
4466 zvni_build_hash_table(zvrf);
2232a77c 4467
1a98c087
MK
4468 /* Add all SVI (L3 GW) MACs to BGP*/
4469 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
4470 zvrf);
4471
d62a17ae 4472 /* Read the MAC FDB */
4473 macfdb_read(zvrf->zns);
2232a77c 4474
d62a17ae 4475 /* Read neighbors */
4476 neigh_read(zvrf->zns);
4477 } else {
4478 /* Cleanup VTEPs for all VNIs - uninstall from
4479 * kernel and free entries.
4480 */
4481 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
4482 }
13d60d35 4483
d62a17ae 4484 return 0;
13d60d35 4485}
4486
4487/*
4488 * Allocate VNI hash table for this VRF and do other initialization.
4489 * NOTE: Currently supported only for default VRF.
4490 */
d62a17ae 4491void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 4492{
d62a17ae 4493 if (!zvrf)
4494 return;
4495 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
4496 "Zebra VRF VNI Table");
13d60d35 4497}
4498
4499/* Close all VNI handling */
d62a17ae 4500void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 4501{
d62a17ae 4502 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9b67b514 4503 hash_free(zvrf->vni_table);
13d60d35 4504}