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