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