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